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);
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);
1209 epan_dissect_t rf_edt;
1211 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1212 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1213 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1214 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1215 epan_dissect_cleanup(&rf_edt);
1219 /* This does a shallow copy of fdlocal, which is good enough. */
1220 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1223 if (phdr->opt_comment != NULL)
1224 cf->packet_comment_count++;
1225 cf->f_datalen = offset + fdlocal.cap_len;
1227 if (!cf->redissecting) {
1228 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1229 cinfo, phdr, buf, TRUE);
1237 typedef struct _callback_data_t {
1240 GTimeVal start_time;
1248 merge_callback(merge_event event, int num _U_,
1249 const merge_in_file_t in_files[], const guint in_file_count,
1253 callback_data_t *cb_data = (callback_data_t*) data;
1255 g_assert(cb_data != NULL);
1259 case MERGE_EVENT_INPUT_FILES_OPENED:
1263 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1267 case MERGE_EVENT_READY_TO_MERGE:
1268 /* Get the sum of the sizes of all the files. */
1269 for (i = 0; i < in_file_count; i++)
1270 cb_data->f_len += in_files[i].size;
1272 cb_data->prog_timer = g_timer_new();
1273 g_timer_start(cb_data->prog_timer);
1275 g_get_current_time(&cb_data->start_time);
1278 case MERGE_EVENT_PACKET_WAS_READ:
1280 gint64 data_offset = 0;
1282 /* Get the sum of the data offsets in all of the files. */
1284 for (i = 0; i < in_file_count; i++)
1285 data_offset += in_files[i].data_offset;
1287 /* Create the progress bar if necessary.
1288 We check on every iteration of the loop, so that it takes no
1289 longer than the standard time to create it (otherwise, for a
1290 large file, we might take considerably longer than that standard
1291 time in order to get to the next progress bar step). */
1292 if (cb_data->progbar == NULL) {
1293 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1294 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1298 * Update the progress bar, but do it only after
1299 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1300 * and packets_bar_update will likely trigger UI paint events, which
1301 * might take a while depending on the platform and display. Reset
1302 * our timer *after* painting.
1304 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1306 gint64 file_pos = 0;
1307 /* Get the sum of the seek positions in all of the files. */
1308 for (i = 0; i < in_file_count; i++)
1309 file_pos += wtap_read_so_far(in_files[i].wth);
1311 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1312 if (progbar_val > 1.0f) {
1313 /* Some file probably grew while we were reading it.
1314 That "shouldn't happen", so we'll just clip the progress
1319 if (cb_data->progbar != NULL) {
1320 gchar status_str[100];
1321 g_snprintf(status_str, sizeof(status_str),
1322 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1323 file_pos / 1024, cb_data->f_len / 1024);
1324 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1326 g_timer_start(cb_data->prog_timer);
1331 case MERGE_EVENT_DONE:
1332 /* We're done merging the files; destroy the progress bar if it was created. */
1333 if (cb_data->progbar != NULL)
1334 destroy_progress_dlg(cb_data->progbar);
1335 g_timer_destroy(cb_data->prog_timer);
1339 return cb_data->stop_flag;
1345 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1346 int in_file_count, char *const *in_filenames,
1347 int file_type, gboolean do_append)
1350 gchar *err_info = NULL;
1352 guint32 err_framenum;
1353 merge_result status;
1354 merge_progress_callback_t cb;
1355 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1357 /* prepare our callback routine */
1358 cb_data->pd_window = pd_window;
1359 cb.callback_func = merge_callback;
1362 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1364 /* merge the files */
1365 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1366 (const char *const *) in_filenames,
1367 in_file_count, do_append,
1368 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1369 "Wireshark", &cb, &err, &err_info,
1370 &err_fileno, &err_framenum);
1378 case MERGE_USER_ABORTED:
1379 /* this isn't really an error, though we will return CF_ERROR later */
1382 case MERGE_ERR_CANT_OPEN_INFILE:
1383 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1386 case MERGE_ERR_CANT_OPEN_OUTFILE:
1387 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1390 case MERGE_ERR_CANT_READ_INFILE:
1391 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1394 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1395 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1396 err_framenum, in_filenames[err_fileno]);
1399 case MERGE_ERR_CANT_WRITE_OUTFILE:
1400 cfile_write_failure_alert_box(in_filenames[err_fileno],
1401 *out_filenamep, err, err_info,
1402 err_framenum, file_type);
1405 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1406 cfile_close_failure_alert_box(*out_filenamep, err);
1410 simple_error_message_box("Unknown merge_files error %d", status);
1414 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1416 if (status != MERGE_OK) {
1417 /* Callers aren't expected to treat an error or an explicit abort
1418 differently - we put up error dialogs ourselves, so they don't
1426 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1428 const char *filter_new = dftext ? dftext : "";
1429 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1432 GTimeVal start_time;
1434 /* if new filter equals old one, do nothing unless told to do so */
1435 if (!force && strcmp(filter_new, filter_old) == 0) {
1441 if (dftext == NULL) {
1442 /* The new filter is an empty filter (i.e., display all packets).
1443 * so leave dfcode==NULL
1447 * We have a filter; make a copy of it (as we'll be saving it),
1448 * and try to compile it.
1450 dftext = g_strdup(dftext);
1451 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1452 /* The attempt failed; report an error. */
1453 simple_message_box(ESD_TYPE_ERROR, NULL,
1454 "See the help for a description of the display filter syntax.",
1455 "\"%s\" isn't a valid display filter: %s",
1463 if (dfcode == NULL) {
1464 /* Yes - free the filter text, and set it to null. */
1470 /* We have a valid filter. Replace the current filter. */
1471 g_free(cf->dfilter);
1472 cf->dfilter = dftext;
1473 g_get_current_time(&start_time);
1476 /* Now rescan the packet list, applying the new filter, but not
1477 throwing away information constructed on a previous pass. */
1478 if (cf->state != FILE_CLOSED) {
1479 if (dftext == NULL) {
1480 rescan_packets(cf, "Resetting", "Filter", FALSE);
1482 rescan_packets(cf, "Filtering", dftext, FALSE);
1486 /* Cleanup and release all dfilter resources */
1487 dfilter_free(dfcode);
1493 cf_reftime_packets(capture_file *cf)
1495 ref_time_packets(cf);
1499 cf_redissect_packets(capture_file *cf)
1501 if (cf->state != FILE_CLOSED) {
1502 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1507 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1508 struct wtap_pkthdr *phdr, Buffer *buf)
1513 #ifdef WANT_PACKET_EDITOR
1514 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1515 if (G_UNLIKELY(fdata->file_off == -1)) {
1516 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1519 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1523 *phdr = frame->phdr;
1524 ws_buffer_assure_space(buf, frame->phdr.caplen);
1525 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1530 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1531 cfile_read_failure_alert_box(cf->filename, err, err_info);
1538 cf_read_record(capture_file *cf, frame_data *fdata)
1540 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1543 /* Rescan the list of packets, reconstructing the CList.
1545 "action" describes why we're doing this; it's used in the progress
1548 "action_item" describes what we're doing; it's used in the progress
1551 "redissect" is TRUE if we need to make the dissectors reconstruct
1552 any state information they have (because a preference that affects
1553 some dissector has changed, meaning some dissector might construct
1554 its state differently from the way it was constructed the last time). */
1556 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1558 /* Rescan packets new packet list */
1561 progdlg_t *progbar = NULL;
1562 GTimer *prog_timer = g_timer_new();
1564 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1565 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1566 gboolean selected_frame_seen;
1568 GTimeVal start_time;
1569 gchar status_str[100];
1573 gboolean create_proto_tree;
1575 gboolean add_to_packet_list = FALSE;
1577 guint32 frames_count;
1579 /* Compile the current display filter.
1580 * We assume this will not fail since cf->dfilter is only set in
1581 * cf_filter IFF the filter was valid.
1583 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1584 g_assert(!cf->dfilter || (compiled && dfcode));
1586 /* Get the union of the flags for all tap listeners. */
1587 tap_flags = union_of_tap_listener_flags();
1589 /* If any tap listeners require the columns, construct them. */
1590 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1593 * Determine whether we need to create a protocol tree.
1596 * we're going to apply a display filter;
1598 * one of the tap listeners is going to apply a filter;
1600 * one of the tap listeners requires a protocol tree;
1602 * we're redissecting and a postdissector wants field
1603 * values or protocols on the first pass.
1606 (dfcode != NULL || have_filtering_tap_listeners() ||
1607 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1608 (redissect && postdissectors_want_hfids()));
1610 reset_tap_listeners();
1611 /* Which frame, if any, is the currently selected frame?
1612 XXX - should the selected frame or the focus frame be the "current"
1613 frame, that frame being the one from which "Find Frame" searches
1615 selected_frame = cf->current_frame;
1617 /* Mark frame num as not found */
1618 selected_frame_num = -1;
1620 /* Freeze the packet list while we redo it, so we don't get any
1621 screen updates while it happens. */
1622 packet_list_freeze();
1625 /* We need to re-initialize all the state information that protocols
1626 keep, because some preference that controls a dissector has changed,
1627 which might cause the state information to be constructed differently
1628 by that dissector. */
1630 /* We might receive new packets while redissecting, and we don't
1631 want to dissect those before their time. */
1632 cf->redissecting = TRUE;
1634 /* 'reset' dissection session */
1635 epan_free(cf->epan);
1636 if (cf->edt && cf->edt->pi.fd) {
1637 /* All pointers in "per frame proto data" for the currently selected
1638 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1639 Free them here to avoid unintended usage in packet_list_clear(). */
1640 frame_data_destroy(cf->edt->pi.fd);
1642 cf->epan = ws_epan_new(cf);
1643 cf->cinfo.epan = cf->epan;
1645 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1646 called via epan_new() / init_dissection() when reloading Lua plugins. */
1647 if (!create_proto_tree && have_filtering_tap_listeners()) {
1648 create_proto_tree = TRUE;
1651 /* We need to redissect the packets so we have to discard our old
1652 * packet list store. */
1653 packet_list_clear();
1654 add_to_packet_list = TRUE;
1657 /* We don't yet know which will be the first and last frames displayed. */
1658 cf->first_displayed = 0;
1659 cf->last_displayed = 0;
1661 /* We currently don't display any packets */
1662 cf->displayed_count = 0;
1664 /* Iterate through the list of frames. Call a routine for each frame
1665 to check whether it should be displayed and, if so, add it to
1666 the display list. */
1668 cf->prev_dis = NULL;
1669 cf->prev_cap = NULL;
1672 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1674 g_timer_start(prog_timer);
1675 /* Count of packets at which we've looked. */
1677 /* Progress so far. */
1680 cf->stop_flag = FALSE;
1681 g_get_current_time(&start_time);
1683 /* no previous row yet */
1684 prev_frame_num = -1;
1687 preceding_frame_num = -1;
1688 preceding_frame = NULL;
1689 following_frame_num = -1;
1690 following_frame = NULL;
1692 selected_frame_seen = FALSE;
1694 frames_count = cf->count;
1696 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1698 for (framenum = 1; framenum <= frames_count; framenum++) {
1699 fdata = frame_data_sequence_find(cf->frames, framenum);
1701 /* Create the progress bar if necessary.
1702 We check on every iteration of the loop, so that it takes no
1703 longer than the standard time to create it (otherwise, for a
1704 large file, we might take considerably longer than that standard
1705 time in order to get to the next progress bar step). */
1706 if (progbar == NULL)
1707 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1713 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1714 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1715 * likely trigger UI paint events, which might take a while depending on
1716 * the platform and display. Reset our timer *after* painting.
1718 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1719 /* let's not divide by zero. I should never be started
1720 * with count == 0, so let's assert that
1722 g_assert(cf->count > 0);
1723 progbar_val = (gfloat) count / frames_count;
1725 if (progbar != NULL) {
1726 g_snprintf(status_str, sizeof(status_str),
1727 "%4u of %u frames", count, frames_count);
1728 update_progress_dlg(progbar, progbar_val, status_str);
1731 g_timer_start(prog_timer);
1734 if (cf->stop_flag) {
1735 /* Well, the user decided to abort the filtering. Just stop.
1737 XXX - go back to the previous filter? Users probably just
1738 want not to wait for a filtering operation to finish;
1739 unless we cancel by having no filter, reverting to the
1740 previous filter will probably be even more expensive than
1741 continuing the filtering, as it involves going back to the
1742 beginning and filtering, and even with no filter we currently
1743 have to re-generate the entire clist, which is also expensive.
1745 I'm not sure what Network Monitor does, but it doesn't appear
1746 to give you an unfiltered display if you cancel. */
1753 /* Since all state for the frame was destroyed, mark the frame
1754 * as not visited, free the GSList referring to the state
1755 * data (the per-frame data itself was freed by
1756 * "init_dissection()"), and null out the GSList pointer. */
1757 frame_data_reset(fdata);
1758 frames_count = cf->count;
1761 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1762 fdata->flags.dependent_of_displayed = 0;
1764 if (!cf_read_record(cf, fdata))
1765 break; /* error reading the frame */
1767 /* If the previous frame is displayed, and we haven't yet seen the
1768 selected frame, remember that frame - it's the closest one we've
1769 yet seen before the selected frame. */
1770 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1771 preceding_frame_num = prev_frame_num;
1772 preceding_frame = prev_frame;
1775 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1777 ws_buffer_start_ptr(&cf->buf),
1778 add_to_packet_list);
1780 /* If this frame is displayed, and this is the first frame we've
1781 seen displayed after the selected frame, remember this frame -
1782 it's the closest one we've yet seen at or after the selected
1784 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1785 following_frame_num = fdata->num;
1786 following_frame = fdata;
1788 if (fdata == selected_frame) {
1789 selected_frame_seen = TRUE;
1790 if (fdata->flags.passed_dfilter)
1791 selected_frame_num = fdata->num;
1794 /* Remember this frame - it'll be the previous frame
1795 on the next pass through the loop. */
1796 prev_frame_num = fdata->num;
1800 epan_dissect_cleanup(&edt);
1802 /* We are done redissecting the packet list. */
1803 cf->redissecting = FALSE;
1806 frames_count = cf->count;
1807 /* Clear out what remains of the visited flags and per-frame data
1810 XXX - that may cause various forms of bogosity when dissecting
1811 these frames, as they won't have been seen by this sequential
1812 pass, but the only alternative I see is to keep scanning them
1813 even though the user requested that the scan stop, and that
1814 would leave the user stuck with an Wireshark grinding on
1815 until it finishes. Should we just stick them with that? */
1816 for (; framenum <= frames_count; framenum++) {
1817 fdata = frame_data_sequence_find(cf->frames, framenum);
1818 frame_data_reset(fdata);
1822 /* We're done filtering the packets; destroy the progress bar if it
1824 if (progbar != NULL)
1825 destroy_progress_dlg(progbar);
1826 g_timer_destroy(prog_timer);
1828 /* Unfreeze the packet list. */
1829 if (!add_to_packet_list)
1830 packet_list_recreate_visible_rows();
1832 /* Compute the time it took to filter the file */
1833 compute_elapsed(cf, &start_time);
1837 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1839 if (selected_frame_num == -1) {
1840 /* The selected frame didn't pass the filter. */
1841 if (selected_frame == NULL) {
1842 /* That's because there *was* no selected frame. Make the first
1843 displayed frame the current frame. */
1844 selected_frame_num = 0;
1846 /* Find the nearest displayed frame to the selected frame (whether
1847 it's before or after that frame) and make that the current frame.
1848 If the next and previous displayed frames are equidistant from the
1849 selected frame, choose the next one. */
1850 g_assert(following_frame == NULL ||
1851 following_frame->num >= selected_frame->num);
1852 g_assert(preceding_frame == NULL ||
1853 preceding_frame->num <= selected_frame->num);
1854 if (following_frame == NULL) {
1855 /* No frame after the selected frame passed the filter, so we
1856 have to select the last displayed frame before the selected
1858 selected_frame_num = preceding_frame_num;
1859 selected_frame = preceding_frame;
1860 } else if (preceding_frame == NULL) {
1861 /* No frame before the selected frame passed the filter, so we
1862 have to select the first displayed frame after the selected
1864 selected_frame_num = following_frame_num;
1865 selected_frame = following_frame;
1867 /* Frames before and after the selected frame passed the filter, so
1868 we'll select the previous frame */
1869 selected_frame_num = preceding_frame_num;
1870 selected_frame = preceding_frame;
1875 if (selected_frame_num == -1) {
1876 /* There are no frames displayed at all. */
1877 cf_unselect_packet(cf);
1879 /* Either the frame that was selected passed the filter, or we've
1880 found the nearest displayed frame to that frame. Select it, make
1881 it the focus row, and make it visible. */
1882 /* Set to invalid to force update of packet list and packet details */
1883 cf->current_row = -1;
1884 if (selected_frame_num == 0) {
1885 packet_list_select_first_row();
1887 if (!packet_list_select_row_from_data(selected_frame)) {
1888 /* We didn't find a row corresponding to this frame.
1889 This means that the frame isn't being displayed currently,
1890 so we can't select it. */
1891 simple_message_box(ESD_TYPE_INFO, NULL,
1892 "The capture file is probably not fully dissected.",
1893 "End of capture exceeded.");
1898 /* Cleanup and release all dfilter resources */
1899 dfilter_free(dfcode);
1904 * Scan through all frame data and recalculate the ref time
1905 * without rereading the file.
1906 * XXX - do we need a progres bar or is this fast enough?
1909 ref_time_packets(capture_file *cf)
1916 cf->prev_dis = NULL;
1919 for (framenum = 1; framenum <= cf->count; framenum++) {
1920 fdata = frame_data_sequence_find(cf->frames, framenum);
1922 /* just add some value here until we know if it is being displayed or not */
1923 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1929 /* If we don't have the time stamp of the first packet in the
1930 capture, it's because this is the first packet. Save the time
1931 stamp of this packet as the time stamp of the first packet. */
1932 if (cf->ref == NULL)
1934 /* if this frames is marked as a reference time frame, reset
1935 firstsec and firstusec to this frame */
1936 if (fdata->flags.ref_time)
1939 /* If we don't have the time stamp of the previous displayed packet,
1940 it's because this is the first displayed packet. Save the time
1941 stamp of this packet as the time stamp of the previous displayed
1943 if (cf->prev_dis == NULL) {
1944 cf->prev_dis = fdata;
1947 /* Get the time elapsed between the first packet and this packet. */
1948 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1949 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1951 /* If it's greater than the current elapsed time, set the elapsed time
1952 to it (we check for "greater than" so as not to be confused by
1953 time moving backwards). */
1954 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1955 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1956 cf->elapsed_time = rel_ts;
1959 /* If this frame is displayed, get the time elapsed between the
1960 previous displayed packet and this packet. */
1961 if ( fdata->flags.passed_dfilter ) {
1962 fdata->prev_dis_num = cf->prev_dis->num;
1963 cf->prev_dis = fdata;
1969 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1970 /* This frame either passed the display filter list or is marked as
1971 a time reference frame. All time reference frames are displayed
1972 even if they don't pass the display filter */
1973 if (fdata->flags.ref_time) {
1974 /* if this was a TIME REF frame we should reset the cum_bytes field */
1975 cf->cum_bytes = fdata->pkt_len;
1976 fdata->cum_bytes = cf->cum_bytes;
1978 /* increase cum_bytes with this packets length */
1979 cf->cum_bytes += fdata->pkt_len;
1992 process_specified_records(capture_file *cf, packet_range_t *range,
1993 const char *string1, const char *string2, gboolean terminate_is_stop,
1994 gboolean (*callback)(capture_file *, frame_data *,
1995 struct wtap_pkthdr *, const guint8 *, void *),
1996 void *callback_args,
1997 gboolean show_progress_bar)
2002 psp_return_t ret = PSP_FINISHED;
2004 progdlg_t *progbar = NULL;
2005 GTimer *prog_timer = g_timer_new();
2008 GTimeVal progbar_start_time;
2009 gchar progbar_status_str[100];
2010 range_process_e process_this;
2011 struct wtap_pkthdr phdr;
2013 wtap_phdr_init(&phdr);
2014 ws_buffer_init(&buf, 1500);
2016 g_timer_start(prog_timer);
2017 /* Count of packets at which we've looked. */
2019 /* Progress so far. */
2022 cf->stop_flag = FALSE;
2023 g_get_current_time(&progbar_start_time);
2026 packet_range_process_init(range);
2028 /* Iterate through all the packets, printing the packets that
2029 were selected by the current display filter. */
2030 for (framenum = 1; framenum <= cf->count; framenum++) {
2031 fdata = frame_data_sequence_find(cf->frames, framenum);
2033 /* Create the progress bar if necessary.
2034 We check on every iteration of the loop, so that it takes no
2035 longer than the standard time to create it (otherwise, for a
2036 large file, we might take considerably longer than that standard
2037 time in order to get to the next progress bar step). */
2038 if (show_progress_bar && progbar == NULL)
2039 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2042 &progbar_start_time,
2046 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2047 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2048 * likely trigger UI paint events, which might take a while depending on
2049 * the platform and display. Reset our timer *after* painting.
2051 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2052 /* let's not divide by zero. I should never be started
2053 * with count == 0, so let's assert that
2055 g_assert(cf->count > 0);
2056 progbar_val = (gfloat) progbar_count / cf->count;
2058 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2059 "%4u of %u packets", progbar_count, cf->count);
2060 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2062 g_timer_start(prog_timer);
2065 if (cf->stop_flag) {
2066 /* Well, the user decided to abort the operation. Just stop,
2067 and arrange to return PSP_STOPPED to our caller, so they know
2068 it was stopped explicitly. */
2075 if (range != NULL) {
2076 /* do we have to process this packet? */
2077 process_this = packet_range_process_packet(range, fdata);
2078 if (process_this == range_process_next) {
2079 /* this packet uninteresting, continue with next one */
2081 } else if (process_this == range_processing_finished) {
2082 /* all interesting packets processed, stop the loop */
2087 /* Get the packet */
2088 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2089 /* Attempt to get the packet failed. */
2093 /* Process the packet */
2094 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2095 /* Callback failed. We assume it reported the error appropriately. */
2101 /* We're done printing the packets; destroy the progress bar if
2103 if (progbar != NULL)
2104 destroy_progress_dlg(progbar);
2105 g_timer_destroy(prog_timer);
2107 wtap_phdr_cleanup(&phdr);
2108 ws_buffer_free(&buf);
2116 } retap_callback_args_t;
2119 retap_packet(capture_file *cf, frame_data *fdata,
2120 struct wtap_pkthdr *phdr, const guint8 *pd,
2123 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2125 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2126 epan_dissect_reset(&args->edt);
2132 cf_retap_packets(capture_file *cf)
2134 packet_range_t range;
2135 retap_callback_args_t callback_args;
2136 gboolean create_proto_tree;
2140 /* Presumably the user closed the capture file. */
2142 return CF_READ_ABORTED;
2145 cf_callback_invoke(cf_cb_file_retap_started, cf);
2147 /* Get the union of the flags for all tap listeners. */
2148 tap_flags = union_of_tap_listener_flags();
2150 /* If any tap listeners require the columns, construct them. */
2151 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2154 * Determine whether we need to create a protocol tree.
2157 * one of the tap listeners is going to apply a filter;
2159 * one of the tap listeners requires a protocol tree.
2162 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2164 /* Reset the tap listeners. */
2165 reset_tap_listeners();
2167 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2169 /* Iterate through the list of packets, dissecting all packets and
2170 re-running the taps. */
2171 packet_range_init(&range, cf);
2172 packet_range_process_init(&range);
2174 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2175 "all packets", TRUE, retap_packet,
2176 &callback_args, TRUE);
2178 epan_dissect_cleanup(&callback_args.edt);
2180 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2184 /* Completed successfully. */
2188 /* Well, the user decided to abort the refiltering.
2189 Return CF_READ_ABORTED so our caller knows they did that. */
2190 return CF_READ_ABORTED;
2193 /* Error while retapping. */
2194 return CF_READ_ERROR;
2197 g_assert_not_reached();
2202 print_args_t *print_args;
2203 gboolean print_header_line;
2204 char *header_line_buf;
2205 int header_line_buf_len;
2206 gboolean print_formfeed;
2207 gboolean print_separator;
2211 int num_visible_cols;
2214 } print_callback_args_t;
2217 print_packet(capture_file *cf, frame_data *fdata,
2218 struct wtap_pkthdr *phdr, const guint8 *pd,
2221 print_callback_args_t *args = (print_callback_args_t *)argsp;
2227 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2228 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2229 col_item_t* col_item;
2231 /* Fill in the column information if we're printing the summary
2233 if (args->print_args->print_summary) {
2234 col_custom_prime_edt(&args->edt, &cf->cinfo);
2235 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2236 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2238 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2240 if (args->print_formfeed) {
2241 if (!new_page(args->print_args->stream))
2244 if (args->print_separator) {
2245 if (!print_line(args->print_args->stream, 0, ""))
2251 * We generate bookmarks, if the output format supports them.
2252 * The name is "__frameN__".
2254 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2256 if (args->print_args->print_summary) {
2257 if (!args->print_args->print_col_headings)
2258 args->print_header_line = FALSE;
2259 if (args->print_header_line) {
2260 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2262 args->print_header_line = FALSE; /* we might not need to print any more */
2264 cp = &args->line_buf[0];
2266 for (i = 0; i < args->num_visible_cols; i++) {
2267 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2268 /* Find the length of the string for this column. */
2269 column_len = (int) strlen(col_item->col_data);
2270 if (args->col_widths[i] > column_len)
2271 column_len = args->col_widths[i];
2273 /* Make sure there's room in the line buffer for the column; if not,
2274 double its length. */
2275 line_len += column_len + 1; /* "+1" for space */
2276 if (line_len > args->line_buf_len) {
2277 cp_off = (int) (cp - args->line_buf);
2278 args->line_buf_len = 2 * line_len;
2279 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2280 cp = args->line_buf + cp_off;
2283 /* Right-justify the packet number column. */
2284 if (col_item->col_fmt == COL_NUMBER)
2285 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2287 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2289 if (i != args->num_visible_cols - 1)
2295 * Generate a bookmark, using the summary line as the title.
2297 if (!print_bookmark(args->print_args->stream, bookmark_name,
2301 if (!print_line(args->print_args->stream, 0, args->line_buf))
2305 * Generate a bookmark, using "Frame N" as the title, as we're not
2306 * printing the summary line.
2308 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2309 if (!print_bookmark(args->print_args->stream, bookmark_name,
2312 } /* if (print_summary) */
2314 if (args->print_args->print_dissections != print_dissections_none) {
2315 if (args->print_args->print_summary) {
2316 /* Separate the summary line from the tree with a blank line. */
2317 if (!print_line(args->print_args->stream, 0, ""))
2321 /* Print the information in that tree. */
2322 if (!proto_tree_print(args->print_args->print_dissections,
2323 args->print_args->print_hex, &args->edt, NULL,
2324 args->print_args->stream))
2327 /* Print a blank line if we print anything after this (aka more than one packet). */
2328 args->print_separator = TRUE;
2330 /* Print a header line if we print any more packet summaries */
2331 if (args->print_args->print_col_headings)
2332 args->print_header_line = TRUE;
2335 if (args->print_args->print_hex) {
2336 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2337 if (!print_line(args->print_args->stream, 0, ""))
2340 /* Print the full packet data as hex. */
2341 if (!print_hex_data(args->print_args->stream, &args->edt))
2344 /* Print a blank line if we print anything after this (aka more than one packet). */
2345 args->print_separator = TRUE;
2347 /* Print a header line if we print any more packet summaries */
2348 if (args->print_args->print_col_headings)
2349 args->print_header_line = TRUE;
2350 } /* if (args->print_args->print_dissections != print_dissections_none) */
2352 epan_dissect_reset(&args->edt);
2354 /* do we want to have a formfeed between each packet from now on? */
2355 if (args->print_args->print_formfeed) {
2356 args->print_formfeed = TRUE;
2362 epan_dissect_reset(&args->edt);
2367 cf_print_packets(capture_file *cf, print_args_t *print_args,
2368 gboolean show_progress_bar)
2370 print_callback_args_t callback_args;
2373 int i, cp_off, column_len, line_len;
2374 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2378 gboolean proto_tree_needed;
2380 callback_args.print_args = print_args;
2381 callback_args.print_header_line = print_args->print_col_headings;
2382 callback_args.header_line_buf = NULL;
2383 callback_args.header_line_buf_len = 256;
2384 callback_args.print_formfeed = FALSE;
2385 callback_args.print_separator = FALSE;
2386 callback_args.line_buf = NULL;
2387 callback_args.line_buf_len = 256;
2388 callback_args.col_widths = NULL;
2389 callback_args.num_visible_cols = 0;
2390 callback_args.visible_cols = NULL;
2392 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2393 destroy_print_stream(print_args->stream);
2394 return CF_PRINT_WRITE_ERROR;
2397 if (print_args->print_summary) {
2398 /* We're printing packet summaries. Allocate the header line buffer
2399 and get the column widths. */
2400 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2402 /* Find the number of visible columns and the last visible column */
2403 for (i = 0; i < prefs.num_cols; i++) {
2405 clp = g_list_nth(prefs.col_list, i);
2406 if (clp == NULL) /* Sanity check, Invalid column requested */
2409 cfmt = (fmt_data *) clp->data;
2410 if (cfmt->visible) {
2412 last_visible_col = i;
2416 /* Find the widths for each of the columns - maximum of the
2417 width of the title and the width of the data - and construct
2418 a buffer with a line containing the column titles. */
2419 callback_args.num_visible_cols = num_visible_col;
2420 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2421 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2422 cp = &callback_args.header_line_buf[0];
2424 visible_col_count = 0;
2425 for (i = 0; i < cf->cinfo.num_cols; i++) {
2427 clp = g_list_nth(prefs.col_list, i);
2428 if (clp == NULL) /* Sanity check, Invalid column requested */
2431 cfmt = (fmt_data *) clp->data;
2432 if (cfmt->visible == FALSE)
2435 /* Save the order of visible columns */
2436 callback_args.visible_cols[visible_col_count] = i;
2438 /* Don't pad the last column. */
2439 if (i == last_visible_col)
2440 callback_args.col_widths[visible_col_count] = 0;
2442 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2443 data_width = get_column_char_width(get_column_format(i));
2444 if (data_width > callback_args.col_widths[visible_col_count])
2445 callback_args.col_widths[visible_col_count] = data_width;
2448 /* Find the length of the string for this column. */
2449 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2450 if (callback_args.col_widths[i] > column_len)
2451 column_len = callback_args.col_widths[visible_col_count];
2453 /* Make sure there's room in the line buffer for the column; if not,
2454 double its length. */
2455 line_len += column_len + 1; /* "+1" for space */
2456 if (line_len > callback_args.header_line_buf_len) {
2457 cp_off = (int) (cp - callback_args.header_line_buf);
2458 callback_args.header_line_buf_len = 2 * line_len;
2459 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2460 callback_args.header_line_buf_len + 1);
2461 cp = callback_args.header_line_buf + cp_off;
2464 /* Right-justify the packet number column. */
2465 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2466 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2468 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2470 if (i != cf->cinfo.num_cols - 1)
2473 visible_col_count++;
2477 /* Now start out the main line buffer with the same length as the
2478 header line buffer. */
2479 callback_args.line_buf_len = callback_args.header_line_buf_len;
2480 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2481 } /* if (print_summary) */
2483 /* Create the protocol tree, and make it visible, if we're printing
2484 the dissection or the hex data.
2485 XXX - do we need it if we're just printing the hex data? */
2487 callback_args.print_args->print_dissections != print_dissections_none ||
2488 callback_args.print_args->print_hex ||
2489 have_custom_cols(&cf->cinfo) || have_field_extractors();
2490 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2492 /* Iterate through the list of packets, printing the packets we were
2494 ret = process_specified_records(cf, &print_args->range, "Printing",
2495 "selected packets", TRUE, print_packet,
2496 &callback_args, show_progress_bar);
2497 epan_dissect_cleanup(&callback_args.edt);
2498 g_free(callback_args.header_line_buf);
2499 g_free(callback_args.line_buf);
2500 g_free(callback_args.col_widths);
2501 g_free(callback_args.visible_cols);
2506 /* Completed successfully. */
2510 /* Well, the user decided to abort the printing.
2512 XXX - note that what got generated before they did that
2513 will get printed if we're piping to a print program; we'd
2514 have to write to a file and then hand that to the print
2515 program to make it actually not print anything. */
2519 /* Error while printing.
2521 XXX - note that what got generated before they did that
2522 will get printed if we're piping to a print program; we'd
2523 have to write to a file and then hand that to the print
2524 program to make it actually not print anything. */
2525 destroy_print_stream(print_args->stream);
2526 return CF_PRINT_WRITE_ERROR;
2529 if (!print_finale(print_args->stream)) {
2530 destroy_print_stream(print_args->stream);
2531 return CF_PRINT_WRITE_ERROR;
2534 if (!destroy_print_stream(print_args->stream))
2535 return CF_PRINT_WRITE_ERROR;
2543 print_args_t *print_args;
2544 } write_packet_callback_args_t;
2547 write_pdml_packet(capture_file *cf, frame_data *fdata,
2548 struct wtap_pkthdr *phdr, const guint8 *pd,
2551 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2553 /* Create the protocol tree, but don't fill in the column information. */
2554 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2556 /* Write out the information in that tree. */
2557 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh);
2559 epan_dissect_reset(&args->edt);
2561 return !ferror(args->fh);
2565 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2567 write_packet_callback_args_t callback_args;
2571 fh = ws_fopen(print_args->file, "w");
2573 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2575 write_pdml_preamble(fh, cf->filename);
2578 return CF_PRINT_WRITE_ERROR;
2581 callback_args.fh = fh;
2582 callback_args.print_args = print_args;
2583 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2585 /* Iterate through the list of packets, printing the packets we were
2587 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2588 "selected packets", TRUE,
2589 write_pdml_packet, &callback_args, TRUE);
2591 epan_dissect_cleanup(&callback_args.edt);
2596 /* Completed successfully. */
2600 /* Well, the user decided to abort the printing. */
2604 /* Error while printing. */
2606 return CF_PRINT_WRITE_ERROR;
2609 write_pdml_finale(fh);
2612 return CF_PRINT_WRITE_ERROR;
2615 /* XXX - check for an error */
2622 write_psml_packet(capture_file *cf, frame_data *fdata,
2623 struct wtap_pkthdr *phdr, const guint8 *pd,
2626 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2628 /* Fill in the column information */
2629 col_custom_prime_edt(&args->edt, &cf->cinfo);
2630 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2631 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2633 /* Write out the column information. */
2634 write_psml_columns(&args->edt, args->fh);
2636 epan_dissect_reset(&args->edt);
2638 return !ferror(args->fh);
2642 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2644 write_packet_callback_args_t callback_args;
2648 gboolean proto_tree_needed;
2650 fh = ws_fopen(print_args->file, "w");
2652 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2654 write_psml_preamble(&cf->cinfo, fh);
2657 return CF_PRINT_WRITE_ERROR;
2660 callback_args.fh = fh;
2661 callback_args.print_args = print_args;
2663 /* Fill in the column information, only create the protocol tree
2664 if having custom columns or field extractors. */
2665 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2666 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2668 /* Iterate through the list of packets, printing the packets we were
2670 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2671 "selected packets", TRUE,
2672 write_psml_packet, &callback_args, TRUE);
2674 epan_dissect_cleanup(&callback_args.edt);
2679 /* Completed successfully. */
2683 /* Well, the user decided to abort the printing. */
2687 /* Error while printing. */
2689 return CF_PRINT_WRITE_ERROR;
2692 write_psml_finale(fh);
2695 return CF_PRINT_WRITE_ERROR;
2698 /* XXX - check for an error */
2705 write_csv_packet(capture_file *cf, frame_data *fdata,
2706 struct wtap_pkthdr *phdr, const guint8 *pd,
2709 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2711 /* Fill in the column information */
2712 col_custom_prime_edt(&args->edt, &cf->cinfo);
2713 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2714 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2716 /* Write out the column information. */
2717 write_csv_columns(&args->edt, args->fh);
2719 epan_dissect_reset(&args->edt);
2721 return !ferror(args->fh);
2725 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2727 write_packet_callback_args_t callback_args;
2728 gboolean proto_tree_needed;
2732 fh = ws_fopen(print_args->file, "w");
2734 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2736 write_csv_column_titles(&cf->cinfo, fh);
2739 return CF_PRINT_WRITE_ERROR;
2742 callback_args.fh = fh;
2743 callback_args.print_args = print_args;
2745 /* only create the protocol tree if having custom columns or field extractors. */
2746 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2747 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2749 /* Iterate through the list of packets, printing the packets we were
2751 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2752 "selected packets", TRUE,
2753 write_csv_packet, &callback_args, TRUE);
2755 epan_dissect_cleanup(&callback_args.edt);
2760 /* Completed successfully. */
2764 /* Well, the user decided to abort the printing. */
2768 /* Error while printing. */
2770 return CF_PRINT_WRITE_ERROR;
2773 /* XXX - check for an error */
2780 carrays_write_packet(capture_file *cf, frame_data *fdata,
2781 struct wtap_pkthdr *phdr,
2782 const guint8 *pd, void *argsp)
2784 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2786 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2787 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2788 epan_dissect_reset(&args->edt);
2790 return !ferror(args->fh);
2794 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2796 write_packet_callback_args_t callback_args;
2800 fh = ws_fopen(print_args->file, "w");
2803 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2807 return CF_PRINT_WRITE_ERROR;
2810 callback_args.fh = fh;
2811 callback_args.print_args = print_args;
2812 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2814 /* Iterate through the list of packets, printing the packets we were
2816 ret = process_specified_records(cf, &print_args->range,
2818 "selected packets", TRUE,
2819 carrays_write_packet, &callback_args, TRUE);
2821 epan_dissect_cleanup(&callback_args.edt);
2825 /* Completed successfully. */
2828 /* Well, the user decided to abort the printing. */
2831 /* Error while printing. */
2833 return CF_PRINT_WRITE_ERROR;
2841 write_json_packet(capture_file *cf, frame_data *fdata,
2842 struct wtap_pkthdr *phdr, const guint8 *pd,
2845 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2847 /* Create the protocol tree, but don't fill in the column information. */
2848 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2850 /* Write out the information in that tree. */
2851 write_json_proto_tree(NULL, args->print_args->print_dissections,
2852 args->print_args->print_hex, NULL, PF_NONE,
2853 &args->edt, args->fh);
2855 epan_dissect_reset(&args->edt);
2857 return !ferror(args->fh);
2861 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2863 write_packet_callback_args_t callback_args;
2867 fh = ws_fopen(print_args->file, "w");
2869 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2871 write_json_preamble(fh);
2874 return CF_PRINT_WRITE_ERROR;
2877 callback_args.fh = fh;
2878 callback_args.print_args = print_args;
2879 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2881 /* Iterate through the list of packets, printing the packets we were
2883 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2884 "selected packets", TRUE,
2885 write_json_packet, &callback_args, TRUE);
2887 epan_dissect_cleanup(&callback_args.edt);
2892 /* Completed successfully. */
2896 /* Well, the user decided to abort the printing. */
2900 /* Error while printing. */
2902 return CF_PRINT_WRITE_ERROR;
2905 write_json_finale(fh);
2908 return CF_PRINT_WRITE_ERROR;
2911 /* XXX - check for an error */
2918 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2919 search_direction dir)
2923 mdata.string = string;
2924 mdata.string_len = strlen(string);
2925 return find_packet(cf, match_protocol_tree, &mdata, dir);
2929 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2931 mdata->frame_matched = FALSE;
2932 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2933 mdata->string_len = strlen(mdata->string);
2935 /* Iterate through all the nodes looking for matching text */
2936 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2937 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2941 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2943 match_data *mdata = (match_data *)criterion;
2946 /* Load the frame's data. */
2947 if (!cf_read_record(cf, fdata)) {
2948 /* Attempt to get the packet failed. */
2952 /* Construct the protocol tree, including the displayed text */
2953 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2954 /* We don't need the column information */
2955 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2957 /* Iterate through all the nodes, seeing if they have text that matches. */
2959 mdata->frame_matched = FALSE;
2960 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2961 epan_dissect_cleanup(&edt);
2962 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2966 match_subtree_text(proto_node *node, gpointer data)
2968 match_data *mdata = (match_data *) data;
2969 const gchar *string = mdata->string;
2970 size_t string_len = mdata->string_len;
2971 capture_file *cf = mdata->cf;
2972 field_info *fi = PNODE_FINFO(node);
2973 gchar label_str[ITEM_LABEL_LENGTH];
2980 /* dissection with an invisible proto tree? */
2983 if (mdata->frame_matched) {
2984 /* We already had a match; don't bother doing any more work. */
2988 /* Don't match invisible entries. */
2989 if (PROTO_ITEM_IS_HIDDEN(node))
2992 /* was a free format label produced? */
2994 label_ptr = fi->rep->representation;
2996 /* no, make a generic label */
2997 label_ptr = label_str;
2998 proto_item_fill_label(fi, label_str);
3002 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3003 mdata->frame_matched = TRUE;
3008 /* Does that label match? */
3009 label_len = strlen(label_ptr);
3010 for (i = 0; i < label_len; i++) {
3011 c_char = label_ptr[i];
3013 c_char = g_ascii_toupper(c_char);
3014 if (c_char == string[c_match]) {
3016 if (c_match == string_len) {
3017 /* No need to look further; we have a match */
3018 mdata->frame_matched = TRUE;
3027 /* Recurse into the subtree, if it exists */
3028 if (node->first_child != NULL)
3029 proto_tree_children_foreach(node, match_subtree_text, mdata);
3033 cf_find_packet_summary_line(capture_file *cf, const char *string,
3034 search_direction dir)
3038 mdata.string = string;
3039 mdata.string_len = strlen(string);
3040 return find_packet(cf, match_summary_line, &mdata, dir);
3044 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3046 match_data *mdata = (match_data *)criterion;
3047 const gchar *string = mdata->string;
3048 size_t string_len = mdata->string_len;
3050 const char *info_column;
3051 size_t info_column_len;
3052 match_result result = MR_NOTMATCHED;
3058 /* Load the frame's data. */
3059 if (!cf_read_record(cf, fdata)) {
3060 /* Attempt to get the packet failed. */
3064 /* Don't bother constructing the protocol tree */
3065 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3066 /* Get the column information */
3067 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3070 /* Find the Info column */
3071 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3072 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3073 /* Found it. See if we match. */
3074 info_column = edt.pi.cinfo->columns[colx].col_data;
3075 info_column_len = strlen(info_column);
3077 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3078 result = MR_MATCHED;
3082 for (i = 0; i < info_column_len; i++) {
3083 c_char = info_column[i];
3085 c_char = g_ascii_toupper(c_char);
3086 if (c_char == string[c_match]) {
3088 if (c_match == string_len) {
3089 result = MR_MATCHED;
3099 epan_dissect_cleanup(&edt);
3106 } cbs_t; /* "Counted byte string" */
3110 * The current match_* routines only support ASCII case insensitivity and don't
3111 * convert UTF-8 inputs to UTF-16 for matching.
3113 * We could modify them to use the GLib Unicode routines or the International
3114 * Components for Unicode library but it's not apparent that we could do so
3115 * without consuming a lot more CPU and memory or that searching would be
3116 * significantly better.
3120 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3121 search_direction dir)
3126 info.data_len = string_size;
3128 /* Regex, String or hex search? */
3130 /* Regular Expression search */
3131 return find_packet(cf, match_regex, NULL, dir);
3132 } else if (cf->string) {
3133 /* String search - what type of string? */
3134 switch (cf->scs_type) {
3136 case SCS_NARROW_AND_WIDE:
3137 return find_packet(cf, match_narrow_and_wide, &info, dir);
3140 return find_packet(cf, match_narrow, &info, dir);
3143 return find_packet(cf, match_wide, &info, dir);
3146 g_assert_not_reached();
3150 return find_packet(cf, match_binary, &info, dir);
3154 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3156 cbs_t *info = (cbs_t *)criterion;
3157 const guint8 *ascii_text = info->data;
3158 size_t textlen = info->data_len;
3159 match_result result;
3166 /* Load the frame's data. */
3167 if (!cf_read_record(cf, fdata)) {
3168 /* Attempt to get the packet failed. */
3172 result = MR_NOTMATCHED;
3173 buf_len = fdata->cap_len;
3174 pd = ws_buffer_start_ptr(&cf->buf);
3176 while (i < buf_len) {
3179 c_char = g_ascii_toupper(c_char);
3180 if (c_char != '\0') {
3181 if (c_char == ascii_text[c_match]) {
3183 if (c_match == textlen) {
3184 result = MR_MATCHED;
3185 cf->search_pos = i; /* Save the position of the last character
3186 for highlighting the field. */
3187 cf->search_len = (guint32)textlen;
3192 g_assert(i>=c_match);
3193 i -= (guint32)c_match;
3203 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3206 cbs_t *info = (cbs_t *)criterion;
3207 const guint8 *ascii_text = info->data;
3208 size_t textlen = info->data_len;
3209 match_result result;
3215 /* Load the frame's data. */
3216 if (!cf_read_record(cf, fdata)) {
3217 /* Attempt to get the packet failed. */
3221 result = MR_NOTMATCHED;
3222 buf_len = fdata->cap_len;
3223 pd = ws_buffer_start_ptr(&cf->buf);
3225 while (i < buf_len) {
3228 c_char = g_ascii_toupper(c_char);
3229 if (c_char == ascii_text[c_match]) {
3231 if (c_match == textlen) {
3232 result = MR_MATCHED;
3233 cf->search_pos = i; /* Save the position of the last character
3234 for highlighting the field. */
3235 cf->search_len = (guint32)textlen;
3240 g_assert(i>=c_match);
3241 i -= (guint32)c_match;
3251 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3253 cbs_t *info = (cbs_t *)criterion;
3254 const guint8 *ascii_text = info->data;
3255 size_t textlen = info->data_len;
3256 match_result result;
3263 /* Load the frame's data. */
3264 if (!cf_read_record(cf, fdata)) {
3265 /* Attempt to get the packet failed. */
3269 result = MR_NOTMATCHED;
3270 buf_len = fdata->cap_len;
3271 pd = ws_buffer_start_ptr(&cf->buf);
3273 while (i < buf_len) {
3276 c_char = g_ascii_toupper(c_char);
3277 if (c_char == ascii_text[c_match]) {
3279 if (c_match == textlen) {
3280 result = MR_MATCHED;
3281 cf->search_pos = i; /* Save the position of the last character
3282 for highlighting the field. */
3283 cf->search_len = (guint32)textlen;
3289 g_assert(i>=(c_match*2));
3290 i -= (guint32)c_match*2;
3299 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3301 cbs_t *info = (cbs_t *)criterion;
3302 const guint8 *binary_data = info->data;
3303 size_t datalen = info->data_len;
3304 match_result result;
3310 /* Load the frame's data. */
3311 if (!cf_read_record(cf, fdata)) {
3312 /* Attempt to get the packet failed. */
3316 result = MR_NOTMATCHED;
3317 buf_len = fdata->cap_len;
3318 pd = ws_buffer_start_ptr(&cf->buf);
3320 while (i < buf_len) {
3321 if (pd[i] == binary_data[c_match]) {
3323 if (c_match == datalen) {
3324 result = MR_MATCHED;
3325 cf->search_pos = i; /* Save the position of the last character
3326 for highlighting the field. */
3327 cf->search_len = (guint32)datalen;
3332 g_assert(i>=c_match);
3333 i -= (guint32)c_match;
3342 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3344 match_result result = MR_NOTMATCHED;
3345 GMatchInfo *match_info = NULL;
3347 /* Load the frame's data. */
3348 if (!cf_read_record(cf, fdata)) {
3349 /* Attempt to get the packet failed. */
3353 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3354 0, (GRegexMatchFlags) 0, &match_info, NULL))
3356 gint start_pos = 0, end_pos = 0;
3357 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3358 cf->search_pos = end_pos - 1;
3359 cf->search_len = end_pos - start_pos;
3360 result = MR_MATCHED;
3366 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3367 search_direction dir)
3369 return find_packet(cf, match_dfilter, sfcode, dir);
3373 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3374 search_direction dir)
3379 if (!dfilter_compile(filter, &sfcode, NULL)) {
3381 * XXX - this shouldn't happen, as the filter string is machine
3386 if (sfcode == NULL) {
3388 * XXX - this shouldn't happen, as the filter string is machine
3393 result = find_packet(cf, match_dfilter, sfcode, dir);
3394 dfilter_free(sfcode);
3399 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3401 dfilter_t *sfcode = (dfilter_t *)criterion;
3403 match_result result;
3405 /* Load the frame's data. */
3406 if (!cf_read_record(cf, fdata)) {
3407 /* Attempt to get the packet failed. */
3411 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3412 epan_dissect_prime_with_dfilter(&edt, sfcode);
3413 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3414 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3415 epan_dissect_cleanup(&edt);
3420 cf_find_packet_marked(capture_file *cf, search_direction dir)
3422 return find_packet(cf, match_marked, NULL, dir);
3426 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3428 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3432 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3434 return find_packet(cf, match_time_reference, NULL, dir);
3438 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3440 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3444 find_packet(capture_file *cf,
3445 match_result (*match_function)(capture_file *, frame_data *, void *),
3446 void *criterion, search_direction dir)
3448 frame_data *start_fd;
3451 frame_data *new_fd = NULL;
3452 progdlg_t *progbar = NULL;
3453 GTimer *prog_timer = g_timer_new();
3457 GTimeVal start_time;
3458 gchar status_str[100];
3460 match_result result;
3462 start_fd = cf->current_frame;
3463 if (start_fd != NULL) {
3464 /* Iterate through the list of packets, starting at the packet we've
3465 picked, calling a routine to run the filter on the packet, see if
3466 it matches, and stop if so. */
3468 framenum = start_fd->num;
3470 g_timer_start(prog_timer);
3471 /* Progress so far. */
3474 cf->stop_flag = FALSE;
3475 g_get_current_time(&start_time);
3477 title = cf->sfilter?cf->sfilter:"";
3479 /* Create the progress bar if necessary.
3480 We check on every iteration of the loop, so that it takes no
3481 longer than the standard time to create it (otherwise, for a
3482 large file, we might take considerably longer than that standard
3483 time in order to get to the next progress bar step). */
3484 if (progbar == NULL)
3485 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3486 FALSE, &cf->stop_flag, &start_time, progbar_val);
3489 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3490 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3491 * likely trigger UI paint events, which might take a while depending on
3492 * the platform and display. Reset our timer *after* painting.
3494 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3495 /* let's not divide by zero. I should never be started
3496 * with count == 0, so let's assert that
3498 g_assert(cf->count > 0);
3500 progbar_val = (gfloat) count / cf->count;
3502 g_snprintf(status_str, sizeof(status_str),
3503 "%4u of %u packets", count, cf->count);
3504 update_progress_dlg(progbar, progbar_val, status_str);
3506 g_timer_start(prog_timer);
3509 if (cf->stop_flag) {
3510 /* Well, the user decided to abort the search. Go back to the
3511 frame where we started. */
3516 /* Go past the current frame. */
3517 if (dir == SD_BACKWARD) {
3518 /* Go on to the previous frame. */
3519 if (framenum == 1) {
3521 * XXX - other apps have a bit more of a detailed message
3522 * for this, and instead of offering "OK" and "Cancel",
3523 * they offer things such as "Continue" and "Cancel";
3524 * we need an API for popping up alert boxes with
3525 * {Verb} and "Cancel".
3528 if (prefs.gui_find_wrap)
3530 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3531 framenum = cf->count; /* wrap around */
3535 statusbar_push_temporary_msg("Search reached the beginning.");
3536 framenum = start_fd->num; /* stay on previous packet */
3541 /* Go on to the next frame. */
3542 if (framenum == cf->count) {
3543 if (prefs.gui_find_wrap)
3545 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3546 framenum = 1; /* wrap around */
3550 statusbar_push_temporary_msg("Search reached the end.");
3551 framenum = start_fd->num; /* stay on previous packet */
3556 fdata = frame_data_sequence_find(cf->frames, framenum);
3560 /* Is this packet in the display? */
3561 if (fdata->flags.passed_dfilter) {
3562 /* Yes. Does it match the search criterion? */
3563 result = (*match_function)(cf, fdata, criterion);
3564 if (result == MR_ERROR) {
3565 /* Error; our caller has reported the error. Go back to the frame
3566 where we started. */
3569 } else if (result == MR_MATCHED) {
3570 /* Yes. Go to the new frame. */
3576 if (fdata == start_fd) {
3577 /* We're back to the frame we were on originally, and that frame
3578 doesn't match the search filter. The search failed. */
3583 /* We're done scanning the packets; destroy the progress bar if it
3585 if (progbar != NULL)
3586 destroy_progress_dlg(progbar);
3587 g_timer_destroy(prog_timer);
3590 if (new_fd != NULL) {
3591 /* Find and select */
3592 cf->search_in_progress = TRUE;
3593 found = packet_list_select_row_from_data(new_fd);
3594 cf->search_in_progress = FALSE;
3595 cf->search_pos = 0; /* Reset the position */
3596 cf->search_len = 0; /* Reset length */
3598 /* We didn't find a row corresponding to this frame.
3599 This means that the frame isn't being displayed currently,
3600 so we can't select it. */
3601 simple_message_box(ESD_TYPE_INFO, NULL,
3602 "The capture file is probably not fully dissected.",
3603 "End of capture exceeded.");
3606 return TRUE; /* success */
3608 return FALSE; /* failure */
3612 cf_goto_frame(capture_file *cf, guint fnumber)
3616 if (cf == NULL || cf->frames == NULL) {
3617 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3618 statusbar_push_temporary_msg("There is no file loaded");
3619 return FALSE; /* we failed to go to that packet */
3622 fdata = frame_data_sequence_find(cf->frames, fnumber);
3624 if (fdata == NULL) {
3625 /* we didn't find a packet with that packet number */
3626 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3627 return FALSE; /* we failed to go to that packet */
3629 if (!fdata->flags.passed_dfilter) {
3630 /* that packet currently isn't displayed */
3631 /* XXX - add it to the set of displayed packets? */
3632 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3633 return FALSE; /* we failed to go to that packet */
3636 if (!packet_list_select_row_from_data(fdata)) {
3637 /* We didn't find a row corresponding to this frame.
3638 This means that the frame isn't being displayed currently,
3639 so we can't select it. */
3640 simple_message_box(ESD_TYPE_INFO, NULL,
3641 "The capture file is probably not fully dissected.",
3642 "End of capture exceeded.");
3645 return TRUE; /* we got to that packet */
3649 * Go to frame specified by currently selected protocol tree item.
3652 cf_goto_framenum(capture_file *cf)
3654 header_field_info *hfinfo;
3657 if (cf->finfo_selected) {
3658 hfinfo = cf->finfo_selected->hfinfo;
3660 if (hfinfo->type == FT_FRAMENUM) {
3661 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3663 return cf_goto_frame(cf, framenum);
3670 /* Select the packet on a given row. */
3672 cf_select_packet(capture_file *cf, int row)
3674 epan_dissect_t *old_edt;
3677 /* Get the frame data struct pointer for this frame */
3678 fdata = packet_list_get_row_data(row);
3680 if (fdata == NULL) {
3684 /* Get the data in that frame. */
3685 if (!cf_read_record (cf, fdata)) {
3689 /* Record that this frame is the current frame. */
3690 cf->current_frame = fdata;
3691 cf->current_row = row;
3694 /* Create the logical protocol tree. */
3695 /* We don't need the columns here. */
3696 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3698 tap_build_interesting(cf->edt);
3699 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3700 cf->current_frame, NULL);
3702 dfilter_macro_build_ftv_cache(cf->edt->tree);
3704 cf_callback_invoke(cf_cb_packet_selected, cf);
3706 if (old_edt != NULL)
3707 epan_dissect_free(old_edt);
3711 /* Unselect the selected packet, if any. */
3713 cf_unselect_packet(capture_file *cf)
3715 epan_dissect_t *old_edt = cf->edt;
3719 /* No packet is selected. */
3720 cf->current_frame = NULL;
3721 cf->current_row = 0;
3723 cf_callback_invoke(cf_cb_packet_unselected, cf);
3725 /* No protocol tree means no selected field. */
3726 cf_unselect_field(cf);
3728 /* Destroy the epan_dissect_t for the unselected packet. */
3729 if (old_edt != NULL)
3730 epan_dissect_free(old_edt);
3733 /* Unset the selected protocol tree field, if any. */
3735 cf_unselect_field(capture_file *cf)
3737 cf->finfo_selected = NULL;
3739 cf_callback_invoke(cf_cb_field_unselected, cf);
3743 * Mark a particular frame.
3746 cf_mark_frame(capture_file *cf, frame_data *frame)
3748 if (! frame->flags.marked) {
3749 frame->flags.marked = TRUE;
3750 if (cf->count > cf->marked_count)
3756 * Unmark a particular frame.
3759 cf_unmark_frame(capture_file *cf, frame_data *frame)
3761 if (frame->flags.marked) {
3762 frame->flags.marked = FALSE;
3763 if (cf->marked_count > 0)
3769 * Ignore a particular frame.
3772 cf_ignore_frame(capture_file *cf, frame_data *frame)
3774 if (! frame->flags.ignored) {
3775 frame->flags.ignored = TRUE;
3776 if (cf->count > cf->ignored_count)
3777 cf->ignored_count++;
3782 * Un-ignore a particular frame.
3785 cf_unignore_frame(capture_file *cf, frame_data *frame)
3787 if (frame->flags.ignored) {
3788 frame->flags.ignored = FALSE;
3789 if (cf->ignored_count > 0)
3790 cf->ignored_count--;
3795 * Read the comment in SHB block
3799 cf_read_shb_comment(capture_file *cf)
3801 wtap_block_t shb_inf;
3805 /* XXX - support multiple SHBs */
3806 shb_inf = wtap_file_get_shb(cf->wth);
3808 /* Get the first comment from the SHB. */
3809 /* XXX - support multiple comments */
3810 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3816 cf_update_capture_comment(capture_file *cf, gchar *comment)
3818 wtap_block_t shb_inf;
3822 /* XXX - support multiple SHBs */
3823 shb_inf = wtap_file_get_shb(cf->wth);
3825 /* Get the first comment from the SHB. */
3826 /* XXX - support multiple comments */
3827 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3828 /* There's no comment - add one. */
3829 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3831 /* See if the comment has changed or not */
3832 if (strcmp(shb_comment, comment) == 0) {
3837 /* The comment has changed, let's update it */
3838 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3840 /* Mark the file as having unsaved changes */
3841 cf->unsaved_changes = TRUE;
3845 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3847 if (cf->frames_user_comments)
3848 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3855 cf_get_comment(capture_file *cf, const frame_data *fd)
3859 /* fetch user comment */
3860 if (fd->flags.has_user_comment)
3861 return g_strdup(cf_get_user_packet_comment(cf, fd));
3863 /* fetch phdr comment */
3864 if (fd->flags.has_phdr_comment) {
3865 struct wtap_pkthdr phdr; /* Packet header */
3866 Buffer buf; /* Packet data */
3868 wtap_phdr_init(&phdr);
3869 ws_buffer_init(&buf, 1500);
3871 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3872 { /* XXX, what we can do here? */ }
3874 comment = phdr.opt_comment;
3875 wtap_phdr_cleanup(&phdr);
3876 ws_buffer_free(&buf);
3883 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3885 const frame_data *fdata1 = (const frame_data *) a;
3886 const frame_data *fdata2 = (const frame_data *) b;
3888 return (fdata1->num < fdata2->num) ? -1 :
3889 (fdata1->num > fdata2->num) ? 1 :
3894 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3896 char *pkt_comment = cf_get_comment(cf, fd);
3898 /* Check if the comment has changed */
3899 if (!g_strcmp0(pkt_comment, new_comment)) {
3900 g_free(pkt_comment);
3903 g_free(pkt_comment);
3906 cf->packet_comment_count--;
3909 cf->packet_comment_count++;
3911 fd->flags.has_user_comment = TRUE;
3913 if (!cf->frames_user_comments)
3914 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3916 /* insert new packet comment */
3917 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3919 expert_update_comment_count(cf->packet_comment_count);
3921 /* OK, we have unsaved changes. */
3922 cf->unsaved_changes = TRUE;
3927 * What types of comments does this capture file have?
3930 cf_comment_types(capture_file *cf)
3932 guint32 comment_types = 0;
3934 if (cf_read_shb_comment(cf) != NULL)
3935 comment_types |= WTAP_COMMENT_PER_SECTION;
3936 if (cf->packet_comment_count != 0)
3937 comment_types |= WTAP_COMMENT_PER_PACKET;
3938 return comment_types;
3942 * Add a resolved address to this file's list of resolved addresses.
3945 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3948 * XXX - support multiple resolved address lists, and add to the one
3949 * attached to this file?
3951 if (!add_ip_name_from_string(addr, name))
3954 /* OK, we have unsaved changes. */
3955 cf->unsaved_changes = TRUE;
3959 #ifdef WANT_PACKET_EDITOR
3961 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3972 modified_frame_data_free(gpointer data)
3974 modified_frame_data *mfd = (modified_frame_data *)data;
3981 * Give a frame new, edited data.
3984 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3985 struct wtap_pkthdr *phdr, guint8 *pd)
3987 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3990 mfd->pd = (char *)pd;
3992 if (cf->edited_frames == NULL)
3993 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3994 modified_frame_data_free);
3995 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3998 /* Mark the file as having unsaved changes */
3999 cf->unsaved_changes = TRUE;
4007 } save_callback_args_t;
4010 * Save a capture to a file, in a particular format, saving either
4011 * all packets, all currently-displayed packets, or all marked packets.
4013 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4014 * up a message box for the failure.
4017 save_record(capture_file *cf, frame_data *fdata,
4018 struct wtap_pkthdr *phdr, const guint8 *pd,
4021 save_callback_args_t *args = (save_callback_args_t *)argsp;
4022 struct wtap_pkthdr hdr;
4025 const char *pkt_comment;
4027 if (fdata->flags.has_user_comment)
4028 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4030 pkt_comment = phdr->opt_comment;
4032 /* init the wtap header for saving */
4033 /* TODO: reuse phdr */
4034 /* XXX - these are the only flags that correspond to data that we have
4035 in the frame_data structure and that matter on a per-packet basis.
4037 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4038 and "on the wire" lengths, or it doesn't.
4040 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4043 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4044 from the packet flags. */
4045 hdr.rec_type = phdr->rec_type;
4046 hdr.presence_flags = 0;
4047 if (fdata->flags.has_ts)
4048 hdr.presence_flags |= WTAP_HAS_TS;
4049 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4050 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4051 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4052 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4054 hdr.caplen = phdr->caplen;
4055 hdr.len = phdr->len;
4056 hdr.pkt_encap = phdr->pkt_encap;
4058 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4060 hdr.pack_flags = phdr->pack_flags;
4061 hdr.opt_comment = g_strdup(pkt_comment);
4064 hdr.pseudo_header = phdr->pseudo_header;
4067 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4069 /* and save the packet */
4070 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
4071 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4076 g_free(hdr.opt_comment);
4081 * Can this capture file be written out in any format using Wiretap
4082 * rather than by copying the raw data?
4085 cf_can_write_with_wiretap(capture_file *cf)
4087 /* We don't care whether we support the comments in this file or not;
4088 if we can't, we'll offer the user the option of discarding the
4090 return wtap_dump_can_write(cf->linktypes, 0);
4094 * Should we let the user do a save?
4098 * the file has unsaved changes, and we can save it in some
4099 * format through Wiretap
4103 * the file is a temporary file and has no unsaved changes (so
4104 * that "saving" it just means copying it).
4106 * XXX - we shouldn't allow files to be edited if they can't be saved,
4107 * so cf->unsaved_changes should be true only if the file can be saved.
4109 * We don't care whether we support the comments in this file or not;
4110 * if we can't, we'll offer the user the option of discarding the
4114 cf_can_save(capture_file *cf)
4116 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4117 /* Saved changes, and we can write it out with Wiretap. */
4121 if (cf->is_tempfile && !cf->unsaved_changes) {
4123 * Temporary file with no unsaved changes, so we can just do a
4129 /* Nothing to save. */
4134 * Should we let the user do a "save as"?
4138 * we can save it in some format through Wiretap
4142 * the file is a temporary file and has no unsaved changes (so
4143 * that "saving" it just means copying it).
4145 * XXX - we shouldn't allow files to be edited if they can't be saved,
4146 * so cf->unsaved_changes should be true only if the file can be saved.
4148 * We don't care whether we support the comments in this file or not;
4149 * if we can't, we'll offer the user the option of discarding the
4153 cf_can_save_as(capture_file *cf)
4155 if (wtap_dump_can_write(cf->linktypes, 0)) {
4156 /* We can write it out with Wiretap. */
4160 if (cf->is_tempfile && !cf->unsaved_changes) {
4162 * Temporary file with no unsaved changes, so we can just do a
4168 /* Nothing to save. */
4173 * Does this file have unsaved data?
4176 cf_has_unsaved_data(capture_file *cf)
4179 * If this is a temporary file, or a file with unsaved changes, it
4182 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4186 * Quick scan to find packet offsets.
4188 static cf_read_status_t
4189 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4191 const struct wtap_pkthdr *phdr;
4196 progdlg_t *progbar = NULL;
4197 GTimer *prog_timer = g_timer_new();
4200 GTimeVal start_time;
4201 gchar status_str[100];
4206 /* Close the old handle. */
4207 wtap_close(cf->wth);
4209 /* Open the new file. */
4210 /* XXX: this will go through all open_routines for a matching one. But right
4211 now rescan_file() is only used when a file is being saved to a different
4212 format than the original, and the user is not given a choice of which
4213 reader to use (only which format to save it in), so doing this makes
4215 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4216 if (cf->wth == NULL) {
4217 cfile_open_failure_alert_box(fname, err, err_info);
4218 return CF_READ_ERROR;
4221 /* We're scanning a file whose contents should be the same as what
4222 we had before, so we don't discard dissection state etc.. */
4225 /* Set the file name because we need it to set the follow stream filter.
4226 XXX - is that still true? We need it for other reasons, though,
4228 cf->filename = g_strdup(fname);
4230 /* Indicate whether it's a permanent or temporary file. */
4231 cf->is_tempfile = is_tempfile;
4233 /* No user changes yet. */
4234 cf->unsaved_changes = FALSE;
4236 cf->cd_t = wtap_file_type_subtype(cf->wth);
4237 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4239 cf->snap = wtap_snapshot_length(cf->wth);
4240 if (cf->snap == 0) {
4241 /* Snapshot length not known. */
4242 cf->has_snap = FALSE;
4243 cf->snap = WTAP_MAX_PACKET_SIZE;
4245 cf->has_snap = TRUE;
4247 name_ptr = g_filename_display_basename(cf->filename);
4249 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4251 /* Record whether the file is compressed.
4252 XXX - do we know this at open time? */
4253 cf->iscompressed = wtap_iscompressed(cf->wth);
4255 /* Find the size of the file. */
4256 size = wtap_file_size(cf->wth, NULL);
4258 g_timer_start(prog_timer);
4260 cf->stop_flag = FALSE;
4261 g_get_current_time(&start_time);
4264 phdr = wtap_phdr(cf->wth);
4265 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
4267 fdata = frame_data_sequence_find(cf->frames, framenum);
4268 fdata->file_off = data_offset;
4271 cf->f_datalen = wtap_read_so_far(cf->wth);
4273 /* Create the progress bar if necessary. */
4274 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4275 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4276 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4277 TRUE, &cf->stop_flag, &start_time, progbar_val);
4281 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4282 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4283 * likely trigger UI paint events, which might take a while depending on
4284 * the platform and display. Reset our timer *after* painting.
4286 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4287 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4288 /* update the packet bar content on the first run or frequently on very large files */
4289 update_progress_dlg(progbar, progbar_val, status_str);
4290 packets_bar_update();
4291 g_timer_start(prog_timer);
4295 if (cf->stop_flag) {
4296 /* Well, the user decided to abort the rescan. Sadly, as this
4297 isn't a reread, recovering is difficult, so we'll just
4298 close the current capture. */
4302 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4303 it's not already there.
4304 XXX - yes, this is O(N), so if every packet had a different
4305 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4306 there are probably going to be a small number of encapsulation types
4308 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4311 /* Free the display name */
4314 /* We're done reading the file; destroy the progress bar if it was created. */
4315 if (progbar != NULL)
4316 destroy_progress_dlg(progbar);
4317 g_timer_destroy(prog_timer);
4319 /* We're done reading sequentially through the file. */
4320 cf->state = FILE_READ_DONE;
4322 /* Close the sequential I/O side, to free up memory it requires. */
4323 wtap_sequential_close(cf->wth);
4325 /* compute the time it took to load the file */
4326 compute_elapsed(cf, &start_time);
4328 /* Set the file encapsulation type now; we don't know what it is until
4329 we've looked at all the packets, as we don't know until then whether
4330 there's more than one type (and thus whether it's
4331 WTAP_ENCAP_PER_PACKET). */
4332 cf->lnk_t = wtap_file_encap(cf->wth);
4334 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4336 if (cf->stop_flag) {
4337 /* Our caller will give up at this point. */
4338 return CF_READ_ABORTED;
4342 /* Put up a message box noting that the read failed somewhere along
4343 the line. Don't throw out the stuff we managed to read, though,
4345 cfile_read_failure_alert_box(NULL, err, err_info);
4346 return CF_READ_ERROR;
4352 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4353 gboolean compressed, gboolean discard_comments,
4354 gboolean dont_reopen)
4357 gchar *fname_new = NULL;
4360 addrinfo_lists_t *addr_lists;
4364 gchar *display_basename;
4371 save_callback_args_t callback_args;
4373 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4375 addr_lists = get_addrinfo_list();
4377 if (save_format == cf->cd_t && compressed == cf->iscompressed
4378 && !discard_comments && !cf->unsaved_changes
4379 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4380 /* We're saving in the format it's already in, and we're
4381 not discarding comments, and there are no changes we have
4382 in memory that aren't saved to the file, and we have no name
4383 resolution blocks to write, so we can just move or copy the raw data. */
4385 if (cf->is_tempfile) {
4386 /* The file being saved is a temporary file from a live
4387 capture, so it doesn't need to stay around under that name;
4388 first, try renaming the capture buffer file to the new name.
4389 This acts as a "safe save", in that, if the file already
4390 exists, the existing file will be removed only if the rename
4393 Sadly, on Windows, as we have the current capture file
4394 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4395 (to cause the rename to remove an existing target), as
4396 done by ws_stdio_rename() (ws_rename() is #defined to
4397 be ws_stdio_rename() on Windows) will fail.
4399 According to the MSDN documentation for CreateFile(), if,
4400 when we open a capture file, we were to directly do a CreateFile(),
4401 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4402 convert it to a file descriptor with _open_osfhandle(),
4403 that would allow the file to be renamed out from under us.
4405 However, that doesn't work in practice. Perhaps the problem
4406 is that the process doing the rename is the process that
4407 has the file open. */
4409 if (ws_rename(cf->filename, fname) == 0) {
4410 /* That succeeded - there's no need to copy the source file. */
4411 how_to_save = SAVE_WITH_MOVE;
4413 if (errno == EXDEV) {
4414 /* They're on different file systems, so we have to copy the
4416 how_to_save = SAVE_WITH_COPY;
4418 /* The rename failed, but not because they're on different
4419 file systems - put up an error message. (Or should we
4420 just punt and try to copy? The only reason why I'd
4421 expect the rename to fail and the copy to succeed would
4422 be if we didn't have permission to remove the file from
4423 the temporary directory, and that might be fixable - but
4424 is it worth requiring the user to go off and fix it?) */
4425 cf_rename_failure_alert_box(fname, errno);
4430 how_to_save = SAVE_WITH_COPY;
4433 /* It's a permanent file, so we should copy it, and not remove the
4435 how_to_save = SAVE_WITH_COPY;
4438 if (how_to_save == SAVE_WITH_COPY) {
4439 /* Copy the file, if we haven't moved it. If we're overwriting
4440 an existing file, we do it with a "safe save", by writing
4441 to a new file and, if the write succeeds, renaming the
4442 new file on top of the old file. */
4443 if (file_exists(fname)) {
4444 fname_new = g_strdup_printf("%s~", fname);
4445 if (!copy_file_binary_mode(cf->filename, fname_new))
4448 if (!copy_file_binary_mode(cf->filename, fname))
4453 /* Either we're saving in a different format or we're saving changes,
4454 such as added, modified, or removed comments, that haven't yet
4455 been written to the underlying file; we can't do that by copying
4456 or moving the capture file, we have to do it by writing the packets
4459 GArray *shb_hdrs = NULL;
4460 wtapng_iface_descriptions_t *idb_inf = NULL;
4461 GArray *nrb_hdrs = NULL;
4464 /* XXX: what free's this shb_hdr? */
4465 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4466 idb_inf = wtap_file_get_idb_info(cf->wth);
4467 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4469 /* Determine what file encapsulation type we should use. */
4470 encap = wtap_dump_file_encap_type(cf->linktypes);
4472 if (file_exists(fname)) {
4473 /* We're overwriting an existing file; write out to a new file,
4474 and, if that succeeds, rename the new file on top of the
4475 old file. That makes this a "safe save", so that we don't
4476 lose the old file if we have a problem writing out the new
4477 file. (If the existing file is the current capture file,
4478 we *HAVE* to do that, otherwise we're overwriting the file
4479 from which we're reading the packets that we're writing!) */
4480 fname_new = g_strdup_printf("%s~", fname);
4481 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4482 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4484 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4485 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4491 cfile_dump_open_failure_alert_box(fname, err, save_format);
4495 /* Add address resolution */
4496 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4498 /* Iterate through the list of packets, processing all the packets. */
4499 callback_args.pdh = pdh;
4500 callback_args.fname = fname;
4501 callback_args.file_type = save_format;
4502 switch (process_specified_records(cf, NULL, "Saving", "packets",
4503 TRUE, save_record, &callback_args, TRUE)) {
4506 /* Completed successfully. */
4510 /* The user decided to abort the saving.
4511 If we're writing to a temporary file, remove it.
4512 XXX - should we do so even if we're not writing to a
4514 wtap_dump_close(pdh, &err);
4515 if (fname_new != NULL)
4516 ws_unlink(fname_new);
4517 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4518 return CF_WRITE_ABORTED;
4521 /* Error while saving.
4522 If we're writing to a temporary file, remove it. */
4523 if (fname_new != NULL)
4524 ws_unlink(fname_new);
4525 wtap_dump_close(pdh, &err);
4529 if (!wtap_dump_close(pdh, &err)) {
4530 cfile_close_failure_alert_box(fname, err);
4534 how_to_save = SAVE_WITH_WTAP;
4537 if (fname_new != NULL) {
4538 /* We wrote out to fname_new, and should rename it on top of
4539 fname. fname_new is now closed, so that should be possible even
4540 on Windows. However, on Windows, we first need to close whatever
4541 file descriptors we have open for fname. */
4543 wtap_fdclose(cf->wth);
4545 /* Now do the rename. */
4546 if (ws_rename(fname_new, fname) == -1) {
4547 /* Well, the rename failed. */
4548 cf_rename_failure_alert_box(fname, errno);
4550 /* Attempt to reopen the random file descriptor using the
4551 current file's filename. (At this point, the sequential
4552 file descriptor is closed.) */
4553 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4554 /* Oh, well, we're screwed. */
4555 display_basename = g_filename_display_basename(cf->filename);
4556 simple_error_message_box(
4557 file_open_error_message(err, FALSE), display_basename);
4558 g_free(display_basename);
4565 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4566 cf->unsaved_changes = FALSE;
4569 switch (how_to_save) {
4571 case SAVE_WITH_MOVE:
4572 /* We just moved the file, so the wtap structure refers to the
4573 new file, and all the information other than the filename
4574 and the "is temporary" status applies to the new file; just
4576 g_free(cf->filename);
4577 cf->filename = g_strdup(fname);
4578 cf->is_tempfile = FALSE;
4579 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4582 case SAVE_WITH_COPY:
4583 /* We just copied the file, s all the information other than
4584 the wtap structure, the filename, and the "is temporary"
4585 status applies to the new file; just update that. */
4586 wtap_close(cf->wth);
4587 /* Although we're just "copying" and then opening the copy, it will
4588 try all open_routine readers to open the copy, so we need to
4589 reset the cfile's open_type. */
4590 cf->open_type = WTAP_TYPE_AUTO;
4591 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4592 if (cf->wth == NULL) {
4593 cfile_open_failure_alert_box(fname, err, err_info);
4596 g_free(cf->filename);
4597 cf->filename = g_strdup(fname);
4598 cf->is_tempfile = FALSE;
4600 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4603 case SAVE_WITH_WTAP:
4604 /* Open and read the file we saved to.
4606 XXX - this is somewhat of a waste; we already have the
4607 packets, all this gets us is updated file type information
4608 (which we could just stuff into "cf"), and having the new
4609 file be the one we have opened and from which we're reading
4610 the data, and it means we have to spend time opening and
4611 reading the file, which could be a significant amount of
4612 time if the file is large.
4614 If the capture-file-writing code were to return the
4615 seek offset of each packet it writes, we could save that
4616 in the frame_data structure for the frame, and just open
4617 the file without reading it again...
4619 ...as long as, for gzipped files, the process of writing
4620 out the file *also* generates the information needed to
4621 support fast random access to the compressed file. */
4622 /* rescan_file will cause us to try all open_routines, so
4623 reset cfile's open_type */
4624 cf->open_type = WTAP_TYPE_AUTO;
4625 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4626 /* The rescan failed; just close the file. Either
4627 a dialog was popped up for the failure, so the
4628 user knows what happened, or they stopped the
4629 rescan, in which case they know what happened. */
4635 /* If we were told to discard the comments, do so. */
4636 if (discard_comments) {
4637 /* Remove SHB comment, if any. */
4638 wtap_write_shb_comment(cf->wth, NULL);
4640 /* remove all user comments */
4641 for (framenum = 1; framenum <= cf->count; framenum++) {
4642 fdata = frame_data_sequence_find(cf->frames, framenum);
4644 fdata->flags.has_phdr_comment = FALSE;
4645 fdata->flags.has_user_comment = FALSE;
4648 if (cf->frames_user_comments) {
4649 g_tree_destroy(cf->frames_user_comments);
4650 cf->frames_user_comments = NULL;
4653 cf->packet_comment_count = 0;
4659 if (fname_new != NULL) {
4660 /* We were trying to write to a temporary file; get rid of it if it
4661 exists. (We don't care whether this fails, as, if it fails,
4662 there's not much we can do about it. I guess if it failed for
4663 a reason other than "it doesn't exist", we could report an
4664 error, so the user knows there's a junk file that they might
4665 want to clean up.) */
4666 ws_unlink(fname_new);
4669 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4670 return CF_WRITE_ERROR;
4674 cf_export_specified_packets(capture_file *cf, const char *fname,
4675 packet_range_t *range, guint save_format,
4676 gboolean compressed)
4678 gchar *fname_new = NULL;
4681 save_callback_args_t callback_args;
4682 GArray *shb_hdrs = NULL;
4683 wtapng_iface_descriptions_t *idb_inf = NULL;
4684 GArray *nrb_hdrs = NULL;
4687 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4689 packet_range_process_init(range);
4691 /* We're writing out specified packets from the specified capture
4692 file to another file. Even if all captured packets are to be
4693 written, don't special-case the operation - read each packet
4694 and then write it out if it's one of the specified ones. */
4696 /* XXX: what free's this shb_hdr? */
4697 shb_hdrs = wtap_file_get_shb_for_new_file(cf->wth);
4698 idb_inf = wtap_file_get_idb_info(cf->wth);
4699 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->wth);
4701 /* Determine what file encapsulation type we should use. */
4702 encap = wtap_dump_file_encap_type(cf->linktypes);
4704 if (file_exists(fname)) {
4705 /* We're overwriting an existing file; write out to a new file,
4706 and, if that succeeds, rename the new file on top of the
4707 old file. That makes this a "safe save", so that we don't
4708 lose the old file if we have a problem writing out the new
4709 file. (If the existing file is the current capture file,
4710 we *HAVE* to do that, otherwise we're overwriting the file
4711 from which we're reading the packets that we're writing!) */
4712 fname_new = g_strdup_printf("%s~", fname);
4713 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4714 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4716 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4717 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4723 cfile_dump_open_failure_alert_box(fname, err, save_format);
4727 /* Add address resolution */
4728 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4730 /* Iterate through the list of packets, processing the packets we were
4733 XXX - we've already called "packet_range_process_init(range)", but
4734 "process_specified_records()" will do it again. Fortunately,
4735 that's harmless in this case, as we haven't done anything to
4736 "range" since we initialized it. */
4737 callback_args.pdh = pdh;
4738 callback_args.fname = fname;
4739 callback_args.file_type = save_format;
4740 switch (process_specified_records(cf, range, "Writing", "specified records",
4741 TRUE, save_record, &callback_args, TRUE)) {
4744 /* Completed successfully. */
4748 /* The user decided to abort the saving.
4749 If we're writing to a temporary file, remove it.
4750 XXX - should we do so even if we're not writing to a
4752 wtap_dump_close(pdh, &err);
4753 if (fname_new != NULL)
4754 ws_unlink(fname_new);
4755 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4756 return CF_WRITE_ABORTED;
4760 /* Error while saving.
4761 If we're writing to a temporary file, remove it. */
4762 if (fname_new != NULL)
4763 ws_unlink(fname_new);
4764 wtap_dump_close(pdh, &err);
4768 if (!wtap_dump_close(pdh, &err)) {
4769 cfile_close_failure_alert_box(fname, err);
4773 if (fname_new != NULL) {
4774 /* We wrote out to fname_new, and should rename it on top of
4775 fname; fname is now closed, so that should be possible even
4776 on Windows. Do the rename. */
4777 if (ws_rename(fname_new, fname) == -1) {
4778 /* Well, the rename failed. */
4779 cf_rename_failure_alert_box(fname, errno);
4784 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4788 if (fname_new != NULL) {
4789 /* We were trying to write to a temporary file; get rid of it if it
4790 exists. (We don't care whether this fails, as, if it fails,
4791 there's not much we can do about it. I guess if it failed for
4792 a reason other than "it doesn't exist", we could report an
4793 error, so the user knows there's a junk file that they might
4794 want to clean up.) */
4795 ws_unlink(fname_new);
4798 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4799 return CF_WRITE_ERROR;
4803 * XXX - whether we mention the source pathname, the target pathname,
4804 * or both depends on the error and on what we find if we look for
4805 * one or both of them.
4808 cf_rename_failure_alert_box(const char *filename, int err)
4810 gchar *display_basename;
4812 display_basename = g_filename_display_basename(filename);
4816 /* XXX - should check whether the source exists and, if not,
4817 report it as the problem and, if so, report the destination
4819 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4824 /* XXX - if we're doing a rename after a safe save, we should
4825 probably say something else. */
4826 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4831 /* XXX - this should probably mention both the source and destination
4833 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4834 display_basename, wtap_strerror(err));
4837 g_free(display_basename);
4840 /* Reload the current capture file. */
4842 cf_reload(capture_file *cf) {
4844 gboolean is_tempfile;
4847 /* If the file could be opened, "cf_open()" calls "cf_close()"
4848 to get rid of state for the old capture file before filling in state
4849 for the new capture file. "cf_close()" will remove the file if
4850 it's a temporary file; we don't want that to happen (for one thing,
4851 it'd prevent subsequent reopens from working). Remember whether it's
4852 a temporary file, mark it as not being a temporary file, and then
4853 reopen it as the type of file it was.
4855 Also, "cf_close()" will free "cf->filename", so we must make
4856 a copy of it first. */
4857 filename = g_strdup(cf->filename);
4858 is_tempfile = cf->is_tempfile;
4859 cf->is_tempfile = FALSE;
4860 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4861 switch (cf_read(cf, TRUE)) {
4865 /* Just because we got an error, that doesn't mean we were unable
4866 to read any of the file; we handle what we could get from the
4870 case CF_READ_ABORTED:
4871 /* The user bailed out of re-reading the capture file; the
4872 capture file has been closed - just free the capture file name
4873 string and return (without changing the last containing
4879 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4880 Instead, the file was left open, so we should restore "cf->is_tempfile"
4883 XXX - change the menu? Presumably "cf_open()" will do that;
4884 make sure it does! */
4885 cf->is_tempfile = is_tempfile;
4887 /* "cf_open()" made a copy of the file name we handed it, so
4888 we should free up our copy. */
4898 * indent-tabs-mode: nil
4901 * ex: set shiftwidth=2 tabstop=8 expandtab:
4902 * :indentSize=2:tabSize=8:noTabs=true: