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 /* Snapshot length not known. */
347 cf->has_snap = FALSE;
348 cf->snap = WTAP_MAX_PACKET_SIZE;
352 /* Allocate a frame_data_sequence for the frames in this file */
353 cf->frames = new_frame_data_sequence();
355 nstime_set_zero(&cf->elapsed_time);
361 packet_list_queue_draw();
362 cf_callback_invoke(cf_cb_file_opened, cf);
364 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
365 /* tell the BER dissector the file name */
366 ber_set_filename(cf->filename);
369 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
370 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
375 cfile_open_failure_alert_box(fname, *err, err_info);
380 * Add an encapsulation type to cf->linktypes.
383 cf_add_encapsulation_type(capture_file *cf, int encap)
387 for (i = 0; i < cf->linktypes->len; i++) {
388 if (g_array_index(cf->linktypes, gint, i) == encap)
389 return; /* it's already there */
391 /* It's not already there - add it. */
392 g_array_append_val(cf->linktypes, encap);
395 /* Reset everything to a pristine state */
397 cf_close(capture_file *cf)
399 cf->stop_flag = FALSE;
400 if (cf->state == FILE_CLOSED)
401 return; /* Nothing to do */
403 /* Die if we're in the middle of reading a file. */
404 g_assert(cf->state != FILE_READ_IN_PROGRESS);
406 cf_callback_invoke(cf_cb_file_closing, cf);
408 /* close things, if not already closed before */
409 color_filters_cleanup();
415 /* We have no file open... */
416 if (cf->filename != NULL) {
417 /* If it's a temporary file, remove it. */
419 ws_unlink(cf->filename);
420 g_free(cf->filename);
423 /* ...which means we have no changes to that file to save. */
424 cf->unsaved_changes = FALSE;
426 /* no open_routine type */
427 cf->open_type = WTAP_TYPE_AUTO;
429 /* Clean up the packet header. */
430 wtap_phdr_cleanup(&cf->phdr);
432 /* Free up the packet buffer. */
433 ws_buffer_free(&cf->buf);
435 dfilter_free(cf->rfcode);
437 if (cf->frames != NULL) {
438 free_frame_data_sequence(cf->frames);
441 #ifdef WANT_PACKET_EDITOR
442 if (cf->edited_frames) {
443 g_tree_destroy(cf->edited_frames);
444 cf->edited_frames = NULL;
447 if (cf->frames_user_comments) {
448 g_tree_destroy(cf->frames_user_comments);
449 cf->frames_user_comments = NULL;
451 cf_unselect_packet(cf); /* nothing to select */
452 cf->first_displayed = 0;
453 cf->last_displayed = 0;
455 /* No frames, no frame selected, no field in that frame selected. */
457 cf->current_frame = 0;
459 cf->finfo_selected = NULL;
461 /* No frame link-layer types, either. */
462 if (cf->linktypes != NULL) {
463 g_array_free(cf->linktypes, TRUE);
464 cf->linktypes = NULL;
467 /* Clear the packet list. */
468 packet_list_freeze();
473 nstime_set_zero(&cf->elapsed_time);
475 reset_tap_listeners();
480 /* We have no file open. */
481 cf->state = FILE_CLOSED;
483 cf_callback_invoke(cf_cb_file_closed, cf);
487 * TRUE if the progress dialog doesn't exist and it looks like we'll
488 * take > 2s to load, FALSE otherwise.
490 static inline gboolean
491 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
495 if (progdlg) return FALSE;
496 elapsed = g_timer_elapsed(prog_timer, NULL);
497 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
498 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
505 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
509 progbar_val = (gfloat) file_pos / (gfloat) size;
510 if (progbar_val > 1.0) {
512 /* The file probably grew while we were reading it.
513 * Update file size, and try again.
515 size = wtap_file_size(cf->wth, NULL);
518 progbar_val = (gfloat) file_pos / (gfloat) size;
520 /* If it's still > 1, either "wtap_file_size()" failed (in which
521 * case there's not much we can do about it), or the file
522 * *shrank* (in which case there's not much we can do about
523 * it); just clip the progress value at 1.0.
525 if (progbar_val > 1.0f)
529 g_snprintf(status_str, status_size,
530 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
531 file_pos / 1024, size / 1024);
537 cf_read(capture_file *cf, gboolean reloading)
540 gchar *err_info = NULL;
542 progdlg_t *volatile progbar = NULL;
543 GTimer *prog_timer = g_timer_new();
547 volatile gboolean create_proto_tree;
551 /* Compile the current display filter.
552 * We assume this will not fail since cf->dfilter is only set in
553 * cf_filter IFF the filter was valid.
555 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
556 g_assert(!cf->dfilter || (compiled && dfcode));
558 /* Get the union of the flags for all tap listeners. */
559 tap_flags = union_of_tap_listener_flags();
562 * Determine whether we need to create a protocol tree.
565 * we're going to apply a display filter;
567 * one of the tap listeners is going to apply a filter;
569 * one of the tap listeners requires a protocol tree;
571 * a postdissector wants field values or protocols on
575 (dfcode != NULL || have_filtering_tap_listeners() ||
576 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
578 reset_tap_listeners();
580 name_ptr = g_filename_display_basename(cf->filename);
583 cf_callback_invoke(cf_cb_file_reload_started, cf);
585 cf_callback_invoke(cf_cb_file_read_started, cf);
587 /* Record whether the file is compressed.
588 XXX - do we know this at open time? */
589 cf->iscompressed = wtap_iscompressed(cf->wth);
591 /* The packet list window will be empty until the file is completly loaded */
592 packet_list_freeze();
594 cf->stop_flag = FALSE;
595 g_get_current_time(&start_time);
597 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
607 gchar status_str[100];
611 /* If any tap listeners require the columns, construct them. */
612 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
614 /* Find the size of the file. */
615 size = wtap_file_size(cf->wth, NULL);
617 g_timer_start(prog_timer);
619 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
622 file_pos = wtap_read_so_far(cf->wth);
624 /* Create the progress bar if necessary. */
625 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
626 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
628 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
629 TRUE, &cf->stop_flag, &start_time, progbar_val);
631 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
632 TRUE, &cf->stop_flag, &start_time, progbar_val);
636 * Update the progress bar, but do it only after
637 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
638 * and packets_bar_update will likely trigger UI paint events, which
639 * might take a while depending on the platform and display. Reset
640 * our timer *after* painting.
642 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
643 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
644 /* update the packet bar content on the first run or frequently on very large files */
645 update_progress_dlg(progbar, progbar_val, status_str);
646 packets_bar_update();
647 g_timer_start(prog_timer);
652 /* Well, the user decided to abort the read. He/She will be warned and
653 it might be enough for him/her to work with the already loaded
655 This is especially true for very large capture files, where you don't
656 want to wait loading the whole file (which may last minutes or even
657 hours even on fast machines) just to see that it was the wrong file. */
660 read_packet(cf, dfcode, &edt, cinfo, data_offset);
663 CATCH(OutOfMemoryError) {
664 simple_message_box(ESD_TYPE_ERROR, NULL,
665 "More information and workarounds can be found at\n"
666 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
667 "Sorry, but Wireshark has run out of memory and has to terminate now.");
669 /* Could we close the current capture and free up memory from that? */
671 /* we have to terminate, as we cannot recover from the memory error */
677 /* Free the display name */
680 /* Cleanup and release all dfilter resources */
681 if (dfcode != NULL) {
682 dfilter_free(dfcode);
685 epan_dissect_cleanup(&edt);
687 /* We're done reading the file; destroy the progress bar if it was created. */
689 destroy_progress_dlg(progbar);
690 g_timer_destroy(prog_timer);
692 /* We're done reading sequentially through the file. */
693 cf->state = FILE_READ_DONE;
695 /* Close the sequential I/O side, to free up memory it requires. */
696 wtap_sequential_close(cf->wth);
698 /* Allow the protocol dissectors to free up memory that they
699 * don't need after the sequential run-through of the packets. */
700 postseq_cleanup_all_protocols();
702 /* compute the time it took to load the file */
703 compute_elapsed(cf, &start_time);
705 /* Set the file encapsulation type now; we don't know what it is until
706 we've looked at all the packets, as we don't know until then whether
707 there's more than one type (and thus whether it's
708 WTAP_ENCAP_PER_PACKET). */
709 cf->lnk_t = wtap_file_encap(cf->wth);
711 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
716 cf_callback_invoke(cf_cb_file_reload_finished, cf);
718 cf_callback_invoke(cf_cb_file_read_finished, cf);
720 /* If we have any displayed packets to select, select the first of those
721 packets by making the first row the selected row. */
722 if (cf->first_displayed != 0) {
723 packet_list_select_first_row();
727 simple_message_box(ESD_TYPE_WARN, NULL,
728 "The remaining packets in the file were discarded.\n"
730 "As a lot of packets from the original file will be missing,\n"
731 "remember to be careful when saving the current content to a file.\n",
732 "File loading was cancelled.");
733 return CF_READ_ERROR;
737 /* Put up a message box noting that the read failed somewhere along
738 the line. Don't throw out the stuff we managed to read, though,
740 cfile_read_failure_alert_box(NULL, err, err_info);
741 return CF_READ_ERROR;
748 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
751 volatile int newly_displayed_packets = 0;
754 gboolean create_proto_tree;
758 /* Compile the current display filter.
759 * We assume this will not fail since cf->dfilter is only set in
760 * cf_filter IFF the filter was valid.
762 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
763 g_assert(!cf->dfilter || (compiled && dfcode));
765 /* Get the union of the flags for all tap listeners. */
766 tap_flags = union_of_tap_listener_flags();
769 * Determine whether we need to create a protocol tree.
772 * we're going to apply a display filter;
774 * one of the tap listeners is going to apply a filter;
776 * one of the tap listeners requires a protocol tree;
778 * a postdissector wants field values or protocols on
782 (dfcode != NULL || have_filtering_tap_listeners() ||
783 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
787 packet_list_check_end();
788 /* Don't freeze/thaw the list when doing live capture */
789 /*packet_list_freeze();*/
791 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
793 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
796 gint64 data_offset = 0;
799 /* If any tap listeners require the columns, construct them. */
800 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
802 while (to_read != 0) {
803 wtap_cleareof(cf->wth);
804 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
807 if (cf->state == FILE_READ_ABORTED) {
808 /* Well, the user decided to exit Wireshark. Break out of the
809 loop, and let the code below (which is called even if there
810 aren't any packets left to read) exit. */
813 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
814 newly_displayed_packets++;
819 CATCH(OutOfMemoryError) {
820 simple_message_box(ESD_TYPE_ERROR, NULL,
821 "More information and workarounds can be found at\n"
822 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
823 "Sorry, but Wireshark has run out of memory and has to terminate now.");
825 /* Could we close the current capture and free up memory from that? */
826 return CF_READ_ABORTED;
828 /* we have to terminate, as we cannot recover from the memory error */
834 /* Update the file encapsulation; it might have changed based on the
835 packets we've read. */
836 cf->lnk_t = wtap_file_encap(cf->wth);
838 /* Cleanup and release all dfilter resources */
839 if (dfcode != NULL) {
840 dfilter_free(dfcode);
843 epan_dissect_cleanup(&edt);
845 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
846 cf->count, cf->state, *err);*/
848 /* Don't freeze/thaw the list when doing live capture */
849 /*packet_list_thaw();*/
850 /* With the new packet list the first packet
851 * isn't automatically selected.
853 if (!cf->current_frame)
854 packet_list_select_first_row();
856 /* moving to the end of the packet list - if the user requested so and
857 we have some new packets. */
858 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
859 packet_list_moveto_end();
861 if (cf->state == FILE_READ_ABORTED) {
862 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
863 so that our caller can kill off the capture child process;
864 this will cause an EOF on the pipe from the child, so
865 "cf_finish_tail()" will be called, and it will clean up
867 return CF_READ_ABORTED;
868 } else if (*err != 0) {
869 /* We got an error reading the capture file.
870 XXX - pop up a dialog box instead? */
871 if (err_info != NULL) {
872 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
873 wtap_strerror(*err), cf->filename, err_info);
876 g_warning("Error \"%s\" while reading \"%s\"",
877 wtap_strerror(*err), cf->filename);
879 return CF_READ_ERROR;
885 cf_fake_continue_tail(capture_file *cf) {
886 cf->state = FILE_READ_DONE;
890 cf_finish_tail(capture_file *cf, int *err)
897 gboolean create_proto_tree;
901 /* Compile the current display filter.
902 * We assume this will not fail since cf->dfilter is only set in
903 * cf_filter IFF the filter was valid.
905 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
906 g_assert(!cf->dfilter || (compiled && dfcode));
908 /* Get the union of the flags for all tap listeners. */
909 tap_flags = union_of_tap_listener_flags();
911 /* If any tap listeners require the columns, construct them. */
912 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
915 * Determine whether we need to create a protocol tree.
918 * we're going to apply a display filter;
920 * one of the tap listeners is going to apply a filter;
922 * one of the tap listeners requires a protocol tree;
924 * a postdissector wants field values or protocols on
928 (dfcode != NULL || have_filtering_tap_listeners() ||
929 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
931 if (cf->wth == NULL) {
933 return CF_READ_ERROR;
936 packet_list_check_end();
937 /* Don't freeze/thaw the list when doing live capture */
938 /*packet_list_freeze();*/
940 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
942 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
943 if (cf->state == FILE_READ_ABORTED) {
944 /* Well, the user decided to abort the read. Break out of the
945 loop, and let the code below (which is called even if there
946 aren't any packets left to read) exit. */
949 read_packet(cf, dfcode, &edt, cinfo, data_offset);
952 /* Cleanup and release all dfilter resources */
953 if (dfcode != NULL) {
954 dfilter_free(dfcode);
957 epan_dissect_cleanup(&edt);
959 /* Don't freeze/thaw the list when doing live capture */
960 /*packet_list_thaw();*/
962 if (cf->state == FILE_READ_ABORTED) {
963 /* Well, the user decided to abort the read. We're only called
964 when the child capture process closes the pipe to us (meaning
965 it's probably exited), so we can just close the capture
966 file; we return CF_READ_ABORTED so our caller can do whatever
967 is appropriate when that happens. */
969 return CF_READ_ABORTED;
972 if (auto_scroll_live && cf->count != 0)
973 packet_list_moveto_end();
975 /* We're done reading sequentially through the file. */
976 cf->state = FILE_READ_DONE;
978 /* We're done reading sequentially through the file; close the
979 sequential I/O side, to free up memory it requires. */
980 wtap_sequential_close(cf->wth);
982 /* Allow the protocol dissectors to free up memory that they
983 * don't need after the sequential run-through of the packets. */
984 postseq_cleanup_all_protocols();
986 /* Update the file encapsulation; it might have changed based on the
987 packets we've read. */
988 cf->lnk_t = wtap_file_encap(cf->wth);
990 /* Update the details in the file-set dialog, as the capture file
991 * has likely grown since we first stat-ed it */
992 fileset_update_file(cf->filename);
995 /* We got an error reading the capture file.
996 XXX - pop up a dialog box? */
997 if (err_info != NULL) {
998 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
999 wtap_strerror(*err), cf->filename, err_info);
1002 g_warning("Error \"%s\" while reading \"%s\"",
1003 wtap_strerror(*err), cf->filename);
1005 return CF_READ_ERROR;
1010 #endif /* HAVE_LIBPCAP */
1013 cf_get_display_name(capture_file *cf)
1017 /* Return a name to use in displays */
1018 if (!cf->is_tempfile) {
1019 /* Get the last component of the file name, and use that. */
1021 displayname = g_filename_display_basename(cf->filename);
1023 displayname=g_strdup("(No file)");
1026 /* The file we read is a temporary file from a live capture or
1027 a merge operation; we don't mention its name, but, if it's
1028 from a capture, give the source of the capture. */
1030 displayname = g_strdup(cf->source);
1032 displayname = g_strdup("(Untitled)");
1038 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1044 cf->source = g_strdup(source);
1046 cf->source = g_strdup("");
1050 const gchar *cf_get_tempfile_source(capture_file *cf) {
1058 /* XXX - use a macro instead? */
1060 cf_get_packet_count(capture_file *cf)
1065 /* XXX - use a macro instead? */
1067 cf_is_tempfile(capture_file *cf)
1069 return cf->is_tempfile;
1072 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1074 cf->is_tempfile = is_tempfile;
1078 /* XXX - use a macro instead? */
1079 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1081 cf->drops_known = drops_known;
1084 /* XXX - use a macro instead? */
1085 void cf_set_drops(capture_file *cf, guint32 drops)
1090 /* XXX - use a macro instead? */
1091 gboolean cf_get_drops_known(capture_file *cf)
1093 return cf->drops_known;
1096 /* XXX - use a macro instead? */
1097 guint32 cf_get_drops(capture_file *cf)
1102 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1104 cf->rfcode = rfcode;
1108 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1109 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1110 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1114 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1115 &cf->ref, cf->prev_dis);
1116 cf->prev_cap = fdata;
1118 if (dfcode != NULL) {
1119 epan_dissect_prime_with_dfilter(edt, dfcode);
1122 /* Prepare coloring rules, this ensures that display filter rules containing
1123 * frame.color_rule references are still processed.
1124 * TODO: actually detect that situation or maybe apply other optimizations? */
1125 if (edt->tree && color_filters_used()) {
1126 color_filters_prime_edt(edt);
1127 fdata->flags.need_colorize = 1;
1131 if (!fdata->flags.visited) {
1132 /* This is the first pass, so prime the epan_dissect_t with the
1133 hfids postdissectors want on the first pass. */
1134 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1137 /* Dissect the frame. */
1138 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1140 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1141 if (dfcode != NULL) {
1142 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1144 if (fdata->flags.passed_dfilter) {
1145 /* This frame passed the display filter but it may depend on other
1146 * (potentially not displayed) frames. Find those frames and mark them
1149 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1152 fdata->flags.passed_dfilter = 1;
1154 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1155 cf->displayed_count++;
1157 if (add_to_packet_list) {
1158 /* We fill the needed columns from new_packet_list */
1159 row = packet_list_append(cinfo, fdata);
1162 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1164 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1165 cf->prev_dis = fdata;
1167 /* If we haven't yet seen the first frame, this is it. */
1168 if (cf->first_displayed == 0)
1169 cf->first_displayed = fdata->num;
1171 /* This is the last frame we've seen so far. */
1172 cf->last_displayed = fdata->num;
1175 epan_dissect_reset(edt);
1179 /* read in a new packet */
1180 /* returns the row of the new packet in the packet list or -1 if not displayed */
1182 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1183 column_info *cinfo, gint64 offset)
1185 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1186 const guint8 *buf = wtap_buf_ptr(cf->wth);
1190 gboolean passed = TRUE;
1193 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1194 it's not already there.
1195 XXX - yes, this is O(N), so if every packet had a different
1196 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1197 there are probably going to be a small number of encapsulation types
1199 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1201 /* The frame number of this packet is one more than the count of
1202 frames in the file so far. */
1203 framenum = cf->count + 1;
1205 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1208 epan_dissect_t rf_edt;
1210 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1211 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1212 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1213 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1214 epan_dissect_cleanup(&rf_edt);
1218 /* This does a shallow copy of fdlocal, which is good enough. */
1219 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1222 if (phdr->opt_comment != NULL)
1223 cf->packet_comment_count++;
1224 cf->f_datalen = offset + fdlocal.cap_len;
1226 if (!cf->redissecting) {
1227 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1228 cinfo, phdr, buf, TRUE);
1236 typedef struct _callback_data_t {
1239 GTimeVal start_time;
1247 merge_callback(merge_event event, int num _U_,
1248 const merge_in_file_t in_files[], const guint in_file_count,
1252 callback_data_t *cb_data = (callback_data_t*) data;
1254 g_assert(cb_data != NULL);
1258 case MERGE_EVENT_INPUT_FILES_OPENED:
1262 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1266 case MERGE_EVENT_READY_TO_MERGE:
1267 /* Get the sum of the sizes of all the files. */
1268 for (i = 0; i < in_file_count; i++)
1269 cb_data->f_len += in_files[i].size;
1271 cb_data->prog_timer = g_timer_new();
1272 g_timer_start(cb_data->prog_timer);
1274 g_get_current_time(&cb_data->start_time);
1277 case MERGE_EVENT_PACKET_WAS_READ:
1279 gint64 data_offset = 0;
1281 /* Get the sum of the data offsets in all of the files. */
1283 for (i = 0; i < in_file_count; i++)
1284 data_offset += in_files[i].data_offset;
1286 /* Create the progress bar if necessary.
1287 We check on every iteration of the loop, so that it takes no
1288 longer than the standard time to create it (otherwise, for a
1289 large file, we might take considerably longer than that standard
1290 time in order to get to the next progress bar step). */
1291 if (cb_data->progbar == NULL) {
1292 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1293 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1297 * Update the progress bar, but do it only after
1298 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1299 * and packets_bar_update will likely trigger UI paint events, which
1300 * might take a while depending on the platform and display. Reset
1301 * our timer *after* painting.
1303 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1305 gint64 file_pos = 0;
1306 /* Get the sum of the seek positions in all of the files. */
1307 for (i = 0; i < in_file_count; i++)
1308 file_pos += wtap_read_so_far(in_files[i].wth);
1310 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1311 if (progbar_val > 1.0f) {
1312 /* Some file probably grew while we were reading it.
1313 That "shouldn't happen", so we'll just clip the progress
1318 if (cb_data->progbar != NULL) {
1319 gchar status_str[100];
1320 g_snprintf(status_str, sizeof(status_str),
1321 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1322 file_pos / 1024, cb_data->f_len / 1024);
1323 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1325 g_timer_start(cb_data->prog_timer);
1330 case MERGE_EVENT_DONE:
1331 /* We're done merging the files; destroy the progress bar if it was created. */
1332 if (cb_data->progbar != NULL)
1333 destroy_progress_dlg(cb_data->progbar);
1334 g_timer_destroy(cb_data->prog_timer);
1338 return cb_data->stop_flag;
1344 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1345 int in_file_count, char *const *in_filenames,
1346 int file_type, gboolean do_append)
1349 gchar *err_info = NULL;
1351 guint32 err_framenum;
1352 merge_result status;
1353 merge_progress_callback_t cb;
1354 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1356 /* prepare our callback routine */
1357 cb_data->pd_window = pd_window;
1358 cb.callback_func = merge_callback;
1361 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1363 /* merge the files */
1364 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1365 (const char *const *) in_filenames,
1366 in_file_count, do_append,
1367 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1368 "Wireshark", &cb, &err, &err_info,
1369 &err_fileno, &err_framenum);
1377 case MERGE_USER_ABORTED:
1378 /* this isn't really an error, though we will return CF_ERROR later */
1381 case MERGE_ERR_CANT_OPEN_INFILE:
1382 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1385 case MERGE_ERR_CANT_OPEN_OUTFILE:
1386 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1389 case MERGE_ERR_CANT_READ_INFILE:
1390 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1393 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1394 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1395 err_framenum, in_filenames[err_fileno]);
1398 case MERGE_ERR_CANT_WRITE_OUTFILE:
1399 cfile_write_failure_alert_box(in_filenames[err_fileno],
1400 *out_filenamep, err, err_info,
1401 err_framenum, file_type);
1404 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1405 cfile_close_failure_alert_box(*out_filenamep, err);
1409 simple_error_message_box("Unknown merge_files error %d", status);
1413 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1415 if (status != MERGE_OK) {
1416 /* Callers aren't expected to treat an error or an explicit abort
1417 differently - we put up error dialogs ourselves, so they don't
1425 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1427 const char *filter_new = dftext ? dftext : "";
1428 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1431 GTimeVal start_time;
1433 /* if new filter equals old one, do nothing unless told to do so */
1434 if (!force && strcmp(filter_new, filter_old) == 0) {
1440 if (dftext == NULL) {
1441 /* The new filter is an empty filter (i.e., display all packets).
1442 * so leave dfcode==NULL
1446 * We have a filter; make a copy of it (as we'll be saving it),
1447 * and try to compile it.
1449 dftext = g_strdup(dftext);
1450 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1451 /* The attempt failed; report an error. */
1452 simple_message_box(ESD_TYPE_ERROR, NULL,
1453 "See the help for a description of the display filter syntax.",
1454 "\"%s\" isn't a valid display filter: %s",
1462 if (dfcode == NULL) {
1463 /* Yes - free the filter text, and set it to null. */
1469 /* We have a valid filter. Replace the current filter. */
1470 g_free(cf->dfilter);
1471 cf->dfilter = dftext;
1472 g_get_current_time(&start_time);
1475 /* Now rescan the packet list, applying the new filter, but not
1476 throwing away information constructed on a previous pass. */
1477 if (cf->state != FILE_CLOSED) {
1478 if (dftext == NULL) {
1479 rescan_packets(cf, "Resetting", "Filter", FALSE);
1481 rescan_packets(cf, "Filtering", dftext, FALSE);
1485 /* Cleanup and release all dfilter resources */
1486 dfilter_free(dfcode);
1492 cf_reftime_packets(capture_file *cf)
1494 ref_time_packets(cf);
1498 cf_redissect_packets(capture_file *cf)
1500 if (cf->state != FILE_CLOSED) {
1501 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1506 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1507 struct wtap_pkthdr *phdr, Buffer *buf)
1512 #ifdef WANT_PACKET_EDITOR
1513 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1514 if (G_UNLIKELY(fdata->file_off == -1)) {
1515 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1518 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1522 *phdr = frame->phdr;
1523 ws_buffer_assure_space(buf, frame->phdr.caplen);
1524 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1529 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1530 cfile_read_failure_alert_box(cf->filename, err, err_info);
1537 cf_read_record(capture_file *cf, frame_data *fdata)
1539 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1542 /* Rescan the list of packets, reconstructing the CList.
1544 "action" describes why we're doing this; it's used in the progress
1547 "action_item" describes what we're doing; it's used in the progress
1550 "redissect" is TRUE if we need to make the dissectors reconstruct
1551 any state information they have (because a preference that affects
1552 some dissector has changed, meaning some dissector might construct
1553 its state differently from the way it was constructed the last time). */
1555 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1557 /* Rescan packets new packet list */
1560 progdlg_t *progbar = NULL;
1561 GTimer *prog_timer = g_timer_new();
1563 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1564 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1565 gboolean selected_frame_seen;
1567 GTimeVal start_time;
1568 gchar status_str[100];
1572 gboolean create_proto_tree;
1574 gboolean add_to_packet_list = FALSE;
1576 guint32 frames_count;
1578 /* Compile the current display filter.
1579 * We assume this will not fail since cf->dfilter is only set in
1580 * cf_filter IFF the filter was valid.
1582 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1583 g_assert(!cf->dfilter || (compiled && dfcode));
1585 /* Get the union of the flags for all tap listeners. */
1586 tap_flags = union_of_tap_listener_flags();
1588 /* If any tap listeners require the columns, construct them. */
1589 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1592 * Determine whether we need to create a protocol tree.
1595 * we're going to apply a display filter;
1597 * one of the tap listeners is going to apply a filter;
1599 * one of the tap listeners requires a protocol tree;
1601 * we're redissecting and a postdissector wants field
1602 * values or protocols on the first pass.
1605 (dfcode != NULL || have_filtering_tap_listeners() ||
1606 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1607 (redissect && postdissectors_want_hfids()));
1609 reset_tap_listeners();
1610 /* Which frame, if any, is the currently selected frame?
1611 XXX - should the selected frame or the focus frame be the "current"
1612 frame, that frame being the one from which "Find Frame" searches
1614 selected_frame = cf->current_frame;
1616 /* Mark frame num as not found */
1617 selected_frame_num = -1;
1619 /* Freeze the packet list while we redo it, so we don't get any
1620 screen updates while it happens. */
1621 packet_list_freeze();
1624 /* We need to re-initialize all the state information that protocols
1625 keep, because some preference that controls a dissector has changed,
1626 which might cause the state information to be constructed differently
1627 by that dissector. */
1629 /* We might receive new packets while redissecting, and we don't
1630 want to dissect those before their time. */
1631 cf->redissecting = TRUE;
1633 /* 'reset' dissection session */
1634 epan_free(cf->epan);
1635 if (cf->edt && cf->edt->pi.fd) {
1636 /* All pointers in "per frame proto data" for the currently selected
1637 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1638 Free them here to avoid unintended usage in packet_list_clear(). */
1639 frame_data_destroy(cf->edt->pi.fd);
1641 cf->epan = ws_epan_new(cf);
1642 cf->cinfo.epan = cf->epan;
1644 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1645 called via epan_new() / init_dissection() when reloading Lua plugins. */
1646 if (!create_proto_tree && have_filtering_tap_listeners()) {
1647 create_proto_tree = TRUE;
1650 /* We need to redissect the packets so we have to discard our old
1651 * packet list store. */
1652 packet_list_clear();
1653 add_to_packet_list = TRUE;
1656 /* We don't yet know which will be the first and last frames displayed. */
1657 cf->first_displayed = 0;
1658 cf->last_displayed = 0;
1660 /* We currently don't display any packets */
1661 cf->displayed_count = 0;
1663 /* Iterate through the list of frames. Call a routine for each frame
1664 to check whether it should be displayed and, if so, add it to
1665 the display list. */
1667 cf->prev_dis = NULL;
1668 cf->prev_cap = NULL;
1671 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1673 g_timer_start(prog_timer);
1674 /* Count of packets at which we've looked. */
1676 /* Progress so far. */
1679 cf->stop_flag = FALSE;
1680 g_get_current_time(&start_time);
1682 /* no previous row yet */
1683 prev_frame_num = -1;
1686 preceding_frame_num = -1;
1687 preceding_frame = NULL;
1688 following_frame_num = -1;
1689 following_frame = NULL;
1691 selected_frame_seen = FALSE;
1693 frames_count = cf->count;
1695 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1697 for (framenum = 1; framenum <= frames_count; framenum++) {
1698 fdata = frame_data_sequence_find(cf->frames, framenum);
1700 /* Create the progress bar if necessary.
1701 We check on every iteration of the loop, so that it takes no
1702 longer than the standard time to create it (otherwise, for a
1703 large file, we might take considerably longer than that standard
1704 time in order to get to the next progress bar step). */
1705 if (progbar == NULL)
1706 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1712 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1713 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1714 * likely trigger UI paint events, which might take a while depending on
1715 * the platform and display. Reset our timer *after* painting.
1717 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1718 /* let's not divide by zero. I should never be started
1719 * with count == 0, so let's assert that
1721 g_assert(cf->count > 0);
1722 progbar_val = (gfloat) count / frames_count;
1724 if (progbar != NULL) {
1725 g_snprintf(status_str, sizeof(status_str),
1726 "%4u of %u frames", count, frames_count);
1727 update_progress_dlg(progbar, progbar_val, status_str);
1730 g_timer_start(prog_timer);
1733 if (cf->stop_flag) {
1734 /* Well, the user decided to abort the filtering. Just stop.
1736 XXX - go back to the previous filter? Users probably just
1737 want not to wait for a filtering operation to finish;
1738 unless we cancel by having no filter, reverting to the
1739 previous filter will probably be even more expensive than
1740 continuing the filtering, as it involves going back to the
1741 beginning and filtering, and even with no filter we currently
1742 have to re-generate the entire clist, which is also expensive.
1744 I'm not sure what Network Monitor does, but it doesn't appear
1745 to give you an unfiltered display if you cancel. */
1752 /* Since all state for the frame was destroyed, mark the frame
1753 * as not visited, free the GSList referring to the state
1754 * data (the per-frame data itself was freed by
1755 * "init_dissection()"), and null out the GSList pointer. */
1756 frame_data_reset(fdata);
1757 frames_count = cf->count;
1760 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1761 fdata->flags.dependent_of_displayed = 0;
1763 if (!cf_read_record(cf, fdata))
1764 break; /* error reading the frame */
1766 /* If the previous frame is displayed, and we haven't yet seen the
1767 selected frame, remember that frame - it's the closest one we've
1768 yet seen before the selected frame. */
1769 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1770 preceding_frame_num = prev_frame_num;
1771 preceding_frame = prev_frame;
1774 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1776 ws_buffer_start_ptr(&cf->buf),
1777 add_to_packet_list);
1779 /* If this frame is displayed, and this is the first frame we've
1780 seen displayed after the selected frame, remember this frame -
1781 it's the closest one we've yet seen at or after the selected
1783 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1784 following_frame_num = fdata->num;
1785 following_frame = fdata;
1787 if (fdata == selected_frame) {
1788 selected_frame_seen = TRUE;
1789 if (fdata->flags.passed_dfilter)
1790 selected_frame_num = fdata->num;
1793 /* Remember this frame - it'll be the previous frame
1794 on the next pass through the loop. */
1795 prev_frame_num = fdata->num;
1799 epan_dissect_cleanup(&edt);
1801 /* We are done redissecting the packet list. */
1802 cf->redissecting = FALSE;
1805 frames_count = cf->count;
1806 /* Clear out what remains of the visited flags and per-frame data
1809 XXX - that may cause various forms of bogosity when dissecting
1810 these frames, as they won't have been seen by this sequential
1811 pass, but the only alternative I see is to keep scanning them
1812 even though the user requested that the scan stop, and that
1813 would leave the user stuck with an Wireshark grinding on
1814 until it finishes. Should we just stick them with that? */
1815 for (; framenum <= frames_count; framenum++) {
1816 fdata = frame_data_sequence_find(cf->frames, framenum);
1817 frame_data_reset(fdata);
1821 /* We're done filtering the packets; destroy the progress bar if it
1823 if (progbar != NULL)
1824 destroy_progress_dlg(progbar);
1825 g_timer_destroy(prog_timer);
1827 /* Unfreeze the packet list. */
1828 if (!add_to_packet_list)
1829 packet_list_recreate_visible_rows();
1831 /* Compute the time it took to filter the file */
1832 compute_elapsed(cf, &start_time);
1836 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1838 if (selected_frame_num == -1) {
1839 /* The selected frame didn't pass the filter. */
1840 if (selected_frame == NULL) {
1841 /* That's because there *was* no selected frame. Make the first
1842 displayed frame the current frame. */
1843 selected_frame_num = 0;
1845 /* Find the nearest displayed frame to the selected frame (whether
1846 it's before or after that frame) and make that the current frame.
1847 If the next and previous displayed frames are equidistant from the
1848 selected frame, choose the next one. */
1849 g_assert(following_frame == NULL ||
1850 following_frame->num >= selected_frame->num);
1851 g_assert(preceding_frame == NULL ||
1852 preceding_frame->num <= selected_frame->num);
1853 if (following_frame == NULL) {
1854 /* No frame after the selected frame passed the filter, so we
1855 have to select the last displayed frame before the selected
1857 selected_frame_num = preceding_frame_num;
1858 selected_frame = preceding_frame;
1859 } else if (preceding_frame == NULL) {
1860 /* No frame before the selected frame passed the filter, so we
1861 have to select the first displayed frame after the selected
1863 selected_frame_num = following_frame_num;
1864 selected_frame = following_frame;
1866 /* Frames before and after the selected frame passed the filter, so
1867 we'll select the previous frame */
1868 selected_frame_num = preceding_frame_num;
1869 selected_frame = preceding_frame;
1874 if (selected_frame_num == -1) {
1875 /* There are no frames displayed at all. */
1876 cf_unselect_packet(cf);
1878 /* Either the frame that was selected passed the filter, or we've
1879 found the nearest displayed frame to that frame. Select it, make
1880 it the focus row, and make it visible. */
1881 /* Set to invalid to force update of packet list and packet details */
1882 cf->current_row = -1;
1883 if (selected_frame_num == 0) {
1884 packet_list_select_first_row();
1886 if (!packet_list_select_row_from_data(selected_frame)) {
1887 /* We didn't find a row corresponding to this frame.
1888 This means that the frame isn't being displayed currently,
1889 so we can't select it. */
1890 simple_message_box(ESD_TYPE_INFO, NULL,
1891 "The capture file is probably not fully dissected.",
1892 "End of capture exceeded.");
1897 /* Cleanup and release all dfilter resources */
1898 dfilter_free(dfcode);
1903 * Scan through all frame data and recalculate the ref time
1904 * without rereading the file.
1905 * XXX - do we need a progres bar or is this fast enough?
1908 ref_time_packets(capture_file *cf)
1915 cf->prev_dis = NULL;
1918 for (framenum = 1; framenum <= cf->count; framenum++) {
1919 fdata = frame_data_sequence_find(cf->frames, framenum);
1921 /* just add some value here until we know if it is being displayed or not */
1922 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1928 /* If we don't have the time stamp of the first packet in the
1929 capture, it's because this is the first packet. Save the time
1930 stamp of this packet as the time stamp of the first packet. */
1931 if (cf->ref == NULL)
1933 /* if this frames is marked as a reference time frame, reset
1934 firstsec and firstusec to this frame */
1935 if (fdata->flags.ref_time)
1938 /* If we don't have the time stamp of the previous displayed packet,
1939 it's because this is the first displayed packet. Save the time
1940 stamp of this packet as the time stamp of the previous displayed
1942 if (cf->prev_dis == NULL) {
1943 cf->prev_dis = fdata;
1946 /* Get the time elapsed between the first packet and this packet. */
1947 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1948 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1950 /* If it's greater than the current elapsed time, set the elapsed time
1951 to it (we check for "greater than" so as not to be confused by
1952 time moving backwards). */
1953 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1954 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1955 cf->elapsed_time = rel_ts;
1958 /* If this frame is displayed, get the time elapsed between the
1959 previous displayed packet and this packet. */
1960 if ( fdata->flags.passed_dfilter ) {
1961 fdata->prev_dis_num = cf->prev_dis->num;
1962 cf->prev_dis = fdata;
1968 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1969 /* This frame either passed the display filter list or is marked as
1970 a time reference frame. All time reference frames are displayed
1971 even if they don't pass the display filter */
1972 if (fdata->flags.ref_time) {
1973 /* if this was a TIME REF frame we should reset the cum_bytes field */
1974 cf->cum_bytes = fdata->pkt_len;
1975 fdata->cum_bytes = cf->cum_bytes;
1977 /* increase cum_bytes with this packets length */
1978 cf->cum_bytes += fdata->pkt_len;
1991 process_specified_records(capture_file *cf, packet_range_t *range,
1992 const char *string1, const char *string2, gboolean terminate_is_stop,
1993 gboolean (*callback)(capture_file *, frame_data *,
1994 struct wtap_pkthdr *, const guint8 *, void *),
1995 void *callback_args,
1996 gboolean show_progress_bar)
2001 psp_return_t ret = PSP_FINISHED;
2003 progdlg_t *progbar = NULL;
2004 GTimer *prog_timer = g_timer_new();
2007 GTimeVal progbar_start_time;
2008 gchar progbar_status_str[100];
2009 range_process_e process_this;
2010 struct wtap_pkthdr phdr;
2012 wtap_phdr_init(&phdr);
2013 ws_buffer_init(&buf, 1500);
2015 g_timer_start(prog_timer);
2016 /* Count of packets at which we've looked. */
2018 /* Progress so far. */
2021 cf->stop_flag = FALSE;
2022 g_get_current_time(&progbar_start_time);
2025 packet_range_process_init(range);
2027 /* Iterate through all the packets, printing the packets that
2028 were selected by the current display filter. */
2029 for (framenum = 1; framenum <= cf->count; framenum++) {
2030 fdata = frame_data_sequence_find(cf->frames, framenum);
2032 /* Create the progress bar if necessary.
2033 We check on every iteration of the loop, so that it takes no
2034 longer than the standard time to create it (otherwise, for a
2035 large file, we might take considerably longer than that standard
2036 time in order to get to the next progress bar step). */
2037 if (show_progress_bar && progbar == NULL)
2038 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2041 &progbar_start_time,
2045 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2046 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2047 * likely trigger UI paint events, which might take a while depending on
2048 * the platform and display. Reset our timer *after* painting.
2050 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2051 /* let's not divide by zero. I should never be started
2052 * with count == 0, so let's assert that
2054 g_assert(cf->count > 0);
2055 progbar_val = (gfloat) progbar_count / cf->count;
2057 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2058 "%4u of %u packets", progbar_count, cf->count);
2059 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2061 g_timer_start(prog_timer);
2064 if (cf->stop_flag) {
2065 /* Well, the user decided to abort the operation. Just stop,
2066 and arrange to return PSP_STOPPED to our caller, so they know
2067 it was stopped explicitly. */
2074 if (range != NULL) {
2075 /* do we have to process this packet? */
2076 process_this = packet_range_process_packet(range, fdata);
2077 if (process_this == range_process_next) {
2078 /* this packet uninteresting, continue with next one */
2080 } else if (process_this == range_processing_finished) {
2081 /* all interesting packets processed, stop the loop */
2086 /* Get the packet */
2087 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2088 /* Attempt to get the packet failed. */
2092 /* Process the packet */
2093 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2094 /* Callback failed. We assume it reported the error appropriately. */
2100 /* We're done printing the packets; destroy the progress bar if
2102 if (progbar != NULL)
2103 destroy_progress_dlg(progbar);
2104 g_timer_destroy(prog_timer);
2106 wtap_phdr_cleanup(&phdr);
2107 ws_buffer_free(&buf);
2115 } retap_callback_args_t;
2118 retap_packet(capture_file *cf, frame_data *fdata,
2119 struct wtap_pkthdr *phdr, const guint8 *pd,
2122 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2124 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2125 epan_dissect_reset(&args->edt);
2131 cf_retap_packets(capture_file *cf)
2133 packet_range_t range;
2134 retap_callback_args_t callback_args;
2135 gboolean create_proto_tree;
2139 /* Presumably the user closed the capture file. */
2141 return CF_READ_ABORTED;
2144 cf_callback_invoke(cf_cb_file_retap_started, cf);
2146 /* Get the union of the flags for all tap listeners. */
2147 tap_flags = union_of_tap_listener_flags();
2149 /* If any tap listeners require the columns, construct them. */
2150 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2153 * Determine whether we need to create a protocol tree.
2156 * one of the tap listeners is going to apply a filter;
2158 * one of the tap listeners requires a protocol tree.
2161 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2163 /* Reset the tap listeners. */
2164 reset_tap_listeners();
2166 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2168 /* Iterate through the list of packets, dissecting all packets and
2169 re-running the taps. */
2170 packet_range_init(&range, cf);
2171 packet_range_process_init(&range);
2173 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2174 "all packets", TRUE, retap_packet,
2175 &callback_args, TRUE);
2177 epan_dissect_cleanup(&callback_args.edt);
2179 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2183 /* Completed successfully. */
2187 /* Well, the user decided to abort the refiltering.
2188 Return CF_READ_ABORTED so our caller knows they did that. */
2189 return CF_READ_ABORTED;
2192 /* Error while retapping. */
2193 return CF_READ_ERROR;
2196 g_assert_not_reached();
2201 print_args_t *print_args;
2202 gboolean print_header_line;
2203 char *header_line_buf;
2204 int header_line_buf_len;
2205 gboolean print_formfeed;
2206 gboolean print_separator;
2210 int num_visible_cols;
2213 } print_callback_args_t;
2216 print_packet(capture_file *cf, frame_data *fdata,
2217 struct wtap_pkthdr *phdr, const guint8 *pd,
2220 print_callback_args_t *args = (print_callback_args_t *)argsp;
2226 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2227 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2228 col_item_t* col_item;
2230 /* Fill in the column information if we're printing the summary
2232 if (args->print_args->print_summary) {
2233 col_custom_prime_edt(&args->edt, &cf->cinfo);
2234 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2235 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2237 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2239 if (args->print_formfeed) {
2240 if (!new_page(args->print_args->stream))
2243 if (args->print_separator) {
2244 if (!print_line(args->print_args->stream, 0, ""))
2250 * We generate bookmarks, if the output format supports them.
2251 * The name is "__frameN__".
2253 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2255 if (args->print_args->print_summary) {
2256 if (!args->print_args->print_col_headings)
2257 args->print_header_line = FALSE;
2258 if (args->print_header_line) {
2259 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2261 args->print_header_line = FALSE; /* we might not need to print any more */
2263 cp = &args->line_buf[0];
2265 for (i = 0; i < args->num_visible_cols; i++) {
2266 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2267 /* Find the length of the string for this column. */
2268 column_len = (int) strlen(col_item->col_data);
2269 if (args->col_widths[i] > column_len)
2270 column_len = args->col_widths[i];
2272 /* Make sure there's room in the line buffer for the column; if not,
2273 double its length. */
2274 line_len += column_len + 1; /* "+1" for space */
2275 if (line_len > args->line_buf_len) {
2276 cp_off = (int) (cp - args->line_buf);
2277 args->line_buf_len = 2 * line_len;
2278 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2279 cp = args->line_buf + cp_off;
2282 /* Right-justify the packet number column. */
2283 if (col_item->col_fmt == COL_NUMBER)
2284 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2286 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2288 if (i != args->num_visible_cols - 1)
2294 * Generate a bookmark, using the summary line as the title.
2296 if (!print_bookmark(args->print_args->stream, bookmark_name,
2300 if (!print_line(args->print_args->stream, 0, args->line_buf))
2304 * Generate a bookmark, using "Frame N" as the title, as we're not
2305 * printing the summary line.
2307 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2308 if (!print_bookmark(args->print_args->stream, bookmark_name,
2311 } /* if (print_summary) */
2313 if (args->print_args->print_dissections != print_dissections_none) {
2314 if (args->print_args->print_summary) {
2315 /* Separate the summary line from the tree with a blank line. */
2316 if (!print_line(args->print_args->stream, 0, ""))
2320 /* Print the information in that tree. */
2321 if (!proto_tree_print(args->print_args->print_dissections,
2322 args->print_args->print_hex, &args->edt, NULL,
2323 args->print_args->stream))
2326 /* Print a blank line if we print anything after this (aka more than one packet). */
2327 args->print_separator = TRUE;
2329 /* Print a header line if we print any more packet summaries */
2330 if (args->print_args->print_col_headings)
2331 args->print_header_line = TRUE;
2334 if (args->print_args->print_hex) {
2335 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2336 if (!print_line(args->print_args->stream, 0, ""))
2339 /* Print the full packet data as hex. */
2340 if (!print_hex_data(args->print_args->stream, &args->edt))
2343 /* Print a blank line if we print anything after this (aka more than one packet). */
2344 args->print_separator = TRUE;
2346 /* Print a header line if we print any more packet summaries */
2347 if (args->print_args->print_col_headings)
2348 args->print_header_line = TRUE;
2349 } /* if (args->print_args->print_dissections != print_dissections_none) */
2351 epan_dissect_reset(&args->edt);
2353 /* do we want to have a formfeed between each packet from now on? */
2354 if (args->print_args->print_formfeed) {
2355 args->print_formfeed = TRUE;
2361 epan_dissect_reset(&args->edt);
2366 cf_print_packets(capture_file *cf, print_args_t *print_args,
2367 gboolean show_progress_bar)
2369 print_callback_args_t callback_args;
2372 int i, cp_off, column_len, line_len;
2373 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2377 gboolean proto_tree_needed;
2379 callback_args.print_args = print_args;
2380 callback_args.print_header_line = print_args->print_col_headings;
2381 callback_args.header_line_buf = NULL;
2382 callback_args.header_line_buf_len = 256;
2383 callback_args.print_formfeed = FALSE;
2384 callback_args.print_separator = FALSE;
2385 callback_args.line_buf = NULL;
2386 callback_args.line_buf_len = 256;
2387 callback_args.col_widths = NULL;
2388 callback_args.num_visible_cols = 0;
2389 callback_args.visible_cols = NULL;
2391 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2392 destroy_print_stream(print_args->stream);
2393 return CF_PRINT_WRITE_ERROR;
2396 if (print_args->print_summary) {
2397 /* We're printing packet summaries. Allocate the header line buffer
2398 and get the column widths. */
2399 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2401 /* Find the number of visible columns and the last visible column */
2402 for (i = 0; i < prefs.num_cols; i++) {
2404 clp = g_list_nth(prefs.col_list, i);
2405 if (clp == NULL) /* Sanity check, Invalid column requested */
2408 cfmt = (fmt_data *) clp->data;
2409 if (cfmt->visible) {
2411 last_visible_col = i;
2415 /* Find the widths for each of the columns - maximum of the
2416 width of the title and the width of the data - and construct
2417 a buffer with a line containing the column titles. */
2418 callback_args.num_visible_cols = num_visible_col;
2419 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2420 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2421 cp = &callback_args.header_line_buf[0];
2423 visible_col_count = 0;
2424 for (i = 0; i < cf->cinfo.num_cols; i++) {
2426 clp = g_list_nth(prefs.col_list, i);
2427 if (clp == NULL) /* Sanity check, Invalid column requested */
2430 cfmt = (fmt_data *) clp->data;
2431 if (cfmt->visible == FALSE)
2434 /* Save the order of visible columns */
2435 callback_args.visible_cols[visible_col_count] = i;
2437 /* Don't pad the last column. */
2438 if (i == last_visible_col)
2439 callback_args.col_widths[visible_col_count] = 0;
2441 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2442 data_width = get_column_char_width(get_column_format(i));
2443 if (data_width > callback_args.col_widths[visible_col_count])
2444 callback_args.col_widths[visible_col_count] = data_width;
2447 /* Find the length of the string for this column. */
2448 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2449 if (callback_args.col_widths[i] > column_len)
2450 column_len = callback_args.col_widths[visible_col_count];
2452 /* Make sure there's room in the line buffer for the column; if not,
2453 double its length. */
2454 line_len += column_len + 1; /* "+1" for space */
2455 if (line_len > callback_args.header_line_buf_len) {
2456 cp_off = (int) (cp - callback_args.header_line_buf);
2457 callback_args.header_line_buf_len = 2 * line_len;
2458 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2459 callback_args.header_line_buf_len + 1);
2460 cp = callback_args.header_line_buf + cp_off;
2463 /* Right-justify the packet number column. */
2464 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2465 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2467 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2469 if (i != cf->cinfo.num_cols - 1)
2472 visible_col_count++;
2476 /* Now start out the main line buffer with the same length as the
2477 header line buffer. */
2478 callback_args.line_buf_len = callback_args.header_line_buf_len;
2479 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2480 } /* if (print_summary) */
2482 /* Create the protocol tree, and make it visible, if we're printing
2483 the dissection or the hex data.
2484 XXX - do we need it if we're just printing the hex data? */
2486 callback_args.print_args->print_dissections != print_dissections_none ||
2487 callback_args.print_args->print_hex ||
2488 have_custom_cols(&cf->cinfo) || have_field_extractors();
2489 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2491 /* Iterate through the list of packets, printing the packets we were
2493 ret = process_specified_records(cf, &print_args->range, "Printing",
2494 "selected packets", TRUE, print_packet,
2495 &callback_args, show_progress_bar);
2496 epan_dissect_cleanup(&callback_args.edt);
2497 g_free(callback_args.header_line_buf);
2498 g_free(callback_args.line_buf);
2499 g_free(callback_args.col_widths);
2500 g_free(callback_args.visible_cols);
2505 /* Completed successfully. */
2509 /* Well, the user decided to abort the printing.
2511 XXX - note that what got generated before they did that
2512 will get printed if we're piping to a print program; we'd
2513 have to write to a file and then hand that to the print
2514 program to make it actually not print anything. */
2518 /* Error while printing.
2520 XXX - note that what got generated before they did that
2521 will get printed if we're piping to a print program; we'd
2522 have to write to a file and then hand that to the print
2523 program to make it actually not print anything. */
2524 destroy_print_stream(print_args->stream);
2525 return CF_PRINT_WRITE_ERROR;
2528 if (!print_finale(print_args->stream)) {
2529 destroy_print_stream(print_args->stream);
2530 return CF_PRINT_WRITE_ERROR;
2533 if (!destroy_print_stream(print_args->stream))
2534 return CF_PRINT_WRITE_ERROR;
2542 print_args_t *print_args;
2543 } write_packet_callback_args_t;
2546 write_pdml_packet(capture_file *cf, frame_data *fdata,
2547 struct wtap_pkthdr *phdr, const guint8 *pd,
2550 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2552 /* Create the protocol tree, but don't fill in the column information. */
2553 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2555 /* Write out the information in that tree. */
2556 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh);
2558 epan_dissect_reset(&args->edt);
2560 return !ferror(args->fh);
2564 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2566 write_packet_callback_args_t callback_args;
2570 fh = ws_fopen(print_args->file, "w");
2572 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2574 write_pdml_preamble(fh, cf->filename);
2577 return CF_PRINT_WRITE_ERROR;
2580 callback_args.fh = fh;
2581 callback_args.print_args = print_args;
2582 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2584 /* Iterate through the list of packets, printing the packets we were
2586 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2587 "selected packets", TRUE,
2588 write_pdml_packet, &callback_args, TRUE);
2590 epan_dissect_cleanup(&callback_args.edt);
2595 /* Completed successfully. */
2599 /* Well, the user decided to abort the printing. */
2603 /* Error while printing. */
2605 return CF_PRINT_WRITE_ERROR;
2608 write_pdml_finale(fh);
2611 return CF_PRINT_WRITE_ERROR;
2614 /* XXX - check for an error */
2621 write_psml_packet(capture_file *cf, frame_data *fdata,
2622 struct wtap_pkthdr *phdr, const guint8 *pd,
2625 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2627 /* Fill in the column information */
2628 col_custom_prime_edt(&args->edt, &cf->cinfo);
2629 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2630 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2632 /* Write out the column information. */
2633 write_psml_columns(&args->edt, args->fh);
2635 epan_dissect_reset(&args->edt);
2637 return !ferror(args->fh);
2641 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2643 write_packet_callback_args_t callback_args;
2647 gboolean proto_tree_needed;
2649 fh = ws_fopen(print_args->file, "w");
2651 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2653 write_psml_preamble(&cf->cinfo, fh);
2656 return CF_PRINT_WRITE_ERROR;
2659 callback_args.fh = fh;
2660 callback_args.print_args = print_args;
2662 /* Fill in the column information, only create the protocol tree
2663 if having custom columns or field extractors. */
2664 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2665 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2667 /* Iterate through the list of packets, printing the packets we were
2669 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2670 "selected packets", TRUE,
2671 write_psml_packet, &callback_args, TRUE);
2673 epan_dissect_cleanup(&callback_args.edt);
2678 /* Completed successfully. */
2682 /* Well, the user decided to abort the printing. */
2686 /* Error while printing. */
2688 return CF_PRINT_WRITE_ERROR;
2691 write_psml_finale(fh);
2694 return CF_PRINT_WRITE_ERROR;
2697 /* XXX - check for an error */
2704 write_csv_packet(capture_file *cf, frame_data *fdata,
2705 struct wtap_pkthdr *phdr, const guint8 *pd,
2708 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2710 /* Fill in the column information */
2711 col_custom_prime_edt(&args->edt, &cf->cinfo);
2712 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2713 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2715 /* Write out the column information. */
2716 write_csv_columns(&args->edt, args->fh);
2718 epan_dissect_reset(&args->edt);
2720 return !ferror(args->fh);
2724 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2726 write_packet_callback_args_t callback_args;
2727 gboolean proto_tree_needed;
2731 fh = ws_fopen(print_args->file, "w");
2733 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2735 write_csv_column_titles(&cf->cinfo, fh);
2738 return CF_PRINT_WRITE_ERROR;
2741 callback_args.fh = fh;
2742 callback_args.print_args = print_args;
2744 /* only create the protocol tree if having custom columns or field extractors. */
2745 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2746 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2748 /* Iterate through the list of packets, printing the packets we were
2750 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2751 "selected packets", TRUE,
2752 write_csv_packet, &callback_args, TRUE);
2754 epan_dissect_cleanup(&callback_args.edt);
2759 /* Completed successfully. */
2763 /* Well, the user decided to abort the printing. */
2767 /* Error while printing. */
2769 return CF_PRINT_WRITE_ERROR;
2772 /* XXX - check for an error */
2779 carrays_write_packet(capture_file *cf, frame_data *fdata,
2780 struct wtap_pkthdr *phdr,
2781 const guint8 *pd, void *argsp)
2783 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2785 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2786 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2787 epan_dissect_reset(&args->edt);
2789 return !ferror(args->fh);
2793 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2795 write_packet_callback_args_t callback_args;
2799 fh = ws_fopen(print_args->file, "w");
2802 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2806 return CF_PRINT_WRITE_ERROR;
2809 callback_args.fh = fh;
2810 callback_args.print_args = print_args;
2811 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2813 /* Iterate through the list of packets, printing the packets we were
2815 ret = process_specified_records(cf, &print_args->range,
2817 "selected packets", TRUE,
2818 carrays_write_packet, &callback_args, TRUE);
2820 epan_dissect_cleanup(&callback_args.edt);
2824 /* Completed successfully. */
2827 /* Well, the user decided to abort the printing. */
2830 /* Error while printing. */
2832 return CF_PRINT_WRITE_ERROR;
2840 write_json_packet(capture_file *cf, frame_data *fdata,
2841 struct wtap_pkthdr *phdr, const guint8 *pd,
2844 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2846 /* Create the protocol tree, but don't fill in the column information. */
2847 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2849 /* Write out the information in that tree. */
2850 write_json_proto_tree(NULL, args->print_args->print_dissections,
2851 args->print_args->print_hex, NULL, PF_NONE,
2852 &args->edt, args->fh);
2854 epan_dissect_reset(&args->edt);
2856 return !ferror(args->fh);
2860 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2862 write_packet_callback_args_t callback_args;
2866 fh = ws_fopen(print_args->file, "w");
2868 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2870 write_json_preamble(fh);
2873 return CF_PRINT_WRITE_ERROR;
2876 callback_args.fh = fh;
2877 callback_args.print_args = print_args;
2878 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2880 /* Iterate through the list of packets, printing the packets we were
2882 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2883 "selected packets", TRUE,
2884 write_json_packet, &callback_args, TRUE);
2886 epan_dissect_cleanup(&callback_args.edt);
2891 /* Completed successfully. */
2895 /* Well, the user decided to abort the printing. */
2899 /* Error while printing. */
2901 return CF_PRINT_WRITE_ERROR;
2904 write_json_finale(fh);
2907 return CF_PRINT_WRITE_ERROR;
2910 /* XXX - check for an error */
2917 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2918 search_direction dir)
2922 mdata.string = string;
2923 mdata.string_len = strlen(string);
2924 return find_packet(cf, match_protocol_tree, &mdata, dir);
2928 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2930 mdata->frame_matched = FALSE;
2931 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2932 mdata->string_len = strlen(mdata->string);
2934 /* Iterate through all the nodes looking for matching text */
2935 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2936 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2940 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2942 match_data *mdata = (match_data *)criterion;
2945 /* Load the frame's data. */
2946 if (!cf_read_record(cf, fdata)) {
2947 /* Attempt to get the packet failed. */
2951 /* Construct the protocol tree, including the displayed text */
2952 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2953 /* We don't need the column information */
2954 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2956 /* Iterate through all the nodes, seeing if they have text that matches. */
2958 mdata->frame_matched = FALSE;
2959 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2960 epan_dissect_cleanup(&edt);
2961 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2965 match_subtree_text(proto_node *node, gpointer data)
2967 match_data *mdata = (match_data *) data;
2968 const gchar *string = mdata->string;
2969 size_t string_len = mdata->string_len;
2970 capture_file *cf = mdata->cf;
2971 field_info *fi = PNODE_FINFO(node);
2972 gchar label_str[ITEM_LABEL_LENGTH];
2979 /* dissection with an invisible proto tree? */
2982 if (mdata->frame_matched) {
2983 /* We already had a match; don't bother doing any more work. */
2987 /* Don't match invisible entries. */
2988 if (PROTO_ITEM_IS_HIDDEN(node))
2991 /* was a free format label produced? */
2993 label_ptr = fi->rep->representation;
2995 /* no, make a generic label */
2996 label_ptr = label_str;
2997 proto_item_fill_label(fi, label_str);
3001 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3002 mdata->frame_matched = TRUE;
3007 /* Does that label match? */
3008 label_len = strlen(label_ptr);
3009 for (i = 0; i < label_len; i++) {
3010 c_char = label_ptr[i];
3012 c_char = g_ascii_toupper(c_char);
3013 if (c_char == string[c_match]) {
3015 if (c_match == string_len) {
3016 /* No need to look further; we have a match */
3017 mdata->frame_matched = TRUE;
3026 /* Recurse into the subtree, if it exists */
3027 if (node->first_child != NULL)
3028 proto_tree_children_foreach(node, match_subtree_text, mdata);
3032 cf_find_packet_summary_line(capture_file *cf, const char *string,
3033 search_direction dir)
3037 mdata.string = string;
3038 mdata.string_len = strlen(string);
3039 return find_packet(cf, match_summary_line, &mdata, dir);
3043 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3045 match_data *mdata = (match_data *)criterion;
3046 const gchar *string = mdata->string;
3047 size_t string_len = mdata->string_len;
3049 const char *info_column;
3050 size_t info_column_len;
3051 match_result result = MR_NOTMATCHED;
3057 /* Load the frame's data. */
3058 if (!cf_read_record(cf, fdata)) {
3059 /* Attempt to get the packet failed. */
3063 /* Don't bother constructing the protocol tree */
3064 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3065 /* Get the column information */
3066 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3069 /* Find the Info column */
3070 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3071 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3072 /* Found it. See if we match. */
3073 info_column = edt.pi.cinfo->columns[colx].col_data;
3074 info_column_len = strlen(info_column);
3076 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3077 result = MR_MATCHED;
3081 for (i = 0; i < info_column_len; i++) {
3082 c_char = info_column[i];
3084 c_char = g_ascii_toupper(c_char);
3085 if (c_char == string[c_match]) {
3087 if (c_match == string_len) {
3088 result = MR_MATCHED;
3098 epan_dissect_cleanup(&edt);
3105 } cbs_t; /* "Counted byte string" */
3109 * The current match_* routines only support ASCII case insensitivity and don't
3110 * convert UTF-8 inputs to UTF-16 for matching.
3112 * We could modify them to use the GLib Unicode routines or the International
3113 * Components for Unicode library but it's not apparent that we could do so
3114 * without consuming a lot more CPU and memory or that searching would be
3115 * significantly better.
3119 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3120 search_direction dir)
3125 info.data_len = string_size;
3127 /* Regex, String or hex search? */
3129 /* Regular Expression search */
3130 return find_packet(cf, match_regex, NULL, dir);
3131 } else if (cf->string) {
3132 /* String search - what type of string? */
3133 switch (cf->scs_type) {
3135 case SCS_NARROW_AND_WIDE:
3136 return find_packet(cf, match_narrow_and_wide, &info, dir);
3139 return find_packet(cf, match_narrow, &info, dir);
3142 return find_packet(cf, match_wide, &info, dir);
3145 g_assert_not_reached();
3149 return find_packet(cf, match_binary, &info, dir);
3153 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3155 cbs_t *info = (cbs_t *)criterion;
3156 const guint8 *ascii_text = info->data;
3157 size_t textlen = info->data_len;
3158 match_result result;
3165 /* Load the frame's data. */
3166 if (!cf_read_record(cf, fdata)) {
3167 /* Attempt to get the packet failed. */
3171 result = MR_NOTMATCHED;
3172 buf_len = fdata->cap_len;
3173 pd = ws_buffer_start_ptr(&cf->buf);
3175 while (i < buf_len) {
3178 c_char = g_ascii_toupper(c_char);
3179 if (c_char != '\0') {
3180 if (c_char == ascii_text[c_match]) {
3182 if (c_match == textlen) {
3183 result = MR_MATCHED;
3184 cf->search_pos = i; /* Save the position of the last character
3185 for highlighting the field. */
3186 cf->search_len = (guint32)textlen;
3191 g_assert(i>=c_match);
3192 i -= (guint32)c_match;
3202 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3205 cbs_t *info = (cbs_t *)criterion;
3206 const guint8 *ascii_text = info->data;
3207 size_t textlen = info->data_len;
3208 match_result result;
3214 /* Load the frame's data. */
3215 if (!cf_read_record(cf, fdata)) {
3216 /* Attempt to get the packet failed. */
3220 result = MR_NOTMATCHED;
3221 buf_len = fdata->cap_len;
3222 pd = ws_buffer_start_ptr(&cf->buf);
3224 while (i < buf_len) {
3227 c_char = g_ascii_toupper(c_char);
3228 if (c_char == ascii_text[c_match]) {
3230 if (c_match == textlen) {
3231 result = MR_MATCHED;
3232 cf->search_pos = i; /* Save the position of the last character
3233 for highlighting the field. */
3234 cf->search_len = (guint32)textlen;
3239 g_assert(i>=c_match);
3240 i -= (guint32)c_match;
3250 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3252 cbs_t *info = (cbs_t *)criterion;
3253 const guint8 *ascii_text = info->data;
3254 size_t textlen = info->data_len;
3255 match_result result;
3262 /* Load the frame's data. */
3263 if (!cf_read_record(cf, fdata)) {
3264 /* Attempt to get the packet failed. */
3268 result = MR_NOTMATCHED;
3269 buf_len = fdata->cap_len;
3270 pd = ws_buffer_start_ptr(&cf->buf);
3272 while (i < buf_len) {
3275 c_char = g_ascii_toupper(c_char);
3276 if (c_char == ascii_text[c_match]) {
3278 if (c_match == textlen) {
3279 result = MR_MATCHED;
3280 cf->search_pos = i; /* Save the position of the last character
3281 for highlighting the field. */
3282 cf->search_len = (guint32)textlen;
3288 g_assert(i>=(c_match*2));
3289 i -= (guint32)c_match*2;
3298 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3300 cbs_t *info = (cbs_t *)criterion;
3301 const guint8 *binary_data = info->data;
3302 size_t datalen = info->data_len;
3303 match_result result;
3309 /* Load the frame's data. */
3310 if (!cf_read_record(cf, fdata)) {
3311 /* Attempt to get the packet failed. */
3315 result = MR_NOTMATCHED;
3316 buf_len = fdata->cap_len;
3317 pd = ws_buffer_start_ptr(&cf->buf);
3319 while (i < buf_len) {
3320 if (pd[i] == binary_data[c_match]) {
3322 if (c_match == datalen) {
3323 result = MR_MATCHED;
3324 cf->search_pos = i; /* Save the position of the last character
3325 for highlighting the field. */
3326 cf->search_len = (guint32)datalen;
3331 g_assert(i>=c_match);
3332 i -= (guint32)c_match;
3341 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3343 match_result result = MR_NOTMATCHED;
3344 GMatchInfo *match_info = NULL;
3346 /* Load the frame's data. */
3347 if (!cf_read_record(cf, fdata)) {
3348 /* Attempt to get the packet failed. */
3352 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3353 0, (GRegexMatchFlags) 0, &match_info, NULL))
3355 gint start_pos = 0, end_pos = 0;
3356 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3357 cf->search_pos = end_pos - 1;
3358 cf->search_len = end_pos - start_pos;
3359 result = MR_MATCHED;
3365 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3366 search_direction dir)
3368 return find_packet(cf, match_dfilter, sfcode, dir);
3372 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3373 search_direction dir)
3378 if (!dfilter_compile(filter, &sfcode, NULL)) {
3380 * XXX - this shouldn't happen, as the filter string is machine
3385 if (sfcode == NULL) {
3387 * XXX - this shouldn't happen, as the filter string is machine
3392 result = find_packet(cf, match_dfilter, sfcode, dir);
3393 dfilter_free(sfcode);
3398 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3400 dfilter_t *sfcode = (dfilter_t *)criterion;
3402 match_result result;
3404 /* Load the frame's data. */
3405 if (!cf_read_record(cf, fdata)) {
3406 /* Attempt to get the packet failed. */
3410 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3411 epan_dissect_prime_with_dfilter(&edt, sfcode);
3412 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3413 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3414 epan_dissect_cleanup(&edt);
3419 cf_find_packet_marked(capture_file *cf, search_direction dir)
3421 return find_packet(cf, match_marked, NULL, dir);
3425 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3427 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3431 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3433 return find_packet(cf, match_time_reference, NULL, dir);
3437 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3439 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3443 find_packet(capture_file *cf,
3444 match_result (*match_function)(capture_file *, frame_data *, void *),
3445 void *criterion, search_direction dir)
3447 frame_data *start_fd;
3450 frame_data *new_fd = NULL;
3451 progdlg_t *progbar = NULL;
3452 GTimer *prog_timer = g_timer_new();
3456 GTimeVal start_time;
3457 gchar status_str[100];
3459 match_result result;
3461 start_fd = cf->current_frame;
3462 if (start_fd != NULL) {
3463 /* Iterate through the list of packets, starting at the packet we've
3464 picked, calling a routine to run the filter on the packet, see if
3465 it matches, and stop if so. */
3467 framenum = start_fd->num;
3469 g_timer_start(prog_timer);
3470 /* Progress so far. */
3473 cf->stop_flag = FALSE;
3474 g_get_current_time(&start_time);
3476 title = cf->sfilter?cf->sfilter:"";
3478 /* Create the progress bar if necessary.
3479 We check on every iteration of the loop, so that it takes no
3480 longer than the standard time to create it (otherwise, for a
3481 large file, we might take considerably longer than that standard
3482 time in order to get to the next progress bar step). */
3483 if (progbar == NULL)
3484 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3485 FALSE, &cf->stop_flag, &start_time, progbar_val);
3488 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3489 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3490 * likely trigger UI paint events, which might take a while depending on
3491 * the platform and display. Reset our timer *after* painting.
3493 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3494 /* let's not divide by zero. I should never be started
3495 * with count == 0, so let's assert that
3497 g_assert(cf->count > 0);
3499 progbar_val = (gfloat) count / cf->count;
3501 g_snprintf(status_str, sizeof(status_str),
3502 "%4u of %u packets", count, cf->count);
3503 update_progress_dlg(progbar, progbar_val, status_str);
3505 g_timer_start(prog_timer);
3508 if (cf->stop_flag) {
3509 /* Well, the user decided to abort the search. Go back to the
3510 frame where we started. */
3515 /* Go past the current frame. */
3516 if (dir == SD_BACKWARD) {
3517 /* Go on to the previous frame. */
3518 if (framenum == 1) {
3520 * XXX - other apps have a bit more of a detailed message
3521 * for this, and instead of offering "OK" and "Cancel",
3522 * they offer things such as "Continue" and "Cancel";
3523 * we need an API for popping up alert boxes with
3524 * {Verb} and "Cancel".
3527 if (prefs.gui_find_wrap)
3529 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3530 framenum = cf->count; /* wrap around */
3534 statusbar_push_temporary_msg("Search reached the beginning.");
3535 framenum = start_fd->num; /* stay on previous packet */
3540 /* Go on to the next frame. */
3541 if (framenum == cf->count) {
3542 if (prefs.gui_find_wrap)
3544 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3545 framenum = 1; /* wrap around */
3549 statusbar_push_temporary_msg("Search reached the end.");
3550 framenum = start_fd->num; /* stay on previous packet */
3555 fdata = frame_data_sequence_find(cf->frames, framenum);
3559 /* Is this packet in the display? */
3560 if (fdata->flags.passed_dfilter) {
3561 /* Yes. Does it match the search criterion? */
3562 result = (*match_function)(cf, fdata, criterion);
3563 if (result == MR_ERROR) {
3564 /* Error; our caller has reported the error. Go back to the frame
3565 where we started. */
3568 } else if (result == MR_MATCHED) {
3569 /* Yes. Go to the new frame. */
3575 if (fdata == start_fd) {
3576 /* We're back to the frame we were on originally, and that frame
3577 doesn't match the search filter. The search failed. */
3582 /* We're done scanning the packets; destroy the progress bar if it
3584 if (progbar != NULL)
3585 destroy_progress_dlg(progbar);
3586 g_timer_destroy(prog_timer);
3589 if (new_fd != NULL) {
3590 /* Find and select */
3591 cf->search_in_progress = TRUE;
3592 found = packet_list_select_row_from_data(new_fd);
3593 cf->search_in_progress = FALSE;
3594 cf->search_pos = 0; /* Reset the position */
3595 cf->search_len = 0; /* Reset length */
3597 /* We didn't find a row corresponding to this frame.
3598 This means that the frame isn't being displayed currently,
3599 so we can't select it. */
3600 simple_message_box(ESD_TYPE_INFO, NULL,
3601 "The capture file is probably not fully dissected.",
3602 "End of capture exceeded.");
3605 return TRUE; /* success */
3607 return FALSE; /* failure */
3611 cf_goto_frame(capture_file *cf, guint fnumber)
3615 if (cf == NULL || cf->frames == NULL) {
3616 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3617 statusbar_push_temporary_msg("There is no file loaded");
3618 return FALSE; /* we failed to go to that packet */
3621 fdata = frame_data_sequence_find(cf->frames, fnumber);
3623 if (fdata == NULL) {
3624 /* we didn't find a packet with that packet number */
3625 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3626 return FALSE; /* we failed to go to that packet */
3628 if (!fdata->flags.passed_dfilter) {
3629 /* that packet currently isn't displayed */
3630 /* XXX - add it to the set of displayed packets? */
3631 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3632 return FALSE; /* we failed to go to that packet */
3635 if (!packet_list_select_row_from_data(fdata)) {
3636 /* We didn't find a row corresponding to this frame.
3637 This means that the frame isn't being displayed currently,
3638 so we can't select it. */
3639 simple_message_box(ESD_TYPE_INFO, NULL,
3640 "The capture file is probably not fully dissected.",
3641 "End of capture exceeded.");
3644 return TRUE; /* we got to that packet */
3648 * Go to frame specified by currently selected protocol tree item.
3651 cf_goto_framenum(capture_file *cf)
3653 header_field_info *hfinfo;
3656 if (cf->finfo_selected) {
3657 hfinfo = cf->finfo_selected->hfinfo;
3659 if (hfinfo->type == FT_FRAMENUM) {
3660 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3662 return cf_goto_frame(cf, framenum);
3669 /* Select the packet on a given row. */
3671 cf_select_packet(capture_file *cf, int row)
3673 epan_dissect_t *old_edt;
3676 /* Get the frame data struct pointer for this frame */
3677 fdata = packet_list_get_row_data(row);
3679 if (fdata == NULL) {
3683 /* Get the data in that frame. */
3684 if (!cf_read_record (cf, fdata)) {
3688 /* Record that this frame is the current frame. */
3689 cf->current_frame = fdata;
3690 cf->current_row = row;
3693 /* Create the logical protocol tree. */
3694 /* We don't need the columns here. */
3695 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3697 tap_build_interesting(cf->edt);
3698 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3699 cf->current_frame, NULL);
3701 dfilter_macro_build_ftv_cache(cf->edt->tree);
3703 cf_callback_invoke(cf_cb_packet_selected, cf);
3705 if (old_edt != NULL)
3706 epan_dissect_free(old_edt);
3710 /* Unselect the selected packet, if any. */
3712 cf_unselect_packet(capture_file *cf)
3714 epan_dissect_t *old_edt = cf->edt;
3718 /* No packet is selected. */
3719 cf->current_frame = NULL;
3720 cf->current_row = 0;
3722 cf_callback_invoke(cf_cb_packet_unselected, cf);
3724 /* No protocol tree means no selected field. */
3725 cf_unselect_field(cf);
3727 /* Destroy the epan_dissect_t for the unselected packet. */
3728 if (old_edt != NULL)
3729 epan_dissect_free(old_edt);
3732 /* Unset the selected protocol tree field, if any. */
3734 cf_unselect_field(capture_file *cf)
3736 cf->finfo_selected = NULL;
3738 cf_callback_invoke(cf_cb_field_unselected, cf);
3742 * Mark a particular frame.
3745 cf_mark_frame(capture_file *cf, frame_data *frame)
3747 if (! frame->flags.marked) {
3748 frame->flags.marked = TRUE;
3749 if (cf->count > cf->marked_count)
3755 * Unmark a particular frame.
3758 cf_unmark_frame(capture_file *cf, frame_data *frame)
3760 if (frame->flags.marked) {
3761 frame->flags.marked = FALSE;
3762 if (cf->marked_count > 0)
3768 * Ignore a particular frame.
3771 cf_ignore_frame(capture_file *cf, frame_data *frame)
3773 if (! frame->flags.ignored) {
3774 frame->flags.ignored = TRUE;
3775 if (cf->count > cf->ignored_count)
3776 cf->ignored_count++;
3781 * Un-ignore a particular frame.
3784 cf_unignore_frame(capture_file *cf, frame_data *frame)
3786 if (frame->flags.ignored) {
3787 frame->flags.ignored = FALSE;
3788 if (cf->ignored_count > 0)
3789 cf->ignored_count--;
3794 * Read the comment in SHB block
3798 cf_read_shb_comment(capture_file *cf)
3800 wtap_block_t shb_inf;
3804 /* XXX - support multiple SHBs */
3805 shb_inf = wtap_file_get_shb(cf->wth);
3807 /* Get the first comment from the SHB. */
3808 /* XXX - support multiple comments */
3809 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3815 cf_update_capture_comment(capture_file *cf, gchar *comment)
3817 wtap_block_t shb_inf;
3821 /* XXX - support multiple SHBs */
3822 shb_inf = wtap_file_get_shb(cf->wth);
3824 /* Get the first comment from the SHB. */
3825 /* XXX - support multiple comments */
3826 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3827 /* There's no comment - add one. */
3828 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3830 /* See if the comment has changed or not */
3831 if (strcmp(shb_comment, comment) == 0) {
3836 /* The comment has changed, let's update it */
3837 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3839 /* Mark the file as having unsaved changes */
3840 cf->unsaved_changes = TRUE;
3844 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3846 if (cf->frames_user_comments)
3847 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3854 cf_get_comment(capture_file *cf, const frame_data *fd)
3858 /* fetch user comment */
3859 if (fd->flags.has_user_comment)
3860 return g_strdup(cf_get_user_packet_comment(cf, fd));
3862 /* fetch phdr comment */
3863 if (fd->flags.has_phdr_comment) {
3864 struct wtap_pkthdr phdr; /* Packet header */
3865 Buffer buf; /* Packet data */
3867 wtap_phdr_init(&phdr);
3868 ws_buffer_init(&buf, 1500);
3870 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3871 { /* XXX, what we can do here? */ }
3873 comment = phdr.opt_comment;
3874 wtap_phdr_cleanup(&phdr);
3875 ws_buffer_free(&buf);
3882 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3884 const frame_data *fdata1 = (const frame_data *) a;
3885 const frame_data *fdata2 = (const frame_data *) b;
3887 return (fdata1->num < fdata2->num) ? -1 :
3888 (fdata1->num > fdata2->num) ? 1 :
3893 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3895 char *pkt_comment = cf_get_comment(cf, fd);
3897 /* Check if the comment has changed */
3898 if (!g_strcmp0(pkt_comment, new_comment)) {
3899 g_free(pkt_comment);
3902 g_free(pkt_comment);
3905 cf->packet_comment_count--;
3908 cf->packet_comment_count++;
3910 fd->flags.has_user_comment = TRUE;
3912 if (!cf->frames_user_comments)
3913 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3915 /* insert new packet comment */
3916 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3918 expert_update_comment_count(cf->packet_comment_count);
3920 /* OK, we have unsaved changes. */
3921 cf->unsaved_changes = TRUE;
3926 * What types of comments does this capture file have?
3929 cf_comment_types(capture_file *cf)
3931 guint32 comment_types = 0;
3933 if (cf_read_shb_comment(cf) != NULL)
3934 comment_types |= WTAP_COMMENT_PER_SECTION;
3935 if (cf->packet_comment_count != 0)
3936 comment_types |= WTAP_COMMENT_PER_PACKET;
3937 return comment_types;
3941 * Add a resolved address to this file's list of resolved addresses.
3944 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3947 * XXX - support multiple resolved address lists, and add to the one
3948 * attached to this file?
3950 if (!add_ip_name_from_string(addr, name))
3953 /* OK, we have unsaved changes. */
3954 cf->unsaved_changes = TRUE;
3958 #ifdef WANT_PACKET_EDITOR
3960 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3971 modified_frame_data_free(gpointer data)
3973 modified_frame_data *mfd = (modified_frame_data *)data;
3980 * Give a frame new, edited data.
3983 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3984 struct wtap_pkthdr *phdr, guint8 *pd)
3986 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3989 mfd->pd = (char *)pd;
3991 if (cf->edited_frames == NULL)
3992 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3993 modified_frame_data_free);
3994 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3997 /* Mark the file as having unsaved changes */
3998 cf->unsaved_changes = TRUE;
4006 } save_callback_args_t;
4009 * Save a capture to a file, in a particular format, saving either
4010 * all packets, all currently-displayed packets, or all marked packets.
4012 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4013 * up a message box for the failure.
4016 save_record(capture_file *cf, frame_data *fdata,
4017 struct wtap_pkthdr *phdr, const guint8 *pd,
4020 save_callback_args_t *args = (save_callback_args_t *)argsp;
4021 struct wtap_pkthdr hdr;
4024 const char *pkt_comment;
4026 if (fdata->flags.has_user_comment)
4027 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4029 pkt_comment = phdr->opt_comment;
4031 /* init the wtap header for saving */
4032 /* TODO: reuse phdr */
4033 /* XXX - these are the only flags that correspond to data that we have
4034 in the frame_data structure and that matter on a per-packet basis.
4036 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4037 and "on the wire" lengths, or it doesn't.
4039 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4042 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4043 from the packet flags. */
4044 hdr.rec_type = phdr->rec_type;
4045 hdr.presence_flags = 0;
4046 if (fdata->flags.has_ts)
4047 hdr.presence_flags |= WTAP_HAS_TS;
4048 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4049 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4050 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4051 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4053 hdr.caplen = phdr->caplen;
4054 hdr.len = phdr->len;
4055 hdr.pkt_encap = phdr->pkt_encap;
4057 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4059 hdr.pack_flags = phdr->pack_flags;
4060 hdr.opt_comment = g_strdup(pkt_comment);
4063 hdr.pseudo_header = phdr->pseudo_header;
4066 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4068 /* and save the packet */
4069 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
4070 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4075 g_free(hdr.opt_comment);
4080 * Can this capture file be written out in any format using Wiretap
4081 * rather than by copying the raw data?
4084 cf_can_write_with_wiretap(capture_file *cf)
4086 /* We don't care whether we support the comments in this file or not;
4087 if we can't, we'll offer the user the option of discarding the
4089 return wtap_dump_can_write(cf->linktypes, 0);
4093 * Should we let the user do a save?
4097 * the file has unsaved changes, and we can save it in some
4098 * format through Wiretap
4102 * the file is a temporary file and has no unsaved changes (so
4103 * that "saving" it just means copying it).
4105 * XXX - we shouldn't allow files to be edited if they can't be saved,
4106 * so cf->unsaved_changes should be true only if the file can be saved.
4108 * We don't care whether we support the comments in this file or not;
4109 * if we can't, we'll offer the user the option of discarding the
4113 cf_can_save(capture_file *cf)
4115 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4116 /* Saved changes, and we can write it out with Wiretap. */
4120 if (cf->is_tempfile && !cf->unsaved_changes) {
4122 * Temporary file with no unsaved changes, so we can just do a
4128 /* Nothing to save. */
4133 * Should we let the user do a "save as"?
4137 * we can save it in some format through Wiretap
4141 * the file is a temporary file and has no unsaved changes (so
4142 * that "saving" it just means copying it).
4144 * XXX - we shouldn't allow files to be edited if they can't be saved,
4145 * so cf->unsaved_changes should be true only if the file can be saved.
4147 * We don't care whether we support the comments in this file or not;
4148 * if we can't, we'll offer the user the option of discarding the
4152 cf_can_save_as(capture_file *cf)
4154 if (wtap_dump_can_write(cf->linktypes, 0)) {
4155 /* We can write it out with Wiretap. */
4159 if (cf->is_tempfile && !cf->unsaved_changes) {
4161 * Temporary file with no unsaved changes, so we can just do a
4167 /* Nothing to save. */
4172 * Does this file have unsaved data?
4175 cf_has_unsaved_data(capture_file *cf)
4178 * If this is a temporary file, or a file with unsaved changes, it
4181 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4185 * Quick scan to find packet offsets.
4187 static cf_read_status_t
4188 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4190 const struct wtap_pkthdr *phdr;
4195 progdlg_t *progbar = NULL;
4196 GTimer *prog_timer = g_timer_new();
4199 GTimeVal start_time;
4200 gchar status_str[100];
4205 /* Close the old handle. */
4206 wtap_close(cf->wth);
4208 /* Open the new file. */
4209 /* XXX: this will go through all open_routines for a matching one. But right
4210 now rescan_file() is only used when a file is being saved to a different
4211 format than the original, and the user is not given a choice of which
4212 reader to use (only which format to save it in), so doing this makes
4214 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4215 if (cf->wth == NULL) {
4216 cfile_open_failure_alert_box(fname, err, err_info);
4217 return CF_READ_ERROR;
4220 /* We're scanning a file whose contents should be the same as what
4221 we had before, so we don't discard dissection state etc.. */
4224 /* Set the file name because we need it to set the follow stream filter.
4225 XXX - is that still true? We need it for other reasons, though,
4227 cf->filename = g_strdup(fname);
4229 /* Indicate whether it's a permanent or temporary file. */
4230 cf->is_tempfile = is_tempfile;
4232 /* No user changes yet. */
4233 cf->unsaved_changes = FALSE;
4235 cf->cd_t = wtap_file_type_subtype(cf->wth);
4236 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4238 cf->snap = wtap_snapshot_length(cf->wth);
4239 if (cf->snap == 0) {
4240 /* Snapshot length not known. */
4241 cf->has_snap = FALSE;
4242 cf->snap = WTAP_MAX_PACKET_SIZE;
4244 cf->has_snap = TRUE;
4246 name_ptr = g_filename_display_basename(cf->filename);
4248 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4250 /* Record whether the file is compressed.
4251 XXX - do we know this at open time? */
4252 cf->iscompressed = wtap_iscompressed(cf->wth);
4254 /* Find the size of the file. */
4255 size = wtap_file_size(cf->wth, NULL);
4257 g_timer_start(prog_timer);
4259 cf->stop_flag = FALSE;
4260 g_get_current_time(&start_time);
4263 phdr = wtap_phdr(cf->wth);
4264 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
4266 fdata = frame_data_sequence_find(cf->frames, framenum);
4267 fdata->file_off = data_offset;
4270 cf->f_datalen = wtap_read_so_far(cf->wth);
4272 /* Create the progress bar if necessary. */
4273 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4274 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4275 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4276 TRUE, &cf->stop_flag, &start_time, progbar_val);
4280 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4281 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4282 * likely trigger UI paint events, which might take a while depending on
4283 * the platform and display. Reset our timer *after* painting.
4285 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4286 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4287 /* update the packet bar content on the first run or frequently on very large files */
4288 update_progress_dlg(progbar, progbar_val, status_str);
4289 packets_bar_update();
4290 g_timer_start(prog_timer);
4294 if (cf->stop_flag) {
4295 /* Well, the user decided to abort the rescan. Sadly, as this
4296 isn't a reread, recovering is difficult, so we'll just
4297 close the current capture. */
4301 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4302 it's not already there.
4303 XXX - yes, this is O(N), so if every packet had a different
4304 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4305 there are probably going to be a small number of encapsulation types
4307 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4310 /* Free the display name */
4313 /* We're done reading the file; destroy the progress bar if it was created. */
4314 if (progbar != NULL)
4315 destroy_progress_dlg(progbar);
4316 g_timer_destroy(prog_timer);
4318 /* We're done reading sequentially through the file. */
4319 cf->state = FILE_READ_DONE;
4321 /* Close the sequential I/O side, to free up memory it requires. */
4322 wtap_sequential_close(cf->wth);
4324 /* compute the time it took to load the file */
4325 compute_elapsed(cf, &start_time);
4327 /* Set the file encapsulation type now; we don't know what it is until
4328 we've looked at all the packets, as we don't know until then whether
4329 there's more than one type (and thus whether it's
4330 WTAP_ENCAP_PER_PACKET). */
4331 cf->lnk_t = wtap_file_encap(cf->wth);
4333 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4335 if (cf->stop_flag) {
4336 /* Our caller will give up at this point. */
4337 return CF_READ_ABORTED;
4341 /* Put up a message box noting that the read failed somewhere along
4342 the line. Don't throw out the stuff we managed to read, though,
4344 cfile_read_failure_alert_box(NULL, err, err_info);
4345 return CF_READ_ERROR;
4351 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4352 gboolean compressed, gboolean discard_comments,
4353 gboolean dont_reopen)
4356 gchar *fname_new = NULL;
4359 addrinfo_lists_t *addr_lists;
4363 gchar *display_basename;
4370 save_callback_args_t callback_args;
4372 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4374 addr_lists = get_addrinfo_list();
4376 if (save_format == cf->cd_t && compressed == cf->iscompressed
4377 && !discard_comments && !cf->unsaved_changes
4378 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4379 /* We're saving in the format it's already in, and we're
4380 not discarding comments, and there are no changes we have
4381 in memory that aren't saved to the file, and we have no name
4382 resolution blocks to write, so we can just move or copy the raw data. */
4384 if (cf->is_tempfile) {
4385 /* The file being saved is a temporary file from a live
4386 capture, so it doesn't need to stay around under that name;
4387 first, try renaming the capture buffer file to the new name.
4388 This acts as a "safe save", in that, if the file already
4389 exists, the existing file will be removed only if the rename
4392 Sadly, on Windows, as we have the current capture file
4393 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4394 (to cause the rename to remove an existing target), as
4395 done by ws_stdio_rename() (ws_rename() is #defined to
4396 be ws_stdio_rename() on Windows) will fail.
4398 According to the MSDN documentation for CreateFile(), if,
4399 when we open a capture file, we were to directly do a CreateFile(),
4400 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4401 convert it to a file descriptor with _open_osfhandle(),
4402 that would allow the file to be renamed out from under us.
4404 However, that doesn't work in practice. Perhaps the problem
4405 is that the process doing the rename is the process that
4406 has the file open. */
4408 if (ws_rename(cf->filename, fname) == 0) {
4409 /* That succeeded - there's no need to copy the source file. */
4410 how_to_save = SAVE_WITH_MOVE;
4412 if (errno == EXDEV) {
4413 /* They're on different file systems, so we have to copy the
4415 how_to_save = SAVE_WITH_COPY;
4417 /* The rename failed, but not because they're on different
4418 file systems - put up an error message. (Or should we
4419 just punt and try to copy? The only reason why I'd
4420 expect the rename to fail and the copy to succeed would
4421 be if we didn't have permission to remove the file from
4422 the temporary directory, and that might be fixable - but
4423 is it worth requiring the user to go off and fix it?) */
4424 cf_rename_failure_alert_box(fname, errno);
4429 how_to_save = SAVE_WITH_COPY;
4432 /* It's a permanent file, so we should copy it, and not remove the
4434 how_to_save = SAVE_WITH_COPY;
4437 if (how_to_save == SAVE_WITH_COPY) {
4438 /* Copy the file, if we haven't moved it. If we're overwriting
4439 an existing file, we do it with a "safe save", by writing
4440 to a new file and, if the write succeeds, renaming the
4441 new file on top of the old file. */
4442 if (file_exists(fname)) {
4443 fname_new = g_strdup_printf("%s~", fname);
4444 if (!copy_file_binary_mode(cf->filename, fname_new))
4447 if (!copy_file_binary_mode(cf->filename, fname))
4452 /* Either we're saving in a different format or we're saving changes,
4453 such as added, modified, or removed comments, that haven't yet
4454 been written to the underlying file; we can't do that by copying
4455 or moving the capture file, we have to do it by writing the packets
4458 GArray *shb_hdrs = NULL;
4459 wtapng_iface_descriptions_t *idb_inf = NULL;
4460 GArray *nrb_hdrs = NULL;
4463 /* XXX: what free's this shb_hdr? */
4464 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4465 idb_inf = wtap_file_get_idb_info(cf->wth);
4466 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4468 /* Determine what file encapsulation type we should use. */
4469 encap = wtap_dump_file_encap_type(cf->linktypes);
4471 if (file_exists(fname)) {
4472 /* We're overwriting an existing file; write out to a new file,
4473 and, if that succeeds, rename the new file on top of the
4474 old file. That makes this a "safe save", so that we don't
4475 lose the old file if we have a problem writing out the new
4476 file. (If the existing file is the current capture file,
4477 we *HAVE* to do that, otherwise we're overwriting the file
4478 from which we're reading the packets that we're writing!) */
4479 fname_new = g_strdup_printf("%s~", fname);
4480 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4481 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4483 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4484 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4490 cfile_dump_open_failure_alert_box(fname, err, save_format);
4494 /* Add address resolution */
4495 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4497 /* Iterate through the list of packets, processing all the packets. */
4498 callback_args.pdh = pdh;
4499 callback_args.fname = fname;
4500 callback_args.file_type = save_format;
4501 switch (process_specified_records(cf, NULL, "Saving", "packets",
4502 TRUE, save_record, &callback_args, TRUE)) {
4505 /* Completed successfully. */
4509 /* The user decided to abort the saving.
4510 If we're writing to a temporary file, remove it.
4511 XXX - should we do so even if we're not writing to a
4513 wtap_dump_close(pdh, &err);
4514 if (fname_new != NULL)
4515 ws_unlink(fname_new);
4516 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4517 return CF_WRITE_ABORTED;
4520 /* Error while saving.
4521 If we're writing to a temporary file, remove it. */
4522 if (fname_new != NULL)
4523 ws_unlink(fname_new);
4524 wtap_dump_close(pdh, &err);
4528 if (!wtap_dump_close(pdh, &err)) {
4529 cfile_close_failure_alert_box(fname, err);
4533 how_to_save = SAVE_WITH_WTAP;
4536 if (fname_new != NULL) {
4537 /* We wrote out to fname_new, and should rename it on top of
4538 fname. fname_new is now closed, so that should be possible even
4539 on Windows. However, on Windows, we first need to close whatever
4540 file descriptors we have open for fname. */
4542 wtap_fdclose(cf->wth);
4544 /* Now do the rename. */
4545 if (ws_rename(fname_new, fname) == -1) {
4546 /* Well, the rename failed. */
4547 cf_rename_failure_alert_box(fname, errno);
4549 /* Attempt to reopen the random file descriptor using the
4550 current file's filename. (At this point, the sequential
4551 file descriptor is closed.) */
4552 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4553 /* Oh, well, we're screwed. */
4554 display_basename = g_filename_display_basename(cf->filename);
4555 simple_error_message_box(
4556 file_open_error_message(err, FALSE), display_basename);
4557 g_free(display_basename);
4564 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4565 cf->unsaved_changes = FALSE;
4568 switch (how_to_save) {
4570 case SAVE_WITH_MOVE:
4571 /* We just moved the file, so the wtap structure refers to the
4572 new file, and all the information other than the filename
4573 and the "is temporary" status applies to the new file; just
4575 g_free(cf->filename);
4576 cf->filename = g_strdup(fname);
4577 cf->is_tempfile = FALSE;
4578 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4581 case SAVE_WITH_COPY:
4582 /* We just copied the file, s all the information other than
4583 the wtap structure, the filename, and the "is temporary"
4584 status applies to the new file; just update that. */
4585 wtap_close(cf->wth);
4586 /* Although we're just "copying" and then opening the copy, it will
4587 try all open_routine readers to open the copy, so we need to
4588 reset the cfile's open_type. */
4589 cf->open_type = WTAP_TYPE_AUTO;
4590 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4591 if (cf->wth == NULL) {
4592 cfile_open_failure_alert_box(fname, err, err_info);
4595 g_free(cf->filename);
4596 cf->filename = g_strdup(fname);
4597 cf->is_tempfile = FALSE;
4599 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4602 case SAVE_WITH_WTAP:
4603 /* Open and read the file we saved to.
4605 XXX - this is somewhat of a waste; we already have the
4606 packets, all this gets us is updated file type information
4607 (which we could just stuff into "cf"), and having the new
4608 file be the one we have opened and from which we're reading
4609 the data, and it means we have to spend time opening and
4610 reading the file, which could be a significant amount of
4611 time if the file is large.
4613 If the capture-file-writing code were to return the
4614 seek offset of each packet it writes, we could save that
4615 in the frame_data structure for the frame, and just open
4616 the file without reading it again...
4618 ...as long as, for gzipped files, the process of writing
4619 out the file *also* generates the information needed to
4620 support fast random access to the compressed file. */
4621 /* rescan_file will cause us to try all open_routines, so
4622 reset cfile's open_type */
4623 cf->open_type = WTAP_TYPE_AUTO;
4624 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4625 /* The rescan failed; just close the file. Either
4626 a dialog was popped up for the failure, so the
4627 user knows what happened, or they stopped the
4628 rescan, in which case they know what happened. */
4634 /* If we were told to discard the comments, do so. */
4635 if (discard_comments) {
4636 /* Remove SHB comment, if any. */
4637 wtap_write_shb_comment(cf->wth, NULL);
4639 /* remove all user comments */
4640 for (framenum = 1; framenum <= cf->count; framenum++) {
4641 fdata = frame_data_sequence_find(cf->frames, framenum);
4643 fdata->flags.has_phdr_comment = FALSE;
4644 fdata->flags.has_user_comment = FALSE;
4647 if (cf->frames_user_comments) {
4648 g_tree_destroy(cf->frames_user_comments);
4649 cf->frames_user_comments = NULL;
4652 cf->packet_comment_count = 0;
4658 if (fname_new != NULL) {
4659 /* We were trying to write to a temporary file; get rid of it if it
4660 exists. (We don't care whether this fails, as, if it fails,
4661 there's not much we can do about it. I guess if it failed for
4662 a reason other than "it doesn't exist", we could report an
4663 error, so the user knows there's a junk file that they might
4664 want to clean up.) */
4665 ws_unlink(fname_new);
4668 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4669 return CF_WRITE_ERROR;
4673 cf_export_specified_packets(capture_file *cf, const char *fname,
4674 packet_range_t *range, guint save_format,
4675 gboolean compressed)
4677 gchar *fname_new = NULL;
4680 save_callback_args_t callback_args;
4681 GArray *shb_hdrs = NULL;
4682 wtapng_iface_descriptions_t *idb_inf = NULL;
4683 GArray *nrb_hdrs = NULL;
4686 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4688 packet_range_process_init(range);
4690 /* We're writing out specified packets from the specified capture
4691 file to another file. Even if all captured packets are to be
4692 written, don't special-case the operation - read each packet
4693 and then write it out if it's one of the specified ones. */
4695 /* XXX: what free's this shb_hdr? */
4696 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4697 idb_inf = wtap_file_get_idb_info(cf->wth);
4698 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4700 /* Determine what file encapsulation type we should use. */
4701 encap = wtap_dump_file_encap_type(cf->linktypes);
4703 if (file_exists(fname)) {
4704 /* We're overwriting an existing file; write out to a new file,
4705 and, if that succeeds, rename the new file on top of the
4706 old file. That makes this a "safe save", so that we don't
4707 lose the old file if we have a problem writing out the new
4708 file. (If the existing file is the current capture file,
4709 we *HAVE* to do that, otherwise we're overwriting the file
4710 from which we're reading the packets that we're writing!) */
4711 fname_new = g_strdup_printf("%s~", fname);
4712 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4713 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4715 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4716 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4722 cfile_dump_open_failure_alert_box(fname, err, save_format);
4726 /* Add address resolution */
4727 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4729 /* Iterate through the list of packets, processing the packets we were
4732 XXX - we've already called "packet_range_process_init(range)", but
4733 "process_specified_records()" will do it again. Fortunately,
4734 that's harmless in this case, as we haven't done anything to
4735 "range" since we initialized it. */
4736 callback_args.pdh = pdh;
4737 callback_args.fname = fname;
4738 callback_args.file_type = save_format;
4739 switch (process_specified_records(cf, range, "Writing", "specified records",
4740 TRUE, save_record, &callback_args, TRUE)) {
4743 /* Completed successfully. */
4747 /* The user decided to abort the saving.
4748 If we're writing to a temporary file, remove it.
4749 XXX - should we do so even if we're not writing to a
4751 wtap_dump_close(pdh, &err);
4752 if (fname_new != NULL)
4753 ws_unlink(fname_new);
4754 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4755 return CF_WRITE_ABORTED;
4759 /* Error while saving.
4760 If we're writing to a temporary file, remove it. */
4761 if (fname_new != NULL)
4762 ws_unlink(fname_new);
4763 wtap_dump_close(pdh, &err);
4767 if (!wtap_dump_close(pdh, &err)) {
4768 cfile_close_failure_alert_box(fname, err);
4772 if (fname_new != NULL) {
4773 /* We wrote out to fname_new, and should rename it on top of
4774 fname; fname is now closed, so that should be possible even
4775 on Windows. Do the rename. */
4776 if (ws_rename(fname_new, fname) == -1) {
4777 /* Well, the rename failed. */
4778 cf_rename_failure_alert_box(fname, errno);
4783 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4787 if (fname_new != NULL) {
4788 /* We were trying to write to a temporary file; get rid of it if it
4789 exists. (We don't care whether this fails, as, if it fails,
4790 there's not much we can do about it. I guess if it failed for
4791 a reason other than "it doesn't exist", we could report an
4792 error, so the user knows there's a junk file that they might
4793 want to clean up.) */
4794 ws_unlink(fname_new);
4797 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4798 return CF_WRITE_ERROR;
4802 * XXX - whether we mention the source pathname, the target pathname,
4803 * or both depends on the error and on what we find if we look for
4804 * one or both of them.
4807 cf_rename_failure_alert_box(const char *filename, int err)
4809 gchar *display_basename;
4811 display_basename = g_filename_display_basename(filename);
4815 /* XXX - should check whether the source exists and, if not,
4816 report it as the problem and, if so, report the destination
4818 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4823 /* XXX - if we're doing a rename after a safe save, we should
4824 probably say something else. */
4825 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4830 /* XXX - this should probably mention both the source and destination
4832 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4833 display_basename, wtap_strerror(err));
4836 g_free(display_basename);
4839 /* Reload the current capture file. */
4841 cf_reload(capture_file *cf) {
4843 gboolean is_tempfile;
4846 /* If the file could be opened, "cf_open()" calls "cf_close()"
4847 to get rid of state for the old capture file before filling in state
4848 for the new capture file. "cf_close()" will remove the file if
4849 it's a temporary file; we don't want that to happen (for one thing,
4850 it'd prevent subsequent reopens from working). Remember whether it's
4851 a temporary file, mark it as not being a temporary file, and then
4852 reopen it as the type of file it was.
4854 Also, "cf_close()" will free "cf->filename", so we must make
4855 a copy of it first. */
4856 filename = g_strdup(cf->filename);
4857 is_tempfile = cf->is_tempfile;
4858 cf->is_tempfile = FALSE;
4859 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4860 switch (cf_read(cf, TRUE)) {
4864 /* Just because we got an error, that doesn't mean we were unable
4865 to read any of the file; we handle what we could get from the
4869 case CF_READ_ABORTED:
4870 /* The user bailed out of re-reading the capture file; the
4871 capture file has been closed - just free the capture file name
4872 string and return (without changing the last containing
4878 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4879 Instead, the file was left open, so we should restore "cf->is_tempfile"
4882 XXX - change the menu? Presumably "cf_open()" will do that;
4883 make sure it does! */
4884 cf->is_tempfile = is_tempfile;
4886 /* "cf_open()" made a copy of the file name we handed it, so
4887 we should free up our copy. */
4897 * indent-tabs-mode: nil
4900 * ex: set shiftwidth=2 tabstop=8 expandtab:
4901 * :indentSize=2:tabSize=8:noTabs=true: