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 <ws_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 packets_bar_update();
642 g_timer_start(prog_timer);
646 if (cf->state == FILE_READ_ABORTED) {
647 /* Well, the user decided to exit Wireshark. Break out of the
648 loop, and let the code below (which is called even if there
649 aren't any packets left to read) exit. */
650 is_read_aborted = TRUE;
654 /* Well, the user decided to abort the read. He/She will be warned and
655 it might be enough for him/her to work with the already loaded
657 This is especially true for very large capture files, where you don't
658 want to wait loading the whole file (which may last minutes or even
659 hours even on fast machines) just to see that it was the wrong file. */
662 read_packet(cf, dfcode, &edt, cinfo, data_offset);
665 CATCH(OutOfMemoryError) {
666 simple_message_box(ESD_TYPE_ERROR, NULL,
667 "More information and workarounds can be found at\n"
668 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
669 "Sorry, but Wireshark has run out of memory and has to terminate now.");
671 /* Could we close the current capture and free up memory from that? */
673 /* we have to terminate, as we cannot recover from the memory error */
679 /* Free the display name */
682 /* Cleanup and release all dfilter resources */
683 if (dfcode != NULL) {
684 dfilter_free(dfcode);
687 epan_dissect_cleanup(&edt);
689 /* We're done reading the file; destroy the progress bar if it was created. */
691 destroy_progress_dlg(progbar);
692 g_timer_destroy(prog_timer);
694 /* We're done reading sequentially through the file. */
695 cf->state = FILE_READ_DONE;
697 /* Close the sequential I/O side, to free up memory it requires. */
698 wtap_sequential_close(cf->wth);
700 /* Allow the protocol dissectors to free up memory that they
701 * don't need after the sequential run-through of the packets. */
702 postseq_cleanup_all_protocols();
704 /* compute the time it took to load the file */
705 compute_elapsed(cf, &start_time);
707 /* Set the file encapsulation type now; we don't know what it is until
708 we've looked at all the packets, as we don't know until then whether
709 there's more than one type (and thus whether it's
710 WTAP_ENCAP_PER_PACKET). */
711 cf->lnk_t = wtap_file_encap(cf->wth);
713 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
718 cf_callback_invoke(cf_cb_file_reload_finished, cf);
720 cf_callback_invoke(cf_cb_file_read_finished, cf);
722 /* If we have any displayed packets to select, select the first of those
723 packets by making the first row the selected row. */
724 if (cf->first_displayed != 0) {
725 packet_list_select_first_row();
728 if (is_read_aborted) {
730 * Well, the user decided to exit Wireshark while reading this *offline*
731 * capture file (Live captures are handled by something like
732 * cf_continue_tail). Clean up accordingly.
735 return CF_READ_ABORTED;
739 simple_message_box(ESD_TYPE_WARN, NULL,
740 "The remaining packets in the file were discarded.\n"
742 "As a lot of packets from the original file will be missing,\n"
743 "remember to be careful when saving the current content to a file.\n",
744 "File loading was cancelled.");
745 return CF_READ_ERROR;
749 /* Put up a message box noting that the read failed somewhere along
750 the line. Don't throw out the stuff we managed to read, though,
752 cfile_read_failure_alert_box(NULL, err, err_info);
753 return CF_READ_ERROR;
760 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
763 volatile int newly_displayed_packets = 0;
766 gboolean create_proto_tree;
770 /* Compile the current display filter.
771 * We assume this will not fail since cf->dfilter is only set in
772 * cf_filter IFF the filter was valid.
774 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
775 g_assert(!cf->dfilter || (compiled && dfcode));
777 /* Get the union of the flags for all tap listeners. */
778 tap_flags = union_of_tap_listener_flags();
781 * Determine whether we need to create a protocol tree.
784 * we're going to apply a display filter;
786 * one of the tap listeners is going to apply a filter;
788 * one of the tap listeners requires a protocol tree;
790 * a postdissector wants field values or protocols on
794 (dfcode != NULL || have_filtering_tap_listeners() ||
795 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
799 packet_list_check_end();
800 /* Don't freeze/thaw the list when doing live capture */
801 /*packet_list_freeze();*/
803 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
805 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
808 gint64 data_offset = 0;
811 /* If any tap listeners require the columns, construct them. */
812 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
814 while (to_read != 0) {
815 wtap_cleareof(cf->wth);
816 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
819 if (cf->state == FILE_READ_ABORTED) {
820 /* Well, the user decided to exit Wireshark. Break out of the
821 loop, and let the code below (which is called even if there
822 aren't any packets left to read) exit. */
825 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
826 newly_displayed_packets++;
831 CATCH(OutOfMemoryError) {
832 simple_message_box(ESD_TYPE_ERROR, NULL,
833 "More information and workarounds can be found at\n"
834 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
835 "Sorry, but Wireshark has run out of memory and has to terminate now.");
837 /* Could we close the current capture and free up memory from that? */
838 return CF_READ_ABORTED;
840 /* we have to terminate, as we cannot recover from the memory error */
846 /* Update the file encapsulation; it might have changed based on the
847 packets we've read. */
848 cf->lnk_t = wtap_file_encap(cf->wth);
850 /* Cleanup and release all dfilter resources */
851 if (dfcode != NULL) {
852 dfilter_free(dfcode);
855 epan_dissect_cleanup(&edt);
857 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
858 cf->count, cf->state, *err);*/
860 /* Don't freeze/thaw the list when doing live capture */
861 /*packet_list_thaw();*/
862 /* With the new packet list the first packet
863 * isn't automatically selected.
865 if (!cf->current_frame)
866 packet_list_select_first_row();
868 /* moving to the end of the packet list - if the user requested so and
869 we have some new packets. */
870 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
871 packet_list_moveto_end();
873 if (cf->state == FILE_READ_ABORTED) {
874 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
875 so that our caller can kill off the capture child process;
876 this will cause an EOF on the pipe from the child, so
877 "cf_finish_tail()" will be called, and it will clean up
879 return CF_READ_ABORTED;
880 } else if (*err != 0) {
881 /* We got an error reading the capture file.
882 XXX - pop up a dialog box instead? */
883 if (err_info != NULL) {
884 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
885 wtap_strerror(*err), cf->filename, err_info);
888 g_warning("Error \"%s\" while reading \"%s\"",
889 wtap_strerror(*err), cf->filename);
891 return CF_READ_ERROR;
897 cf_fake_continue_tail(capture_file *cf) {
898 cf->state = FILE_READ_DONE;
902 cf_finish_tail(capture_file *cf, int *err)
909 gboolean create_proto_tree;
913 /* Compile the current display filter.
914 * We assume this will not fail since cf->dfilter is only set in
915 * cf_filter IFF the filter was valid.
917 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
918 g_assert(!cf->dfilter || (compiled && dfcode));
920 /* Get the union of the flags for all tap listeners. */
921 tap_flags = union_of_tap_listener_flags();
923 /* If any tap listeners require the columns, construct them. */
924 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
927 * Determine whether we need to create a protocol tree.
930 * we're going to apply a display filter;
932 * one of the tap listeners is going to apply a filter;
934 * one of the tap listeners requires a protocol tree;
936 * a postdissector wants field values or protocols on
940 (dfcode != NULL || have_filtering_tap_listeners() ||
941 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
943 if (cf->wth == NULL) {
945 return CF_READ_ERROR;
948 packet_list_check_end();
949 /* Don't freeze/thaw the list when doing live capture */
950 /*packet_list_freeze();*/
952 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
954 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
955 if (cf->state == FILE_READ_ABORTED) {
956 /* Well, the user decided to abort the read. Break out of the
957 loop, and let the code below (which is called even if there
958 aren't any packets left to read) exit. */
961 read_packet(cf, dfcode, &edt, cinfo, data_offset);
964 /* Cleanup and release all dfilter resources */
965 if (dfcode != NULL) {
966 dfilter_free(dfcode);
969 epan_dissect_cleanup(&edt);
971 /* Don't freeze/thaw the list when doing live capture */
972 /*packet_list_thaw();*/
974 if (cf->state == FILE_READ_ABORTED) {
975 /* Well, the user decided to abort the read. We're only called
976 when the child capture process closes the pipe to us (meaning
977 it's probably exited), so we can just close the capture
978 file; we return CF_READ_ABORTED so our caller can do whatever
979 is appropriate when that happens. */
981 return CF_READ_ABORTED;
984 if (auto_scroll_live && cf->count != 0)
985 packet_list_moveto_end();
987 /* We're done reading sequentially through the file. */
988 cf->state = FILE_READ_DONE;
990 /* We're done reading sequentially through the file; close the
991 sequential I/O side, to free up memory it requires. */
992 wtap_sequential_close(cf->wth);
994 /* Allow the protocol dissectors to free up memory that they
995 * don't need after the sequential run-through of the packets. */
996 postseq_cleanup_all_protocols();
998 /* Update the file encapsulation; it might have changed based on the
999 packets we've read. */
1000 cf->lnk_t = wtap_file_encap(cf->wth);
1002 /* Update the details in the file-set dialog, as the capture file
1003 * has likely grown since we first stat-ed it */
1004 fileset_update_file(cf->filename);
1007 /* We got an error reading the capture file.
1008 XXX - pop up a dialog box? */
1009 if (err_info != NULL) {
1010 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
1011 wtap_strerror(*err), cf->filename, err_info);
1014 g_warning("Error \"%s\" while reading \"%s\"",
1015 wtap_strerror(*err), cf->filename);
1017 return CF_READ_ERROR;
1022 #endif /* HAVE_LIBPCAP */
1025 cf_get_display_name(capture_file *cf)
1029 /* Return a name to use in displays */
1030 if (!cf->is_tempfile) {
1031 /* Get the last component of the file name, and use that. */
1033 displayname = g_filename_display_basename(cf->filename);
1035 displayname=g_strdup("(No file)");
1038 /* The file we read is a temporary file from a live capture or
1039 a merge operation; we don't mention its name, but, if it's
1040 from a capture, give the source of the capture. */
1042 displayname = g_strdup(cf->source);
1044 displayname = g_strdup("(Untitled)");
1050 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1056 cf->source = g_strdup(source);
1058 cf->source = g_strdup("");
1062 const gchar *cf_get_tempfile_source(capture_file *cf) {
1070 /* XXX - use a macro instead? */
1072 cf_get_packet_count(capture_file *cf)
1077 /* XXX - use a macro instead? */
1079 cf_is_tempfile(capture_file *cf)
1081 return cf->is_tempfile;
1084 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1086 cf->is_tempfile = is_tempfile;
1090 /* XXX - use a macro instead? */
1091 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1093 cf->drops_known = drops_known;
1096 /* XXX - use a macro instead? */
1097 void cf_set_drops(capture_file *cf, guint32 drops)
1102 /* XXX - use a macro instead? */
1103 gboolean cf_get_drops_known(capture_file *cf)
1105 return cf->drops_known;
1108 /* XXX - use a macro instead? */
1109 guint32 cf_get_drops(capture_file *cf)
1114 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1116 cf->rfcode = rfcode;
1120 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1121 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1122 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1126 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1127 &cf->ref, cf->prev_dis);
1128 cf->prev_cap = fdata;
1130 if (dfcode != NULL) {
1131 epan_dissect_prime_with_dfilter(edt, dfcode);
1134 /* Prepare coloring rules, this ensures that display filter rules containing
1135 * frame.color_rule references are still processed.
1136 * TODO: actually detect that situation or maybe apply other optimizations? */
1137 if (edt->tree && color_filters_used()) {
1138 color_filters_prime_edt(edt);
1139 fdata->flags.need_colorize = 1;
1143 if (!fdata->flags.visited) {
1144 /* This is the first pass, so prime the epan_dissect_t with the
1145 hfids postdissectors want on the first pass. */
1146 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1149 /* Dissect the frame. */
1150 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1152 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1153 if (dfcode != NULL) {
1154 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1156 if (fdata->flags.passed_dfilter) {
1157 /* This frame passed the display filter but it may depend on other
1158 * (potentially not displayed) frames. Find those frames and mark them
1161 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1164 fdata->flags.passed_dfilter = 1;
1166 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1167 cf->displayed_count++;
1169 if (add_to_packet_list) {
1170 /* We fill the needed columns from new_packet_list */
1171 row = packet_list_append(cinfo, fdata);
1174 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1176 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1177 cf->prev_dis = fdata;
1179 /* If we haven't yet seen the first frame, this is it. */
1180 if (cf->first_displayed == 0)
1181 cf->first_displayed = fdata->num;
1183 /* This is the last frame we've seen so far. */
1184 cf->last_displayed = fdata->num;
1187 epan_dissect_reset(edt);
1191 /* read in a new packet */
1192 /* returns the row of the new packet in the packet list or -1 if not displayed */
1194 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1195 column_info *cinfo, gint64 offset)
1197 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1198 const guint8 *buf = wtap_buf_ptr(cf->wth);
1202 gboolean passed = TRUE;
1205 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1206 it's not already there.
1207 XXX - yes, this is O(N), so if every packet had a different
1208 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1209 there are probably going to be a small number of encapsulation types
1211 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1213 /* The frame number of this packet is one more than the count of
1214 frames in the file so far. */
1215 framenum = cf->count + 1;
1217 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1220 epan_dissect_t rf_edt;
1222 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1223 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1224 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1225 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1226 epan_dissect_cleanup(&rf_edt);
1230 /* This does a shallow copy of fdlocal, which is good enough. */
1231 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1234 if (phdr->opt_comment != NULL)
1235 cf->packet_comment_count++;
1236 cf->f_datalen = offset + fdlocal.cap_len;
1238 if (!cf->redissecting) {
1239 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1240 cinfo, phdr, buf, TRUE);
1248 typedef struct _callback_data_t {
1251 GTimeVal start_time;
1259 merge_callback(merge_event event, int num _U_,
1260 const merge_in_file_t in_files[], const guint in_file_count,
1264 callback_data_t *cb_data = (callback_data_t*) data;
1266 g_assert(cb_data != NULL);
1270 case MERGE_EVENT_INPUT_FILES_OPENED:
1274 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1278 case MERGE_EVENT_READY_TO_MERGE:
1279 /* Get the sum of the sizes of all the files. */
1280 for (i = 0; i < in_file_count; i++)
1281 cb_data->f_len += in_files[i].size;
1283 cb_data->prog_timer = g_timer_new();
1284 g_timer_start(cb_data->prog_timer);
1286 g_get_current_time(&cb_data->start_time);
1289 case MERGE_EVENT_PACKET_WAS_READ:
1291 gint64 data_offset = 0;
1293 /* Get the sum of the data offsets in all of the files. */
1295 for (i = 0; i < in_file_count; i++)
1296 data_offset += in_files[i].data_offset;
1298 /* Create the progress bar if necessary.
1299 We check on every iteration of the loop, so that it takes no
1300 longer than the standard time to create it (otherwise, for a
1301 large file, we might take considerably longer than that standard
1302 time in order to get to the next progress bar step). */
1303 if (cb_data->progbar == NULL) {
1304 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1305 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1309 * Update the progress bar, but do it only after
1310 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1311 * and packets_bar_update will likely trigger UI paint events, which
1312 * might take a while depending on the platform and display. Reset
1313 * our timer *after* painting.
1315 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1317 gint64 file_pos = 0;
1318 /* Get the sum of the seek positions in all of the files. */
1319 for (i = 0; i < in_file_count; i++)
1320 file_pos += wtap_read_so_far(in_files[i].wth);
1322 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1323 if (progbar_val > 1.0f) {
1324 /* Some file probably grew while we were reading it.
1325 That "shouldn't happen", so we'll just clip the progress
1330 if (cb_data->progbar != NULL) {
1331 gchar status_str[100];
1332 g_snprintf(status_str, sizeof(status_str),
1333 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1334 file_pos / 1024, cb_data->f_len / 1024);
1335 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1337 g_timer_start(cb_data->prog_timer);
1342 case MERGE_EVENT_DONE:
1343 /* We're done merging the files; destroy the progress bar if it was created. */
1344 if (cb_data->progbar != NULL)
1345 destroy_progress_dlg(cb_data->progbar);
1346 g_timer_destroy(cb_data->prog_timer);
1350 return cb_data->stop_flag;
1356 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1357 int in_file_count, char *const *in_filenames,
1358 int file_type, gboolean do_append)
1361 gchar *err_info = NULL;
1363 guint32 err_framenum;
1364 merge_result status;
1365 merge_progress_callback_t cb;
1366 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1368 /* prepare our callback routine */
1369 cb_data->pd_window = pd_window;
1370 cb.callback_func = merge_callback;
1373 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1375 /* merge the files */
1376 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1377 (const char *const *) in_filenames,
1378 in_file_count, do_append,
1379 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1380 "Wireshark", &cb, &err, &err_info,
1381 &err_fileno, &err_framenum);
1389 case MERGE_USER_ABORTED:
1390 /* this isn't really an error, though we will return CF_ERROR later */
1393 case MERGE_ERR_CANT_OPEN_INFILE:
1394 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1397 case MERGE_ERR_CANT_OPEN_OUTFILE:
1398 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1401 case MERGE_ERR_CANT_READ_INFILE:
1402 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1405 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1406 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1407 err_framenum, in_filenames[err_fileno]);
1410 case MERGE_ERR_CANT_WRITE_OUTFILE:
1411 cfile_write_failure_alert_box(in_filenames[err_fileno],
1412 *out_filenamep, err, err_info,
1413 err_framenum, file_type);
1416 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1417 cfile_close_failure_alert_box(*out_filenamep, err);
1421 simple_error_message_box("Unknown merge_files error %d", status);
1425 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1427 if (status != MERGE_OK) {
1428 /* Callers aren't expected to treat an error or an explicit abort
1429 differently - we put up error dialogs ourselves, so they don't
1437 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1439 const char *filter_new = dftext ? dftext : "";
1440 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1443 GTimeVal start_time;
1445 /* if new filter equals old one, do nothing unless told to do so */
1446 if (!force && strcmp(filter_new, filter_old) == 0) {
1452 if (dftext == NULL) {
1453 /* The new filter is an empty filter (i.e., display all packets).
1454 * so leave dfcode==NULL
1458 * We have a filter; make a copy of it (as we'll be saving it),
1459 * and try to compile it.
1461 dftext = g_strdup(dftext);
1462 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1463 /* The attempt failed; report an error. */
1464 simple_message_box(ESD_TYPE_ERROR, NULL,
1465 "See the help for a description of the display filter syntax.",
1466 "\"%s\" isn't a valid display filter: %s",
1474 if (dfcode == NULL) {
1475 /* Yes - free the filter text, and set it to null. */
1481 /* We have a valid filter. Replace the current filter. */
1482 g_free(cf->dfilter);
1483 cf->dfilter = dftext;
1484 g_get_current_time(&start_time);
1487 /* Now rescan the packet list, applying the new filter, but not
1488 throwing away information constructed on a previous pass. */
1489 if (cf->state != FILE_CLOSED) {
1490 if (dftext == NULL) {
1491 rescan_packets(cf, "Resetting", "Filter", FALSE);
1493 rescan_packets(cf, "Filtering", dftext, FALSE);
1497 /* Cleanup and release all dfilter resources */
1498 dfilter_free(dfcode);
1504 cf_reftime_packets(capture_file *cf)
1506 ref_time_packets(cf);
1510 cf_redissect_packets(capture_file *cf)
1512 if (cf->state != FILE_CLOSED) {
1513 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1518 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1519 struct wtap_pkthdr *phdr, Buffer *buf)
1524 #ifdef WANT_PACKET_EDITOR
1525 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1526 if (G_UNLIKELY(fdata->file_off == -1)) {
1527 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1530 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1534 *phdr = frame->phdr;
1535 ws_buffer_assure_space(buf, frame->phdr.caplen);
1536 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1541 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1542 cfile_read_failure_alert_box(cf->filename, err, err_info);
1549 cf_read_record(capture_file *cf, frame_data *fdata)
1551 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1554 /* Rescan the list of packets, reconstructing the CList.
1556 "action" describes why we're doing this; it's used in the progress
1559 "action_item" describes what we're doing; it's used in the progress
1562 "redissect" is TRUE if we need to make the dissectors reconstruct
1563 any state information they have (because a preference that affects
1564 some dissector has changed, meaning some dissector might construct
1565 its state differently from the way it was constructed the last time). */
1567 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1569 /* Rescan packets new packet list */
1572 progdlg_t *progbar = NULL;
1573 GTimer *prog_timer = g_timer_new();
1575 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1576 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1577 gboolean selected_frame_seen;
1579 GTimeVal start_time;
1580 gchar status_str[100];
1584 gboolean create_proto_tree;
1586 gboolean add_to_packet_list = FALSE;
1588 guint32 frames_count;
1590 /* Compile the current display filter.
1591 * We assume this will not fail since cf->dfilter is only set in
1592 * cf_filter IFF the filter was valid.
1594 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1595 g_assert(!cf->dfilter || (compiled && dfcode));
1597 /* Get the union of the flags for all tap listeners. */
1598 tap_flags = union_of_tap_listener_flags();
1600 /* If any tap listeners require the columns, construct them. */
1601 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1604 * Determine whether we need to create a protocol tree.
1607 * we're going to apply a display filter;
1609 * one of the tap listeners is going to apply a filter;
1611 * one of the tap listeners requires a protocol tree;
1613 * we're redissecting and a postdissector wants field
1614 * values or protocols on the first pass.
1617 (dfcode != NULL || have_filtering_tap_listeners() ||
1618 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1619 (redissect && postdissectors_want_hfids()));
1621 reset_tap_listeners();
1622 /* Which frame, if any, is the currently selected frame?
1623 XXX - should the selected frame or the focus frame be the "current"
1624 frame, that frame being the one from which "Find Frame" searches
1626 selected_frame = cf->current_frame;
1628 /* Mark frame num as not found */
1629 selected_frame_num = -1;
1631 /* Freeze the packet list while we redo it, so we don't get any
1632 screen updates while it happens. */
1633 packet_list_freeze();
1636 /* We need to re-initialize all the state information that protocols
1637 keep, because some preference that controls a dissector has changed,
1638 which might cause the state information to be constructed differently
1639 by that dissector. */
1641 /* We might receive new packets while redissecting, and we don't
1642 want to dissect those before their time. */
1643 cf->redissecting = TRUE;
1645 /* 'reset' dissection session */
1646 epan_free(cf->epan);
1647 if (cf->edt && cf->edt->pi.fd) {
1648 /* All pointers in "per frame proto data" for the currently selected
1649 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1650 Free them here to avoid unintended usage in packet_list_clear(). */
1651 frame_data_destroy(cf->edt->pi.fd);
1653 cf->epan = ws_epan_new(cf);
1654 cf->cinfo.epan = cf->epan;
1656 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1657 called via epan_new() / init_dissection() when reloading Lua plugins. */
1658 if (!create_proto_tree && have_filtering_tap_listeners()) {
1659 create_proto_tree = TRUE;
1662 /* We need to redissect the packets so we have to discard our old
1663 * packet list store. */
1664 packet_list_clear();
1665 add_to_packet_list = TRUE;
1668 /* We don't yet know which will be the first and last frames displayed. */
1669 cf->first_displayed = 0;
1670 cf->last_displayed = 0;
1672 /* We currently don't display any packets */
1673 cf->displayed_count = 0;
1675 /* Iterate through the list of frames. Call a routine for each frame
1676 to check whether it should be displayed and, if so, add it to
1677 the display list. */
1679 cf->prev_dis = NULL;
1680 cf->prev_cap = NULL;
1683 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1685 g_timer_start(prog_timer);
1686 /* Count of packets at which we've looked. */
1688 /* Progress so far. */
1691 cf->stop_flag = FALSE;
1692 g_get_current_time(&start_time);
1694 /* no previous row yet */
1695 prev_frame_num = -1;
1698 preceding_frame_num = -1;
1699 preceding_frame = NULL;
1700 following_frame_num = -1;
1701 following_frame = NULL;
1703 selected_frame_seen = FALSE;
1705 frames_count = cf->count;
1707 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1709 for (framenum = 1; framenum <= frames_count; framenum++) {
1710 fdata = frame_data_sequence_find(cf->frames, framenum);
1712 /* Create the progress bar if necessary.
1713 We check on every iteration of the loop, so that it takes no
1714 longer than the standard time to create it (otherwise, for a
1715 large file, we might take considerably longer than that standard
1716 time in order to get to the next progress bar step). */
1717 if (progbar == NULL)
1718 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1724 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1725 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1726 * likely trigger UI paint events, which might take a while depending on
1727 * the platform and display. Reset our timer *after* painting.
1729 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1730 /* let's not divide by zero. I should never be started
1731 * with count == 0, so let's assert that
1733 g_assert(cf->count > 0);
1734 progbar_val = (gfloat) count / frames_count;
1736 if (progbar != NULL) {
1737 g_snprintf(status_str, sizeof(status_str),
1738 "%4u of %u frames", count, frames_count);
1739 update_progress_dlg(progbar, progbar_val, status_str);
1742 g_timer_start(prog_timer);
1745 if (cf->stop_flag) {
1746 /* Well, the user decided to abort the filtering. Just stop.
1748 XXX - go back to the previous filter? Users probably just
1749 want not to wait for a filtering operation to finish;
1750 unless we cancel by having no filter, reverting to the
1751 previous filter will probably be even more expensive than
1752 continuing the filtering, as it involves going back to the
1753 beginning and filtering, and even with no filter we currently
1754 have to re-generate the entire clist, which is also expensive.
1756 I'm not sure what Network Monitor does, but it doesn't appear
1757 to give you an unfiltered display if you cancel. */
1764 /* Since all state for the frame was destroyed, mark the frame
1765 * as not visited, free the GSList referring to the state
1766 * data (the per-frame data itself was freed by
1767 * "init_dissection()"), and null out the GSList pointer. */
1768 frame_data_reset(fdata);
1769 frames_count = cf->count;
1772 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1773 fdata->flags.dependent_of_displayed = 0;
1775 if (!cf_read_record(cf, fdata))
1776 break; /* error reading the frame */
1778 /* If the previous frame is displayed, and we haven't yet seen the
1779 selected frame, remember that frame - it's the closest one we've
1780 yet seen before the selected frame. */
1781 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1782 preceding_frame_num = prev_frame_num;
1783 preceding_frame = prev_frame;
1786 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1788 ws_buffer_start_ptr(&cf->buf),
1789 add_to_packet_list);
1791 /* If this frame is displayed, and this is the first frame we've
1792 seen displayed after the selected frame, remember this frame -
1793 it's the closest one we've yet seen at or after the selected
1795 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1796 following_frame_num = fdata->num;
1797 following_frame = fdata;
1799 if (fdata == selected_frame) {
1800 selected_frame_seen = TRUE;
1801 if (fdata->flags.passed_dfilter)
1802 selected_frame_num = fdata->num;
1805 /* Remember this frame - it'll be the previous frame
1806 on the next pass through the loop. */
1807 prev_frame_num = fdata->num;
1811 epan_dissect_cleanup(&edt);
1813 /* We are done redissecting the packet list. */
1814 cf->redissecting = FALSE;
1817 frames_count = cf->count;
1818 /* Clear out what remains of the visited flags and per-frame data
1821 XXX - that may cause various forms of bogosity when dissecting
1822 these frames, as they won't have been seen by this sequential
1823 pass, but the only alternative I see is to keep scanning them
1824 even though the user requested that the scan stop, and that
1825 would leave the user stuck with an Wireshark grinding on
1826 until it finishes. Should we just stick them with that? */
1827 for (; framenum <= frames_count; framenum++) {
1828 fdata = frame_data_sequence_find(cf->frames, framenum);
1829 frame_data_reset(fdata);
1833 /* We're done filtering the packets; destroy the progress bar if it
1835 if (progbar != NULL)
1836 destroy_progress_dlg(progbar);
1837 g_timer_destroy(prog_timer);
1839 /* Unfreeze the packet list. */
1840 if (!add_to_packet_list)
1841 packet_list_recreate_visible_rows();
1843 /* Compute the time it took to filter the file */
1844 compute_elapsed(cf, &start_time);
1848 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1850 if (selected_frame_num == -1) {
1851 /* The selected frame didn't pass the filter. */
1852 if (selected_frame == NULL) {
1853 /* That's because there *was* no selected frame. Make the first
1854 displayed frame the current frame. */
1855 selected_frame_num = 0;
1857 /* Find the nearest displayed frame to the selected frame (whether
1858 it's before or after that frame) and make that the current frame.
1859 If the next and previous displayed frames are equidistant from the
1860 selected frame, choose the next one. */
1861 g_assert(following_frame == NULL ||
1862 following_frame->num >= selected_frame->num);
1863 g_assert(preceding_frame == NULL ||
1864 preceding_frame->num <= selected_frame->num);
1865 if (following_frame == NULL) {
1866 /* No frame after the selected frame passed the filter, so we
1867 have to select the last displayed frame before the selected
1869 selected_frame_num = preceding_frame_num;
1870 selected_frame = preceding_frame;
1871 } else if (preceding_frame == NULL) {
1872 /* No frame before the selected frame passed the filter, so we
1873 have to select the first displayed frame after the selected
1875 selected_frame_num = following_frame_num;
1876 selected_frame = following_frame;
1878 /* Frames before and after the selected frame passed the filter, so
1879 we'll select the previous frame */
1880 selected_frame_num = preceding_frame_num;
1881 selected_frame = preceding_frame;
1886 if (selected_frame_num == -1) {
1887 /* There are no frames displayed at all. */
1888 cf_unselect_packet(cf);
1890 /* Either the frame that was selected passed the filter, or we've
1891 found the nearest displayed frame to that frame. Select it, make
1892 it the focus row, and make it visible. */
1893 /* Set to invalid to force update of packet list and packet details */
1894 cf->current_row = -1;
1895 if (selected_frame_num == 0) {
1896 packet_list_select_first_row();
1898 if (!packet_list_select_row_from_data(selected_frame)) {
1899 /* We didn't find a row corresponding to this frame.
1900 This means that the frame isn't being displayed currently,
1901 so we can't select it. */
1902 simple_message_box(ESD_TYPE_INFO, NULL,
1903 "The capture file is probably not fully dissected.",
1904 "End of capture exceeded.");
1909 /* Cleanup and release all dfilter resources */
1910 dfilter_free(dfcode);
1915 * Scan through all frame data and recalculate the ref time
1916 * without rereading the file.
1917 * XXX - do we need a progres bar or is this fast enough?
1920 ref_time_packets(capture_file *cf)
1927 cf->prev_dis = NULL;
1930 for (framenum = 1; framenum <= cf->count; framenum++) {
1931 fdata = frame_data_sequence_find(cf->frames, framenum);
1933 /* just add some value here until we know if it is being displayed or not */
1934 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1940 /* If we don't have the time stamp of the first packet in the
1941 capture, it's because this is the first packet. Save the time
1942 stamp of this packet as the time stamp of the first packet. */
1943 if (cf->ref == NULL)
1945 /* if this frames is marked as a reference time frame, reset
1946 firstsec and firstusec to this frame */
1947 if (fdata->flags.ref_time)
1950 /* If we don't have the time stamp of the previous displayed packet,
1951 it's because this is the first displayed packet. Save the time
1952 stamp of this packet as the time stamp of the previous displayed
1954 if (cf->prev_dis == NULL) {
1955 cf->prev_dis = fdata;
1958 /* Get the time elapsed between the first packet and this packet. */
1959 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1960 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1962 /* If it's greater than the current elapsed time, set the elapsed time
1963 to it (we check for "greater than" so as not to be confused by
1964 time moving backwards). */
1965 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1966 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1967 cf->elapsed_time = rel_ts;
1970 /* If this frame is displayed, get the time elapsed between the
1971 previous displayed packet and this packet. */
1972 if ( fdata->flags.passed_dfilter ) {
1973 fdata->prev_dis_num = cf->prev_dis->num;
1974 cf->prev_dis = fdata;
1980 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1981 /* This frame either passed the display filter list or is marked as
1982 a time reference frame. All time reference frames are displayed
1983 even if they don't pass the display filter */
1984 if (fdata->flags.ref_time) {
1985 /* if this was a TIME REF frame we should reset the cum_bytes field */
1986 cf->cum_bytes = fdata->pkt_len;
1987 fdata->cum_bytes = cf->cum_bytes;
1989 /* increase cum_bytes with this packets length */
1990 cf->cum_bytes += fdata->pkt_len;
2003 process_specified_records(capture_file *cf, packet_range_t *range,
2004 const char *string1, const char *string2, gboolean terminate_is_stop,
2005 gboolean (*callback)(capture_file *, frame_data *,
2006 struct wtap_pkthdr *, const guint8 *, void *),
2007 void *callback_args,
2008 gboolean show_progress_bar)
2013 psp_return_t ret = PSP_FINISHED;
2015 progdlg_t *progbar = NULL;
2016 GTimer *prog_timer = g_timer_new();
2019 GTimeVal progbar_start_time;
2020 gchar progbar_status_str[100];
2021 range_process_e process_this;
2022 struct wtap_pkthdr phdr;
2024 wtap_phdr_init(&phdr);
2025 ws_buffer_init(&buf, 1500);
2027 g_timer_start(prog_timer);
2028 /* Count of packets at which we've looked. */
2030 /* Progress so far. */
2033 cf->stop_flag = FALSE;
2034 g_get_current_time(&progbar_start_time);
2037 packet_range_process_init(range);
2039 /* Iterate through all the packets, printing the packets that
2040 were selected by the current display filter. */
2041 for (framenum = 1; framenum <= cf->count; framenum++) {
2042 fdata = frame_data_sequence_find(cf->frames, framenum);
2044 /* Create the progress bar if necessary.
2045 We check on every iteration of the loop, so that it takes no
2046 longer than the standard time to create it (otherwise, for a
2047 large file, we might take considerably longer than that standard
2048 time in order to get to the next progress bar step). */
2049 if (show_progress_bar && progbar == NULL)
2050 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2053 &progbar_start_time,
2057 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2058 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2059 * likely trigger UI paint events, which might take a while depending on
2060 * the platform and display. Reset our timer *after* painting.
2062 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2063 /* let's not divide by zero. I should never be started
2064 * with count == 0, so let's assert that
2066 g_assert(cf->count > 0);
2067 progbar_val = (gfloat) progbar_count / cf->count;
2069 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2070 "%4u of %u packets", progbar_count, cf->count);
2071 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2073 g_timer_start(prog_timer);
2076 if (cf->stop_flag) {
2077 /* Well, the user decided to abort the operation. Just stop,
2078 and arrange to return PSP_STOPPED to our caller, so they know
2079 it was stopped explicitly. */
2086 if (range != NULL) {
2087 /* do we have to process this packet? */
2088 process_this = packet_range_process_packet(range, fdata);
2089 if (process_this == range_process_next) {
2090 /* this packet uninteresting, continue with next one */
2092 } else if (process_this == range_processing_finished) {
2093 /* all interesting packets processed, stop the loop */
2098 /* Get the packet */
2099 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2100 /* Attempt to get the packet failed. */
2104 /* Process the packet */
2105 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2106 /* Callback failed. We assume it reported the error appropriately. */
2112 /* We're done printing the packets; destroy the progress bar if
2114 if (progbar != NULL)
2115 destroy_progress_dlg(progbar);
2116 g_timer_destroy(prog_timer);
2118 wtap_phdr_cleanup(&phdr);
2119 ws_buffer_free(&buf);
2127 } retap_callback_args_t;
2130 retap_packet(capture_file *cf, frame_data *fdata,
2131 struct wtap_pkthdr *phdr, const guint8 *pd,
2134 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2136 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2137 epan_dissect_reset(&args->edt);
2143 cf_retap_packets(capture_file *cf)
2145 packet_range_t range;
2146 retap_callback_args_t callback_args;
2147 gboolean create_proto_tree;
2151 /* Presumably the user closed the capture file. */
2153 return CF_READ_ABORTED;
2156 cf_callback_invoke(cf_cb_file_retap_started, cf);
2158 /* Get the union of the flags for all tap listeners. */
2159 tap_flags = union_of_tap_listener_flags();
2161 /* If any tap listeners require the columns, construct them. */
2162 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2165 * Determine whether we need to create a protocol tree.
2168 * one of the tap listeners is going to apply a filter;
2170 * one of the tap listeners requires a protocol tree.
2173 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2175 /* Reset the tap listeners. */
2176 reset_tap_listeners();
2178 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2180 /* Iterate through the list of packets, dissecting all packets and
2181 re-running the taps. */
2182 packet_range_init(&range, cf);
2183 packet_range_process_init(&range);
2185 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2186 "all packets", TRUE, retap_packet,
2187 &callback_args, TRUE);
2189 epan_dissect_cleanup(&callback_args.edt);
2191 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2195 /* Completed successfully. */
2199 /* Well, the user decided to abort the refiltering.
2200 Return CF_READ_ABORTED so our caller knows they did that. */
2201 return CF_READ_ABORTED;
2204 /* Error while retapping. */
2205 return CF_READ_ERROR;
2208 g_assert_not_reached();
2213 print_args_t *print_args;
2214 gboolean print_header_line;
2215 char *header_line_buf;
2216 int header_line_buf_len;
2217 gboolean print_formfeed;
2218 gboolean print_separator;
2222 int num_visible_cols;
2225 } print_callback_args_t;
2228 print_packet(capture_file *cf, frame_data *fdata,
2229 struct wtap_pkthdr *phdr, const guint8 *pd,
2232 print_callback_args_t *args = (print_callback_args_t *)argsp;
2238 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2239 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2240 col_item_t* col_item;
2242 /* Fill in the column information if we're printing the summary
2244 if (args->print_args->print_summary) {
2245 col_custom_prime_edt(&args->edt, &cf->cinfo);
2246 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2247 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2249 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2251 if (args->print_formfeed) {
2252 if (!new_page(args->print_args->stream))
2255 if (args->print_separator) {
2256 if (!print_line(args->print_args->stream, 0, ""))
2262 * We generate bookmarks, if the output format supports them.
2263 * The name is "__frameN__".
2265 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2267 if (args->print_args->print_summary) {
2268 if (!args->print_args->print_col_headings)
2269 args->print_header_line = FALSE;
2270 if (args->print_header_line) {
2271 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2273 args->print_header_line = FALSE; /* we might not need to print any more */
2275 cp = &args->line_buf[0];
2277 for (i = 0; i < args->num_visible_cols; i++) {
2278 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2279 /* Find the length of the string for this column. */
2280 column_len = (int) strlen(col_item->col_data);
2281 if (args->col_widths[i] > column_len)
2282 column_len = args->col_widths[i];
2284 /* Make sure there's room in the line buffer for the column; if not,
2285 double its length. */
2286 line_len += column_len + 1; /* "+1" for space */
2287 if (line_len > args->line_buf_len) {
2288 cp_off = (int) (cp - args->line_buf);
2289 args->line_buf_len = 2 * line_len;
2290 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2291 cp = args->line_buf + cp_off;
2294 /* Right-justify the packet number column. */
2295 if (col_item->col_fmt == COL_NUMBER)
2296 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2298 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2300 if (i != args->num_visible_cols - 1)
2306 * Generate a bookmark, using the summary line as the title.
2308 if (!print_bookmark(args->print_args->stream, bookmark_name,
2312 if (!print_line(args->print_args->stream, 0, args->line_buf))
2316 * Generate a bookmark, using "Frame N" as the title, as we're not
2317 * printing the summary line.
2319 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2320 if (!print_bookmark(args->print_args->stream, bookmark_name,
2323 } /* if (print_summary) */
2325 if (args->print_args->print_dissections != print_dissections_none) {
2326 if (args->print_args->print_summary) {
2327 /* Separate the summary line from the tree with a blank line. */
2328 if (!print_line(args->print_args->stream, 0, ""))
2332 /* Print the information in that tree. */
2333 if (!proto_tree_print(args->print_args->print_dissections,
2334 args->print_args->print_hex, &args->edt, NULL,
2335 args->print_args->stream))
2338 /* Print a blank line if we print anything after this (aka more than one packet). */
2339 args->print_separator = TRUE;
2341 /* Print a header line if we print any more packet summaries */
2342 if (args->print_args->print_col_headings)
2343 args->print_header_line = TRUE;
2346 if (args->print_args->print_hex) {
2347 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2348 if (!print_line(args->print_args->stream, 0, ""))
2351 /* Print the full packet data as hex. */
2352 if (!print_hex_data(args->print_args->stream, &args->edt))
2355 /* Print a blank line if we print anything after this (aka more than one packet). */
2356 args->print_separator = TRUE;
2358 /* Print a header line if we print any more packet summaries */
2359 if (args->print_args->print_col_headings)
2360 args->print_header_line = TRUE;
2361 } /* if (args->print_args->print_dissections != print_dissections_none) */
2363 epan_dissect_reset(&args->edt);
2365 /* do we want to have a formfeed between each packet from now on? */
2366 if (args->print_args->print_formfeed) {
2367 args->print_formfeed = TRUE;
2373 epan_dissect_reset(&args->edt);
2378 cf_print_packets(capture_file *cf, print_args_t *print_args,
2379 gboolean show_progress_bar)
2381 print_callback_args_t callback_args;
2384 int i, cp_off, column_len, line_len;
2385 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2389 gboolean proto_tree_needed;
2391 callback_args.print_args = print_args;
2392 callback_args.print_header_line = print_args->print_col_headings;
2393 callback_args.header_line_buf = NULL;
2394 callback_args.header_line_buf_len = 256;
2395 callback_args.print_formfeed = FALSE;
2396 callback_args.print_separator = FALSE;
2397 callback_args.line_buf = NULL;
2398 callback_args.line_buf_len = 256;
2399 callback_args.col_widths = NULL;
2400 callback_args.num_visible_cols = 0;
2401 callback_args.visible_cols = NULL;
2403 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2404 destroy_print_stream(print_args->stream);
2405 return CF_PRINT_WRITE_ERROR;
2408 if (print_args->print_summary) {
2409 /* We're printing packet summaries. Allocate the header line buffer
2410 and get the column widths. */
2411 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2413 /* Find the number of visible columns and the last visible column */
2414 for (i = 0; i < prefs.num_cols; i++) {
2416 clp = g_list_nth(prefs.col_list, i);
2417 if (clp == NULL) /* Sanity check, Invalid column requested */
2420 cfmt = (fmt_data *) clp->data;
2421 if (cfmt->visible) {
2423 last_visible_col = i;
2427 /* Find the widths for each of the columns - maximum of the
2428 width of the title and the width of the data - and construct
2429 a buffer with a line containing the column titles. */
2430 callback_args.num_visible_cols = num_visible_col;
2431 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2432 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2433 cp = &callback_args.header_line_buf[0];
2435 visible_col_count = 0;
2436 for (i = 0; i < cf->cinfo.num_cols; i++) {
2438 clp = g_list_nth(prefs.col_list, i);
2439 if (clp == NULL) /* Sanity check, Invalid column requested */
2442 cfmt = (fmt_data *) clp->data;
2443 if (cfmt->visible == FALSE)
2446 /* Save the order of visible columns */
2447 callback_args.visible_cols[visible_col_count] = i;
2449 /* Don't pad the last column. */
2450 if (i == last_visible_col)
2451 callback_args.col_widths[visible_col_count] = 0;
2453 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2454 data_width = get_column_char_width(get_column_format(i));
2455 if (data_width > callback_args.col_widths[visible_col_count])
2456 callback_args.col_widths[visible_col_count] = data_width;
2459 /* Find the length of the string for this column. */
2460 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2461 if (callback_args.col_widths[i] > column_len)
2462 column_len = callback_args.col_widths[visible_col_count];
2464 /* Make sure there's room in the line buffer for the column; if not,
2465 double its length. */
2466 line_len += column_len + 1; /* "+1" for space */
2467 if (line_len > callback_args.header_line_buf_len) {
2468 cp_off = (int) (cp - callback_args.header_line_buf);
2469 callback_args.header_line_buf_len = 2 * line_len;
2470 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2471 callback_args.header_line_buf_len + 1);
2472 cp = callback_args.header_line_buf + cp_off;
2475 /* Right-justify the packet number column. */
2476 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2477 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2479 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2481 if (i != cf->cinfo.num_cols - 1)
2484 visible_col_count++;
2488 /* Now start out the main line buffer with the same length as the
2489 header line buffer. */
2490 callback_args.line_buf_len = callback_args.header_line_buf_len;
2491 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2492 } /* if (print_summary) */
2494 /* Create the protocol tree, and make it visible, if we're printing
2495 the dissection or the hex data.
2496 XXX - do we need it if we're just printing the hex data? */
2498 callback_args.print_args->print_dissections != print_dissections_none ||
2499 callback_args.print_args->print_hex ||
2500 have_custom_cols(&cf->cinfo) || have_field_extractors();
2501 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2503 /* Iterate through the list of packets, printing the packets we were
2505 ret = process_specified_records(cf, &print_args->range, "Printing",
2506 "selected packets", TRUE, print_packet,
2507 &callback_args, show_progress_bar);
2508 epan_dissect_cleanup(&callback_args.edt);
2509 g_free(callback_args.header_line_buf);
2510 g_free(callback_args.line_buf);
2511 g_free(callback_args.col_widths);
2512 g_free(callback_args.visible_cols);
2517 /* Completed successfully. */
2521 /* Well, the user decided to abort the printing.
2523 XXX - note that what got generated before they did that
2524 will get printed if we're piping to a print program; we'd
2525 have to write to a file and then hand that to the print
2526 program to make it actually not print anything. */
2530 /* Error while printing.
2532 XXX - note that what got generated before they did that
2533 will get printed if we're piping to a print program; we'd
2534 have to write to a file and then hand that to the print
2535 program to make it actually not print anything. */
2536 destroy_print_stream(print_args->stream);
2537 return CF_PRINT_WRITE_ERROR;
2540 if (!print_finale(print_args->stream)) {
2541 destroy_print_stream(print_args->stream);
2542 return CF_PRINT_WRITE_ERROR;
2545 if (!destroy_print_stream(print_args->stream))
2546 return CF_PRINT_WRITE_ERROR;
2554 print_args_t *print_args;
2555 } write_packet_callback_args_t;
2558 write_pdml_packet(capture_file *cf, frame_data *fdata,
2559 struct wtap_pkthdr *phdr, const guint8 *pd,
2562 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2564 /* Create the protocol tree, but don't fill in the column information. */
2565 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2567 /* Write out the information in that tree. */
2568 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh, FALSE);
2570 epan_dissect_reset(&args->edt);
2572 return !ferror(args->fh);
2576 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2578 write_packet_callback_args_t callback_args;
2582 fh = ws_fopen(print_args->file, "w");
2584 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2586 write_pdml_preamble(fh, cf->filename);
2589 return CF_PRINT_WRITE_ERROR;
2592 callback_args.fh = fh;
2593 callback_args.print_args = print_args;
2594 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2596 /* Iterate through the list of packets, printing the packets we were
2598 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2599 "selected packets", TRUE,
2600 write_pdml_packet, &callback_args, TRUE);
2602 epan_dissect_cleanup(&callback_args.edt);
2607 /* Completed successfully. */
2611 /* Well, the user decided to abort the printing. */
2615 /* Error while printing. */
2617 return CF_PRINT_WRITE_ERROR;
2620 write_pdml_finale(fh);
2623 return CF_PRINT_WRITE_ERROR;
2626 /* XXX - check for an error */
2633 write_psml_packet(capture_file *cf, frame_data *fdata,
2634 struct wtap_pkthdr *phdr, const guint8 *pd,
2637 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2639 /* Fill in the column information */
2640 col_custom_prime_edt(&args->edt, &cf->cinfo);
2641 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2642 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2644 /* Write out the column information. */
2645 write_psml_columns(&args->edt, args->fh, FALSE);
2647 epan_dissect_reset(&args->edt);
2649 return !ferror(args->fh);
2653 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2655 write_packet_callback_args_t callback_args;
2659 gboolean proto_tree_needed;
2661 fh = ws_fopen(print_args->file, "w");
2663 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2665 write_psml_preamble(&cf->cinfo, fh);
2668 return CF_PRINT_WRITE_ERROR;
2671 callback_args.fh = fh;
2672 callback_args.print_args = print_args;
2674 /* Fill in the column information, only create the protocol tree
2675 if having custom columns or field extractors. */
2676 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2677 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2679 /* Iterate through the list of packets, printing the packets we were
2681 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2682 "selected packets", TRUE,
2683 write_psml_packet, &callback_args, TRUE);
2685 epan_dissect_cleanup(&callback_args.edt);
2690 /* Completed successfully. */
2694 /* Well, the user decided to abort the printing. */
2698 /* Error while printing. */
2700 return CF_PRINT_WRITE_ERROR;
2703 write_psml_finale(fh);
2706 return CF_PRINT_WRITE_ERROR;
2709 /* XXX - check for an error */
2716 write_csv_packet(capture_file *cf, frame_data *fdata,
2717 struct wtap_pkthdr *phdr, const guint8 *pd,
2720 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2722 /* Fill in the column information */
2723 col_custom_prime_edt(&args->edt, &cf->cinfo);
2724 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2725 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2727 /* Write out the column information. */
2728 write_csv_columns(&args->edt, args->fh);
2730 epan_dissect_reset(&args->edt);
2732 return !ferror(args->fh);
2736 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2738 write_packet_callback_args_t callback_args;
2739 gboolean proto_tree_needed;
2743 fh = ws_fopen(print_args->file, "w");
2745 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2747 write_csv_column_titles(&cf->cinfo, fh);
2750 return CF_PRINT_WRITE_ERROR;
2753 callback_args.fh = fh;
2754 callback_args.print_args = print_args;
2756 /* only create the protocol tree if having custom columns or field extractors. */
2757 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2758 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2760 /* Iterate through the list of packets, printing the packets we were
2762 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2763 "selected packets", TRUE,
2764 write_csv_packet, &callback_args, TRUE);
2766 epan_dissect_cleanup(&callback_args.edt);
2771 /* Completed successfully. */
2775 /* Well, the user decided to abort the printing. */
2779 /* Error while printing. */
2781 return CF_PRINT_WRITE_ERROR;
2784 /* XXX - check for an error */
2791 carrays_write_packet(capture_file *cf, frame_data *fdata,
2792 struct wtap_pkthdr *phdr,
2793 const guint8 *pd, void *argsp)
2795 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2797 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2798 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2799 epan_dissect_reset(&args->edt);
2801 return !ferror(args->fh);
2805 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2807 write_packet_callback_args_t callback_args;
2811 fh = ws_fopen(print_args->file, "w");
2814 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2818 return CF_PRINT_WRITE_ERROR;
2821 callback_args.fh = fh;
2822 callback_args.print_args = print_args;
2823 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2825 /* Iterate through the list of packets, printing the packets we were
2827 ret = process_specified_records(cf, &print_args->range,
2829 "selected packets", TRUE,
2830 carrays_write_packet, &callback_args, TRUE);
2832 epan_dissect_cleanup(&callback_args.edt);
2836 /* Completed successfully. */
2839 /* Well, the user decided to abort the printing. */
2842 /* Error while printing. */
2844 return CF_PRINT_WRITE_ERROR;
2852 write_json_packet(capture_file *cf, frame_data *fdata,
2853 struct wtap_pkthdr *phdr, const guint8 *pd,
2856 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2858 /* Create the protocol tree, but don't fill in the column information. */
2859 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2861 /* Write out the information in that tree. */
2862 write_json_proto_tree(NULL, args->print_args->print_dissections,
2863 args->print_args->print_hex, NULL, PF_NONE,
2864 &args->edt, args->fh);
2866 epan_dissect_reset(&args->edt);
2868 return !ferror(args->fh);
2872 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2874 write_packet_callback_args_t callback_args;
2878 fh = ws_fopen(print_args->file, "w");
2880 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2882 write_json_preamble(fh);
2885 return CF_PRINT_WRITE_ERROR;
2888 callback_args.fh = fh;
2889 callback_args.print_args = print_args;
2890 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2892 /* Iterate through the list of packets, printing the packets we were
2894 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2895 "selected packets", TRUE,
2896 write_json_packet, &callback_args, TRUE);
2898 epan_dissect_cleanup(&callback_args.edt);
2903 /* Completed successfully. */
2907 /* Well, the user decided to abort the printing. */
2911 /* Error while printing. */
2913 return CF_PRINT_WRITE_ERROR;
2916 write_json_finale(fh);
2919 return CF_PRINT_WRITE_ERROR;
2922 /* XXX - check for an error */
2929 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2930 search_direction dir)
2934 mdata.string = string;
2935 mdata.string_len = strlen(string);
2936 return find_packet(cf, match_protocol_tree, &mdata, dir);
2940 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2942 mdata->frame_matched = FALSE;
2943 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2944 mdata->string_len = strlen(mdata->string);
2946 /* Iterate through all the nodes looking for matching text */
2947 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2948 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2952 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2954 match_data *mdata = (match_data *)criterion;
2957 /* Load the frame's data. */
2958 if (!cf_read_record(cf, fdata)) {
2959 /* Attempt to get the packet failed. */
2963 /* Construct the protocol tree, including the displayed text */
2964 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2965 /* We don't need the column information */
2966 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2968 /* Iterate through all the nodes, seeing if they have text that matches. */
2970 mdata->frame_matched = FALSE;
2971 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2972 epan_dissect_cleanup(&edt);
2973 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2977 match_subtree_text(proto_node *node, gpointer data)
2979 match_data *mdata = (match_data *) data;
2980 const gchar *string = mdata->string;
2981 size_t string_len = mdata->string_len;
2982 capture_file *cf = mdata->cf;
2983 field_info *fi = PNODE_FINFO(node);
2984 gchar label_str[ITEM_LABEL_LENGTH];
2991 /* dissection with an invisible proto tree? */
2994 if (mdata->frame_matched) {
2995 /* We already had a match; don't bother doing any more work. */
2999 /* Don't match invisible entries. */
3000 if (PROTO_ITEM_IS_HIDDEN(node))
3003 /* was a free format label produced? */
3005 label_ptr = fi->rep->representation;
3007 /* no, make a generic label */
3008 label_ptr = label_str;
3009 proto_item_fill_label(fi, label_str);
3013 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3014 mdata->frame_matched = TRUE;
3019 /* Does that label match? */
3020 label_len = strlen(label_ptr);
3021 for (i = 0; i < label_len; i++) {
3022 c_char = label_ptr[i];
3024 c_char = g_ascii_toupper(c_char);
3025 if (c_char == string[c_match]) {
3027 if (c_match == string_len) {
3028 /* No need to look further; we have a match */
3029 mdata->frame_matched = TRUE;
3038 /* Recurse into the subtree, if it exists */
3039 if (node->first_child != NULL)
3040 proto_tree_children_foreach(node, match_subtree_text, mdata);
3044 cf_find_packet_summary_line(capture_file *cf, const char *string,
3045 search_direction dir)
3049 mdata.string = string;
3050 mdata.string_len = strlen(string);
3051 return find_packet(cf, match_summary_line, &mdata, dir);
3055 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3057 match_data *mdata = (match_data *)criterion;
3058 const gchar *string = mdata->string;
3059 size_t string_len = mdata->string_len;
3061 const char *info_column;
3062 size_t info_column_len;
3063 match_result result = MR_NOTMATCHED;
3069 /* Load the frame's data. */
3070 if (!cf_read_record(cf, fdata)) {
3071 /* Attempt to get the packet failed. */
3075 /* Don't bother constructing the protocol tree */
3076 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3077 /* Get the column information */
3078 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3081 /* Find the Info column */
3082 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3083 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3084 /* Found it. See if we match. */
3085 info_column = edt.pi.cinfo->columns[colx].col_data;
3086 info_column_len = strlen(info_column);
3088 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3089 result = MR_MATCHED;
3093 for (i = 0; i < info_column_len; i++) {
3094 c_char = info_column[i];
3096 c_char = g_ascii_toupper(c_char);
3097 if (c_char == string[c_match]) {
3099 if (c_match == string_len) {
3100 result = MR_MATCHED;
3110 epan_dissect_cleanup(&edt);
3117 } cbs_t; /* "Counted byte string" */
3121 * The current match_* routines only support ASCII case insensitivity and don't
3122 * convert UTF-8 inputs to UTF-16 for matching.
3124 * We could modify them to use the GLib Unicode routines or the International
3125 * Components for Unicode library but it's not apparent that we could do so
3126 * without consuming a lot more CPU and memory or that searching would be
3127 * significantly better.
3131 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3132 search_direction dir)
3137 info.data_len = string_size;
3139 /* Regex, String or hex search? */
3141 /* Regular Expression search */
3142 return find_packet(cf, match_regex, NULL, dir);
3143 } else if (cf->string) {
3144 /* String search - what type of string? */
3145 switch (cf->scs_type) {
3147 case SCS_NARROW_AND_WIDE:
3148 return find_packet(cf, match_narrow_and_wide, &info, dir);
3151 return find_packet(cf, match_narrow, &info, dir);
3154 return find_packet(cf, match_wide, &info, dir);
3157 g_assert_not_reached();
3161 return find_packet(cf, match_binary, &info, dir);
3165 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3167 cbs_t *info = (cbs_t *)criterion;
3168 const guint8 *ascii_text = info->data;
3169 size_t textlen = info->data_len;
3170 match_result result;
3177 /* Load the frame's data. */
3178 if (!cf_read_record(cf, fdata)) {
3179 /* Attempt to get the packet failed. */
3183 result = MR_NOTMATCHED;
3184 buf_len = fdata->cap_len;
3185 pd = ws_buffer_start_ptr(&cf->buf);
3187 while (i < buf_len) {
3190 c_char = g_ascii_toupper(c_char);
3191 if (c_char != '\0') {
3192 if (c_char == ascii_text[c_match]) {
3194 if (c_match == textlen) {
3195 result = MR_MATCHED;
3196 cf->search_pos = i; /* Save the position of the last character
3197 for highlighting the field. */
3198 cf->search_len = (guint32)textlen;
3203 g_assert(i>=c_match);
3204 i -= (guint32)c_match;
3214 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3217 cbs_t *info = (cbs_t *)criterion;
3218 const guint8 *ascii_text = info->data;
3219 size_t textlen = info->data_len;
3220 match_result result;
3226 /* Load the frame's data. */
3227 if (!cf_read_record(cf, fdata)) {
3228 /* Attempt to get the packet failed. */
3232 result = MR_NOTMATCHED;
3233 buf_len = fdata->cap_len;
3234 pd = ws_buffer_start_ptr(&cf->buf);
3236 while (i < buf_len) {
3239 c_char = g_ascii_toupper(c_char);
3240 if (c_char == ascii_text[c_match]) {
3242 if (c_match == textlen) {
3243 result = MR_MATCHED;
3244 cf->search_pos = i; /* Save the position of the last character
3245 for highlighting the field. */
3246 cf->search_len = (guint32)textlen;
3251 g_assert(i>=c_match);
3252 i -= (guint32)c_match;
3262 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3264 cbs_t *info = (cbs_t *)criterion;
3265 const guint8 *ascii_text = info->data;
3266 size_t textlen = info->data_len;
3267 match_result result;
3274 /* Load the frame's data. */
3275 if (!cf_read_record(cf, fdata)) {
3276 /* Attempt to get the packet failed. */
3280 result = MR_NOTMATCHED;
3281 buf_len = fdata->cap_len;
3282 pd = ws_buffer_start_ptr(&cf->buf);
3284 while (i < buf_len) {
3287 c_char = g_ascii_toupper(c_char);
3288 if (c_char == ascii_text[c_match]) {
3290 if (c_match == textlen) {
3291 result = MR_MATCHED;
3292 cf->search_pos = i; /* Save the position of the last character
3293 for highlighting the field. */
3294 cf->search_len = (guint32)textlen;
3300 g_assert(i>=(c_match*2));
3301 i -= (guint32)c_match*2;
3310 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3312 cbs_t *info = (cbs_t *)criterion;
3313 const guint8 *binary_data = info->data;
3314 size_t datalen = info->data_len;
3315 match_result result;
3321 /* Load the frame's data. */
3322 if (!cf_read_record(cf, fdata)) {
3323 /* Attempt to get the packet failed. */
3327 result = MR_NOTMATCHED;
3328 buf_len = fdata->cap_len;
3329 pd = ws_buffer_start_ptr(&cf->buf);
3331 while (i < buf_len) {
3332 if (pd[i] == binary_data[c_match]) {
3334 if (c_match == datalen) {
3335 result = MR_MATCHED;
3336 cf->search_pos = i; /* Save the position of the last character
3337 for highlighting the field. */
3338 cf->search_len = (guint32)datalen;
3343 g_assert(i>=c_match);
3344 i -= (guint32)c_match;
3353 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3355 match_result result = MR_NOTMATCHED;
3356 GMatchInfo *match_info = NULL;
3358 /* Load the frame's data. */
3359 if (!cf_read_record(cf, fdata)) {
3360 /* Attempt to get the packet failed. */
3364 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3365 0, (GRegexMatchFlags) 0, &match_info, NULL))
3367 gint start_pos = 0, end_pos = 0;
3368 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3369 cf->search_pos = end_pos - 1;
3370 cf->search_len = end_pos - start_pos;
3371 result = MR_MATCHED;
3377 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3378 search_direction dir)
3380 return find_packet(cf, match_dfilter, sfcode, dir);
3384 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3385 search_direction dir)
3390 if (!dfilter_compile(filter, &sfcode, NULL)) {
3392 * XXX - this shouldn't happen, as the filter string is machine
3397 if (sfcode == NULL) {
3399 * XXX - this shouldn't happen, as the filter string is machine
3404 result = find_packet(cf, match_dfilter, sfcode, dir);
3405 dfilter_free(sfcode);
3410 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3412 dfilter_t *sfcode = (dfilter_t *)criterion;
3414 match_result result;
3416 /* Load the frame's data. */
3417 if (!cf_read_record(cf, fdata)) {
3418 /* Attempt to get the packet failed. */
3422 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3423 epan_dissect_prime_with_dfilter(&edt, sfcode);
3424 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3425 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3426 epan_dissect_cleanup(&edt);
3431 cf_find_packet_marked(capture_file *cf, search_direction dir)
3433 return find_packet(cf, match_marked, NULL, dir);
3437 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3439 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3443 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3445 return find_packet(cf, match_time_reference, NULL, dir);
3449 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3451 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3455 find_packet(capture_file *cf,
3456 match_result (*match_function)(capture_file *, frame_data *, void *),
3457 void *criterion, search_direction dir)
3459 frame_data *start_fd;
3462 frame_data *new_fd = NULL;
3463 progdlg_t *progbar = NULL;
3464 GTimer *prog_timer = g_timer_new();
3468 GTimeVal start_time;
3469 gchar status_str[100];
3471 match_result result;
3473 start_fd = cf->current_frame;
3474 if (start_fd != NULL) {
3475 /* Iterate through the list of packets, starting at the packet we've
3476 picked, calling a routine to run the filter on the packet, see if
3477 it matches, and stop if so. */
3479 framenum = start_fd->num;
3481 g_timer_start(prog_timer);
3482 /* Progress so far. */
3485 cf->stop_flag = FALSE;
3486 g_get_current_time(&start_time);
3488 title = cf->sfilter?cf->sfilter:"";
3490 /* Create the progress bar if necessary.
3491 We check on every iteration of the loop, so that it takes no
3492 longer than the standard time to create it (otherwise, for a
3493 large file, we might take considerably longer than that standard
3494 time in order to get to the next progress bar step). */
3495 if (progbar == NULL)
3496 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3497 FALSE, &cf->stop_flag, &start_time, progbar_val);
3500 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3501 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3502 * likely trigger UI paint events, which might take a while depending on
3503 * the platform and display. Reset our timer *after* painting.
3505 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3506 /* let's not divide by zero. I should never be started
3507 * with count == 0, so let's assert that
3509 g_assert(cf->count > 0);
3511 progbar_val = (gfloat) count / cf->count;
3513 g_snprintf(status_str, sizeof(status_str),
3514 "%4u of %u packets", count, cf->count);
3515 update_progress_dlg(progbar, progbar_val, status_str);
3517 g_timer_start(prog_timer);
3520 if (cf->stop_flag) {
3521 /* Well, the user decided to abort the search. Go back to the
3522 frame where we started. */
3527 /* Go past the current frame. */
3528 if (dir == SD_BACKWARD) {
3529 /* Go on to the previous frame. */
3530 if (framenum == 1) {
3532 * XXX - other apps have a bit more of a detailed message
3533 * for this, and instead of offering "OK" and "Cancel",
3534 * they offer things such as "Continue" and "Cancel";
3535 * we need an API for popping up alert boxes with
3536 * {Verb} and "Cancel".
3539 if (prefs.gui_find_wrap)
3541 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3542 framenum = cf->count; /* wrap around */
3546 statusbar_push_temporary_msg("Search reached the beginning.");
3547 framenum = start_fd->num; /* stay on previous packet */
3552 /* Go on to the next frame. */
3553 if (framenum == cf->count) {
3554 if (prefs.gui_find_wrap)
3556 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3557 framenum = 1; /* wrap around */
3561 statusbar_push_temporary_msg("Search reached the end.");
3562 framenum = start_fd->num; /* stay on previous packet */
3567 fdata = frame_data_sequence_find(cf->frames, framenum);
3571 /* Is this packet in the display? */
3572 if (fdata->flags.passed_dfilter) {
3573 /* Yes. Does it match the search criterion? */
3574 result = (*match_function)(cf, fdata, criterion);
3575 if (result == MR_ERROR) {
3576 /* Error; our caller has reported the error. Go back to the frame
3577 where we started. */
3580 } else if (result == MR_MATCHED) {
3581 /* Yes. Go to the new frame. */
3587 if (fdata == start_fd) {
3588 /* We're back to the frame we were on originally, and that frame
3589 doesn't match the search filter. The search failed. */
3594 /* We're done scanning the packets; destroy the progress bar if it
3596 if (progbar != NULL)
3597 destroy_progress_dlg(progbar);
3598 g_timer_destroy(prog_timer);
3601 if (new_fd != NULL) {
3602 /* Find and select */
3603 cf->search_in_progress = TRUE;
3604 found = packet_list_select_row_from_data(new_fd);
3605 cf->search_in_progress = FALSE;
3606 cf->search_pos = 0; /* Reset the position */
3607 cf->search_len = 0; /* Reset length */
3609 /* We didn't find a row corresponding to this frame.
3610 This means that the frame isn't being displayed currently,
3611 so we can't select it. */
3612 simple_message_box(ESD_TYPE_INFO, NULL,
3613 "The capture file is probably not fully dissected.",
3614 "End of capture exceeded.");
3617 return TRUE; /* success */
3619 return FALSE; /* failure */
3623 cf_goto_frame(capture_file *cf, guint fnumber)
3627 if (cf == NULL || cf->frames == NULL) {
3628 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3629 statusbar_push_temporary_msg("There is no file loaded");
3630 return FALSE; /* we failed to go to that packet */
3633 fdata = frame_data_sequence_find(cf->frames, fnumber);
3635 if (fdata == NULL) {
3636 /* we didn't find a packet with that packet number */
3637 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3638 return FALSE; /* we failed to go to that packet */
3640 if (!fdata->flags.passed_dfilter) {
3641 /* that packet currently isn't displayed */
3642 /* XXX - add it to the set of displayed packets? */
3643 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3644 return FALSE; /* we failed to go to that packet */
3647 if (!packet_list_select_row_from_data(fdata)) {
3648 /* We didn't find a row corresponding to this frame.
3649 This means that the frame isn't being displayed currently,
3650 so we can't select it. */
3651 simple_message_box(ESD_TYPE_INFO, NULL,
3652 "The capture file is probably not fully dissected.",
3653 "End of capture exceeded.");
3656 return TRUE; /* we got to that packet */
3660 * Go to frame specified by currently selected protocol tree item.
3663 cf_goto_framenum(capture_file *cf)
3665 header_field_info *hfinfo;
3668 if (cf->finfo_selected) {
3669 hfinfo = cf->finfo_selected->hfinfo;
3671 if (hfinfo->type == FT_FRAMENUM) {
3672 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3674 return cf_goto_frame(cf, framenum);
3681 /* Select the packet on a given row. */
3683 cf_select_packet(capture_file *cf, int row)
3685 epan_dissect_t *old_edt;
3688 /* Get the frame data struct pointer for this frame */
3689 fdata = packet_list_get_row_data(row);
3691 if (fdata == NULL) {
3695 /* Get the data in that frame. */
3696 if (!cf_read_record (cf, fdata)) {
3700 /* Record that this frame is the current frame. */
3701 cf->current_frame = fdata;
3702 cf->current_row = row;
3705 /* Create the logical protocol tree. */
3706 /* We don't need the columns here. */
3707 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3709 tap_build_interesting(cf->edt);
3710 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3711 cf->current_frame, NULL);
3713 dfilter_macro_build_ftv_cache(cf->edt->tree);
3715 cf_callback_invoke(cf_cb_packet_selected, cf);
3717 if (old_edt != NULL)
3718 epan_dissect_free(old_edt);
3722 /* Unselect the selected packet, if any. */
3724 cf_unselect_packet(capture_file *cf)
3726 epan_dissect_t *old_edt = cf->edt;
3730 /* No packet is selected. */
3731 cf->current_frame = NULL;
3732 cf->current_row = 0;
3734 cf_callback_invoke(cf_cb_packet_unselected, cf);
3736 /* No protocol tree means no selected field. */
3737 cf_unselect_field(cf);
3739 /* Destroy the epan_dissect_t for the unselected packet. */
3740 if (old_edt != NULL)
3741 epan_dissect_free(old_edt);
3744 /* Unset the selected protocol tree field, if any. */
3746 cf_unselect_field(capture_file *cf)
3748 cf->finfo_selected = NULL;
3750 cf_callback_invoke(cf_cb_field_unselected, cf);
3754 * Mark a particular frame.
3757 cf_mark_frame(capture_file *cf, frame_data *frame)
3759 if (! frame->flags.marked) {
3760 frame->flags.marked = TRUE;
3761 if (cf->count > cf->marked_count)
3767 * Unmark a particular frame.
3770 cf_unmark_frame(capture_file *cf, frame_data *frame)
3772 if (frame->flags.marked) {
3773 frame->flags.marked = FALSE;
3774 if (cf->marked_count > 0)
3780 * Ignore a particular frame.
3783 cf_ignore_frame(capture_file *cf, frame_data *frame)
3785 if (! frame->flags.ignored) {
3786 frame->flags.ignored = TRUE;
3787 if (cf->count > cf->ignored_count)
3788 cf->ignored_count++;
3793 * Un-ignore a particular frame.
3796 cf_unignore_frame(capture_file *cf, frame_data *frame)
3798 if (frame->flags.ignored) {
3799 frame->flags.ignored = FALSE;
3800 if (cf->ignored_count > 0)
3801 cf->ignored_count--;
3806 * Read the comment in SHB block
3810 cf_read_shb_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 cf_update_capture_comment(capture_file *cf, gchar *comment)
3829 wtap_block_t shb_inf;
3833 /* XXX - support multiple SHBs */
3834 shb_inf = wtap_file_get_shb(cf->wth);
3836 /* Get the first comment from the SHB. */
3837 /* XXX - support multiple comments */
3838 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3839 /* There's no comment - add one. */
3840 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3842 /* See if the comment has changed or not */
3843 if (strcmp(shb_comment, comment) == 0) {
3848 /* The comment has changed, let's update it */
3849 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3851 /* Mark the file as having unsaved changes */
3852 cf->unsaved_changes = TRUE;
3856 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3858 if (cf->frames_user_comments)
3859 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3866 cf_get_comment(capture_file *cf, const frame_data *fd)
3870 /* fetch user comment */
3871 if (fd->flags.has_user_comment)
3872 return g_strdup(cf_get_user_packet_comment(cf, fd));
3874 /* fetch phdr comment */
3875 if (fd->flags.has_phdr_comment) {
3876 struct wtap_pkthdr phdr; /* Packet header */
3877 Buffer buf; /* Packet data */
3879 wtap_phdr_init(&phdr);
3880 ws_buffer_init(&buf, 1500);
3882 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3883 { /* XXX, what we can do here? */ }
3885 comment = phdr.opt_comment;
3886 wtap_phdr_cleanup(&phdr);
3887 ws_buffer_free(&buf);
3894 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3896 const frame_data *fdata1 = (const frame_data *) a;
3897 const frame_data *fdata2 = (const frame_data *) b;
3899 return (fdata1->num < fdata2->num) ? -1 :
3900 (fdata1->num > fdata2->num) ? 1 :
3905 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3907 char *pkt_comment = cf_get_comment(cf, fd);
3909 /* Check if the comment has changed */
3910 if (!g_strcmp0(pkt_comment, new_comment)) {
3911 g_free(pkt_comment);
3914 g_free(pkt_comment);
3917 cf->packet_comment_count--;
3920 cf->packet_comment_count++;
3922 fd->flags.has_user_comment = TRUE;
3924 if (!cf->frames_user_comments)
3925 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3927 /* insert new packet comment */
3928 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3930 expert_update_comment_count(cf->packet_comment_count);
3932 /* OK, we have unsaved changes. */
3933 cf->unsaved_changes = TRUE;
3938 * What types of comments does this capture file have?
3941 cf_comment_types(capture_file *cf)
3943 guint32 comment_types = 0;
3945 if (cf_read_shb_comment(cf) != NULL)
3946 comment_types |= WTAP_COMMENT_PER_SECTION;
3947 if (cf->packet_comment_count != 0)
3948 comment_types |= WTAP_COMMENT_PER_PACKET;
3949 return comment_types;
3953 * Add a resolved address to this file's list of resolved addresses.
3956 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3959 * XXX - support multiple resolved address lists, and add to the one
3960 * attached to this file?
3962 if (!add_ip_name_from_string(addr, name))
3965 /* OK, we have unsaved changes. */
3966 cf->unsaved_changes = TRUE;
3970 #ifdef WANT_PACKET_EDITOR
3972 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3983 modified_frame_data_free(gpointer data)
3985 modified_frame_data *mfd = (modified_frame_data *)data;
3992 * Give a frame new, edited data.
3995 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3996 struct wtap_pkthdr *phdr, guint8 *pd)
3998 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
4001 mfd->pd = (char *)pd;
4003 if (cf->edited_frames == NULL)
4004 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
4005 modified_frame_data_free);
4006 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
4009 /* Mark the file as having unsaved changes */
4010 cf->unsaved_changes = TRUE;
4018 } save_callback_args_t;
4021 * Save a capture to a file, in a particular format, saving either
4022 * all packets, all currently-displayed packets, or all marked packets.
4024 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4025 * up a message box for the failure.
4028 save_record(capture_file *cf, frame_data *fdata,
4029 struct wtap_pkthdr *phdr, const guint8 *pd,
4032 save_callback_args_t *args = (save_callback_args_t *)argsp;
4033 struct wtap_pkthdr hdr;
4036 const char *pkt_comment;
4038 if (fdata->flags.has_user_comment)
4039 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4041 pkt_comment = phdr->opt_comment;
4043 /* init the wtap header for saving */
4044 /* TODO: reuse phdr */
4045 /* XXX - these are the only flags that correspond to data that we have
4046 in the frame_data structure and that matter on a per-packet basis.
4048 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4049 and "on the wire" lengths, or it doesn't.
4051 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4054 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4055 from the packet flags. */
4056 hdr.rec_type = phdr->rec_type;
4057 hdr.presence_flags = 0;
4058 if (fdata->flags.has_ts)
4059 hdr.presence_flags |= WTAP_HAS_TS;
4060 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4061 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4062 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4063 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4065 hdr.caplen = phdr->caplen;
4066 hdr.len = phdr->len;
4067 hdr.pkt_encap = phdr->pkt_encap;
4069 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4071 hdr.pack_flags = phdr->pack_flags;
4072 hdr.opt_comment = g_strdup(pkt_comment);
4075 hdr.pseudo_header = phdr->pseudo_header;
4078 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4080 /* and save the packet */
4081 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
4082 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4087 g_free(hdr.opt_comment);
4092 * Can this capture file be written out in any format using Wiretap
4093 * rather than by copying the raw data?
4096 cf_can_write_with_wiretap(capture_file *cf)
4098 /* We don't care whether we support the comments in this file or not;
4099 if we can't, we'll offer the user the option of discarding the
4101 return wtap_dump_can_write(cf->linktypes, 0);
4105 * Should we let the user do a save?
4109 * the file has unsaved changes, and we can save it in some
4110 * format through Wiretap
4114 * the file is a temporary file and has no unsaved changes (so
4115 * that "saving" it just means copying it).
4117 * XXX - we shouldn't allow files to be edited if they can't be saved,
4118 * so cf->unsaved_changes should be true only if the file can be saved.
4120 * We don't care whether we support the comments in this file or not;
4121 * if we can't, we'll offer the user the option of discarding the
4125 cf_can_save(capture_file *cf)
4127 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4128 /* Saved changes, and we can write it out with Wiretap. */
4132 if (cf->is_tempfile && !cf->unsaved_changes) {
4134 * Temporary file with no unsaved changes, so we can just do a
4140 /* Nothing to save. */
4145 * Should we let the user do a "save as"?
4149 * we can save it in some format through Wiretap
4153 * the file is a temporary file and has no unsaved changes (so
4154 * that "saving" it just means copying it).
4156 * XXX - we shouldn't allow files to be edited if they can't be saved,
4157 * so cf->unsaved_changes should be true only if the file can be saved.
4159 * We don't care whether we support the comments in this file or not;
4160 * if we can't, we'll offer the user the option of discarding the
4164 cf_can_save_as(capture_file *cf)
4166 if (wtap_dump_can_write(cf->linktypes, 0)) {
4167 /* We can write it out with Wiretap. */
4171 if (cf->is_tempfile && !cf->unsaved_changes) {
4173 * Temporary file with no unsaved changes, so we can just do a
4179 /* Nothing to save. */
4184 * Does this file have unsaved data?
4187 cf_has_unsaved_data(capture_file *cf)
4190 * If this is a temporary file, or a file with unsaved changes, it
4193 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4197 * Quick scan to find packet offsets.
4199 static cf_read_status_t
4200 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4202 const struct wtap_pkthdr *phdr;
4207 progdlg_t *progbar = NULL;
4208 GTimer *prog_timer = g_timer_new();
4211 GTimeVal start_time;
4212 gchar status_str[100];
4217 /* Close the old handle. */
4218 wtap_close(cf->wth);
4220 /* Open the new file. */
4221 /* XXX: this will go through all open_routines for a matching one. But right
4222 now rescan_file() is only used when a file is being saved to a different
4223 format than the original, and the user is not given a choice of which
4224 reader to use (only which format to save it in), so doing this makes
4226 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4227 if (cf->wth == NULL) {
4228 cfile_open_failure_alert_box(fname, err, err_info);
4229 return CF_READ_ERROR;
4232 /* We're scanning a file whose contents should be the same as what
4233 we had before, so we don't discard dissection state etc.. */
4236 /* Set the file name because we need it to set the follow stream filter.
4237 XXX - is that still true? We need it for other reasons, though,
4239 cf->filename = g_strdup(fname);
4241 /* Indicate whether it's a permanent or temporary file. */
4242 cf->is_tempfile = is_tempfile;
4244 /* No user changes yet. */
4245 cf->unsaved_changes = FALSE;
4247 cf->cd_t = wtap_file_type_subtype(cf->wth);
4248 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4250 cf->snap = wtap_snapshot_length(cf->wth);
4252 name_ptr = g_filename_display_basename(cf->filename);
4254 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4256 /* Record whether the file is compressed.
4257 XXX - do we know this at open time? */
4258 cf->iscompressed = wtap_iscompressed(cf->wth);
4260 /* Find the size of the file. */
4261 size = wtap_file_size(cf->wth, NULL);
4263 g_timer_start(prog_timer);
4265 cf->stop_flag = FALSE;
4266 g_get_current_time(&start_time);
4269 phdr = wtap_phdr(cf->wth);
4270 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
4272 fdata = frame_data_sequence_find(cf->frames, framenum);
4273 fdata->file_off = data_offset;
4276 cf->f_datalen = wtap_read_so_far(cf->wth);
4278 /* Create the progress bar if necessary. */
4279 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4280 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4281 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4282 TRUE, &cf->stop_flag, &start_time, progbar_val);
4286 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4287 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4288 * likely trigger UI paint events, which might take a while depending on
4289 * the platform and display. Reset our timer *after* painting.
4291 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4292 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4293 /* update the packet bar content on the first run or frequently on very large files */
4294 update_progress_dlg(progbar, progbar_val, status_str);
4295 packets_bar_update();
4296 g_timer_start(prog_timer);
4300 if (cf->stop_flag) {
4301 /* Well, the user decided to abort the rescan. Sadly, as this
4302 isn't a reread, recovering is difficult, so we'll just
4303 close the current capture. */
4307 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4308 it's not already there.
4309 XXX - yes, this is O(N), so if every packet had a different
4310 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4311 there are probably going to be a small number of encapsulation types
4313 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4316 /* Free the display name */
4319 /* We're done reading the file; destroy the progress bar if it was created. */
4320 if (progbar != NULL)
4321 destroy_progress_dlg(progbar);
4322 g_timer_destroy(prog_timer);
4324 /* We're done reading sequentially through the file. */
4325 cf->state = FILE_READ_DONE;
4327 /* Close the sequential I/O side, to free up memory it requires. */
4328 wtap_sequential_close(cf->wth);
4330 /* compute the time it took to load the file */
4331 compute_elapsed(cf, &start_time);
4333 /* Set the file encapsulation type now; we don't know what it is until
4334 we've looked at all the packets, as we don't know until then whether
4335 there's more than one type (and thus whether it's
4336 WTAP_ENCAP_PER_PACKET). */
4337 cf->lnk_t = wtap_file_encap(cf->wth);
4339 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4341 if (cf->stop_flag) {
4342 /* Our caller will give up at this point. */
4343 return CF_READ_ABORTED;
4347 /* Put up a message box noting that the read failed somewhere along
4348 the line. Don't throw out the stuff we managed to read, though,
4350 cfile_read_failure_alert_box(NULL, err, err_info);
4351 return CF_READ_ERROR;
4357 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4358 gboolean compressed, gboolean discard_comments,
4359 gboolean dont_reopen)
4362 gchar *fname_new = NULL;
4365 addrinfo_lists_t *addr_lists;
4369 gchar *display_basename;
4376 save_callback_args_t callback_args;
4378 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4380 addr_lists = get_addrinfo_list();
4382 if (save_format == cf->cd_t && compressed == cf->iscompressed
4383 && !discard_comments && !cf->unsaved_changes
4384 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4385 /* We're saving in the format it's already in, and we're
4386 not discarding comments, and there are no changes we have
4387 in memory that aren't saved to the file, and we have no name
4388 resolution blocks to write, so we can just move or copy the raw data. */
4390 if (cf->is_tempfile) {
4391 /* The file being saved is a temporary file from a live
4392 capture, so it doesn't need to stay around under that name;
4393 first, try renaming the capture buffer file to the new name.
4394 This acts as a "safe save", in that, if the file already
4395 exists, the existing file will be removed only if the rename
4398 Sadly, on Windows, as we have the current capture file
4399 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4400 (to cause the rename to remove an existing target), as
4401 done by ws_stdio_rename() (ws_rename() is #defined to
4402 be ws_stdio_rename() on Windows) will fail.
4404 According to the MSDN documentation for CreateFile(), if,
4405 when we open a capture file, we were to directly do a CreateFile(),
4406 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4407 convert it to a file descriptor with _open_osfhandle(),
4408 that would allow the file to be renamed out from under us.
4410 However, that doesn't work in practice. Perhaps the problem
4411 is that the process doing the rename is the process that
4412 has the file open. */
4414 if (ws_rename(cf->filename, fname) == 0) {
4415 /* That succeeded - there's no need to copy the source file. */
4416 how_to_save = SAVE_WITH_MOVE;
4418 if (errno == EXDEV) {
4419 /* They're on different file systems, so we have to copy the
4421 how_to_save = SAVE_WITH_COPY;
4423 /* The rename failed, but not because they're on different
4424 file systems - put up an error message. (Or should we
4425 just punt and try to copy? The only reason why I'd
4426 expect the rename to fail and the copy to succeed would
4427 be if we didn't have permission to remove the file from
4428 the temporary directory, and that might be fixable - but
4429 is it worth requiring the user to go off and fix it?) */
4430 cf_rename_failure_alert_box(fname, errno);
4435 how_to_save = SAVE_WITH_COPY;
4438 /* It's a permanent file, so we should copy it, and not remove the
4440 how_to_save = SAVE_WITH_COPY;
4443 if (how_to_save == SAVE_WITH_COPY) {
4444 /* Copy the file, if we haven't moved it. If we're overwriting
4445 an existing file, we do it with a "safe save", by writing
4446 to a new file and, if the write succeeds, renaming the
4447 new file on top of the old file. */
4448 if (file_exists(fname)) {
4449 fname_new = g_strdup_printf("%s~", fname);
4450 if (!copy_file_binary_mode(cf->filename, fname_new))
4453 if (!copy_file_binary_mode(cf->filename, fname))
4458 /* Either we're saving in a different format or we're saving changes,
4459 such as added, modified, or removed comments, that haven't yet
4460 been written to the underlying file; we can't do that by copying
4461 or moving the capture file, we have to do it by writing the packets
4464 GArray *shb_hdrs = NULL;
4465 wtapng_iface_descriptions_t *idb_inf = NULL;
4466 GArray *nrb_hdrs = NULL;
4469 /* XXX: what free's this shb_hdr? */
4470 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4471 idb_inf = wtap_file_get_idb_info(cf->wth);
4472 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4474 /* Determine what file encapsulation type we should use. */
4475 encap = wtap_dump_file_encap_type(cf->linktypes);
4477 if (file_exists(fname)) {
4478 /* We're overwriting an existing file; write out to a new file,
4479 and, if that succeeds, rename the new file on top of the
4480 old file. That makes this a "safe save", so that we don't
4481 lose the old file if we have a problem writing out the new
4482 file. (If the existing file is the current capture file,
4483 we *HAVE* to do that, otherwise we're overwriting the file
4484 from which we're reading the packets that we're writing!) */
4485 fname_new = g_strdup_printf("%s~", fname);
4486 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4487 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4489 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4490 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4496 cfile_dump_open_failure_alert_box(fname, err, save_format);
4500 /* Add address resolution */
4501 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4503 /* Iterate through the list of packets, processing all the packets. */
4504 callback_args.pdh = pdh;
4505 callback_args.fname = fname;
4506 callback_args.file_type = save_format;
4507 switch (process_specified_records(cf, NULL, "Saving", "packets",
4508 TRUE, save_record, &callback_args, TRUE)) {
4511 /* Completed successfully. */
4515 /* The user decided to abort the saving.
4516 If we're writing to a temporary file, remove it.
4517 XXX - should we do so even if we're not writing to a
4519 wtap_dump_close(pdh, &err);
4520 if (fname_new != NULL)
4521 ws_unlink(fname_new);
4522 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4523 return CF_WRITE_ABORTED;
4526 /* Error while saving.
4527 If we're writing to a temporary file, remove it. */
4528 if (fname_new != NULL)
4529 ws_unlink(fname_new);
4530 wtap_dump_close(pdh, &err);
4534 if (!wtap_dump_close(pdh, &err)) {
4535 cfile_close_failure_alert_box(fname, err);
4539 how_to_save = SAVE_WITH_WTAP;
4542 if (fname_new != NULL) {
4543 /* We wrote out to fname_new, and should rename it on top of
4544 fname. fname_new is now closed, so that should be possible even
4545 on Windows. However, on Windows, we first need to close whatever
4546 file descriptors we have open for fname. */
4548 wtap_fdclose(cf->wth);
4550 /* Now do the rename. */
4551 if (ws_rename(fname_new, fname) == -1) {
4552 /* Well, the rename failed. */
4553 cf_rename_failure_alert_box(fname, errno);
4555 /* Attempt to reopen the random file descriptor using the
4556 current file's filename. (At this point, the sequential
4557 file descriptor is closed.) */
4558 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4559 /* Oh, well, we're screwed. */
4560 display_basename = g_filename_display_basename(cf->filename);
4561 simple_error_message_box(
4562 file_open_error_message(err, FALSE), display_basename);
4563 g_free(display_basename);
4570 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4571 cf->unsaved_changes = FALSE;
4574 switch (how_to_save) {
4576 case SAVE_WITH_MOVE:
4577 /* We just moved the file, so the wtap structure refers to the
4578 new file, and all the information other than the filename
4579 and the "is temporary" status applies to the new file; just
4581 g_free(cf->filename);
4582 cf->filename = g_strdup(fname);
4583 cf->is_tempfile = FALSE;
4584 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4587 case SAVE_WITH_COPY:
4588 /* We just copied the file, s all the information other than
4589 the wtap structure, the filename, and the "is temporary"
4590 status applies to the new file; just update that. */
4591 wtap_close(cf->wth);
4592 /* Although we're just "copying" and then opening the copy, it will
4593 try all open_routine readers to open the copy, so we need to
4594 reset the cfile's open_type. */
4595 cf->open_type = WTAP_TYPE_AUTO;
4596 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4597 if (cf->wth == NULL) {
4598 cfile_open_failure_alert_box(fname, err, err_info);
4601 g_free(cf->filename);
4602 cf->filename = g_strdup(fname);
4603 cf->is_tempfile = FALSE;
4605 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4608 case SAVE_WITH_WTAP:
4609 /* Open and read the file we saved to.
4611 XXX - this is somewhat of a waste; we already have the
4612 packets, all this gets us is updated file type information
4613 (which we could just stuff into "cf"), and having the new
4614 file be the one we have opened and from which we're reading
4615 the data, and it means we have to spend time opening and
4616 reading the file, which could be a significant amount of
4617 time if the file is large.
4619 If the capture-file-writing code were to return the
4620 seek offset of each packet it writes, we could save that
4621 in the frame_data structure for the frame, and just open
4622 the file without reading it again...
4624 ...as long as, for gzipped files, the process of writing
4625 out the file *also* generates the information needed to
4626 support fast random access to the compressed file. */
4627 /* rescan_file will cause us to try all open_routines, so
4628 reset cfile's open_type */
4629 cf->open_type = WTAP_TYPE_AUTO;
4630 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4631 /* The rescan failed; just close the file. Either
4632 a dialog was popped up for the failure, so the
4633 user knows what happened, or they stopped the
4634 rescan, in which case they know what happened. */
4640 /* If we were told to discard the comments, do so. */
4641 if (discard_comments) {
4642 /* Remove SHB comment, if any. */
4643 wtap_write_shb_comment(cf->wth, NULL);
4645 /* remove all user comments */
4646 for (framenum = 1; framenum <= cf->count; framenum++) {
4647 fdata = frame_data_sequence_find(cf->frames, framenum);
4649 fdata->flags.has_phdr_comment = FALSE;
4650 fdata->flags.has_user_comment = FALSE;
4653 if (cf->frames_user_comments) {
4654 g_tree_destroy(cf->frames_user_comments);
4655 cf->frames_user_comments = NULL;
4658 cf->packet_comment_count = 0;
4664 if (fname_new != NULL) {
4665 /* We were trying to write to a temporary file; get rid of it if it
4666 exists. (We don't care whether this fails, as, if it fails,
4667 there's not much we can do about it. I guess if it failed for
4668 a reason other than "it doesn't exist", we could report an
4669 error, so the user knows there's a junk file that they might
4670 want to clean up.) */
4671 ws_unlink(fname_new);
4674 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4675 return CF_WRITE_ERROR;
4679 cf_export_specified_packets(capture_file *cf, const char *fname,
4680 packet_range_t *range, guint save_format,
4681 gboolean compressed)
4683 gchar *fname_new = NULL;
4686 save_callback_args_t callback_args;
4687 GArray *shb_hdrs = NULL;
4688 wtapng_iface_descriptions_t *idb_inf = NULL;
4689 GArray *nrb_hdrs = NULL;
4692 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4694 packet_range_process_init(range);
4696 /* We're writing out specified packets from the specified capture
4697 file to another file. Even if all captured packets are to be
4698 written, don't special-case the operation - read each packet
4699 and then write it out if it's one of the specified ones. */
4701 /* XXX: what free's this shb_hdr? */
4702 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4703 idb_inf = wtap_file_get_idb_info(cf->wth);
4704 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4706 /* Determine what file encapsulation type we should use. */
4707 encap = wtap_dump_file_encap_type(cf->linktypes);
4709 if (file_exists(fname)) {
4710 /* We're overwriting an existing file; write out to a new file,
4711 and, if that succeeds, rename the new file on top of the
4712 old file. That makes this a "safe save", so that we don't
4713 lose the old file if we have a problem writing out the new
4714 file. (If the existing file is the current capture file,
4715 we *HAVE* to do that, otherwise we're overwriting the file
4716 from which we're reading the packets that we're writing!) */
4717 fname_new = g_strdup_printf("%s~", fname);
4718 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4719 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4721 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4722 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4728 cfile_dump_open_failure_alert_box(fname, err, save_format);
4732 /* Add address resolution */
4733 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4735 /* Iterate through the list of packets, processing the packets we were
4738 XXX - we've already called "packet_range_process_init(range)", but
4739 "process_specified_records()" will do it again. Fortunately,
4740 that's harmless in this case, as we haven't done anything to
4741 "range" since we initialized it. */
4742 callback_args.pdh = pdh;
4743 callback_args.fname = fname;
4744 callback_args.file_type = save_format;
4745 switch (process_specified_records(cf, range, "Writing", "specified records",
4746 TRUE, save_record, &callback_args, TRUE)) {
4749 /* Completed successfully. */
4753 /* The user decided to abort the saving.
4754 If we're writing to a temporary file, remove it.
4755 XXX - should we do so even if we're not writing to a
4757 wtap_dump_close(pdh, &err);
4758 if (fname_new != NULL)
4759 ws_unlink(fname_new);
4760 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4761 return CF_WRITE_ABORTED;
4765 /* Error while saving.
4766 If we're writing to a temporary file, remove it. */
4767 if (fname_new != NULL)
4768 ws_unlink(fname_new);
4769 wtap_dump_close(pdh, &err);
4773 if (!wtap_dump_close(pdh, &err)) {
4774 cfile_close_failure_alert_box(fname, err);
4778 if (fname_new != NULL) {
4779 /* We wrote out to fname_new, and should rename it on top of
4780 fname; fname is now closed, so that should be possible even
4781 on Windows. Do the rename. */
4782 if (ws_rename(fname_new, fname) == -1) {
4783 /* Well, the rename failed. */
4784 cf_rename_failure_alert_box(fname, errno);
4789 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4793 if (fname_new != NULL) {
4794 /* We were trying to write to a temporary file; get rid of it if it
4795 exists. (We don't care whether this fails, as, if it fails,
4796 there's not much we can do about it. I guess if it failed for
4797 a reason other than "it doesn't exist", we could report an
4798 error, so the user knows there's a junk file that they might
4799 want to clean up.) */
4800 ws_unlink(fname_new);
4803 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4804 return CF_WRITE_ERROR;
4808 * XXX - whether we mention the source pathname, the target pathname,
4809 * or both depends on the error and on what we find if we look for
4810 * one or both of them.
4813 cf_rename_failure_alert_box(const char *filename, int err)
4815 gchar *display_basename;
4817 display_basename = g_filename_display_basename(filename);
4821 /* XXX - should check whether the source exists and, if not,
4822 report it as the problem and, if so, report the destination
4824 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4829 /* XXX - if we're doing a rename after a safe save, we should
4830 probably say something else. */
4831 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4836 /* XXX - this should probably mention both the source and destination
4838 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4839 display_basename, wtap_strerror(err));
4842 g_free(display_basename);
4845 /* Reload the current capture file. */
4847 cf_reload(capture_file *cf) {
4849 gboolean is_tempfile;
4852 /* If the file could be opened, "cf_open()" calls "cf_close()"
4853 to get rid of state for the old capture file before filling in state
4854 for the new capture file. "cf_close()" will remove the file if
4855 it's a temporary file; we don't want that to happen (for one thing,
4856 it'd prevent subsequent reopens from working). Remember whether it's
4857 a temporary file, mark it as not being a temporary file, and then
4858 reopen it as the type of file it was.
4860 Also, "cf_close()" will free "cf->filename", so we must make
4861 a copy of it first. */
4862 filename = g_strdup(cf->filename);
4863 is_tempfile = cf->is_tempfile;
4864 cf->is_tempfile = FALSE;
4865 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4866 switch (cf_read(cf, TRUE)) {
4870 /* Just because we got an error, that doesn't mean we were unable
4871 to read any of the file; we handle what we could get from the
4875 case CF_READ_ABORTED:
4876 /* The user bailed out of re-reading the capture file; the
4877 capture file has been closed - just free the capture file name
4878 string and return (without changing the last containing
4884 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4885 Instead, the file was left open, so we should restore "cf->is_tempfile"
4888 XXX - change the menu? Presumably "cf_open()" will do that;
4889 make sure it does! */
4890 cf->is_tempfile = is_tempfile;
4892 /* "cf_open()" made a copy of the file name we handed it, so
4893 we should free up our copy. */
4903 * indent-tabs-mode: nil
4906 * ex: set shiftwidth=2 tabstop=8 expandtab:
4907 * :indentSize=2:tabSize=8:noTabs=true: