4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <wsutil/tempfile.h>
22 #include <wsutil/file_util.h>
23 #include <wsutil/filesystem.h>
24 #include <version_info.h>
26 #include <wiretap/merge.h>
28 #include <epan/exceptions.h>
29 #include <epan/epan.h>
30 #include <epan/column.h>
31 #include <epan/packet.h>
32 #include <epan/column-utils.h>
33 #include <epan/expert.h>
34 #include <epan/prefs.h>
35 #include <epan/dfilter/dfilter.h>
36 #include <epan/epan_dissect.h>
38 #include <epan/dissectors/packet-ber.h>
39 #include <epan/timestamp.h>
40 #include <epan/dfilter/dfilter-macro.h>
41 #include <epan/strutil.h>
42 #include <epan/addr_resolv.h>
43 #include <epan/color_filters.h>
48 #include "frame_tvbuff.h"
50 #include "ui/alert_box.h"
51 #include "ui/simple_dialog.h"
52 #include "ui/main_statusbar.h"
53 #include "ui/progress_dlg.h"
54 #include "ui/ws_ui_util.h"
56 /* Needed for addrinfo */
57 #include <sys/types.h>
59 #ifdef HAVE_SYS_SOCKET_H
60 #include <sys/socket.h>
63 #ifdef HAVE_NETINET_IN_H
64 # include <netinet/in.h>
68 # include <winsock2.h>
69 # include <ws2tcpip.h>
72 static gboolean read_record(capture_file *cf, dfilter_t *dfcode,
73 epan_dissect_t *edt, column_info *cinfo, gint64 offset);
75 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
82 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
84 static void match_subtree_text(proto_node *node, gpointer data);
85 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
87 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
89 static match_result match_narrow(capture_file *cf, frame_data *fdata,
91 static match_result match_wide(capture_file *cf, frame_data *fdata,
93 static match_result match_binary(capture_file *cf, frame_data *fdata,
95 static match_result match_regex(capture_file *cf, frame_data *fdata,
97 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
99 static match_result match_marked(capture_file *cf, frame_data *fdata,
101 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
103 static gboolean find_packet(capture_file *cf,
104 match_result (*match_function)(capture_file *, frame_data *, void *),
105 void *criterion, search_direction dir);
107 static void cf_rename_failure_alert_box(const char *filename, int err);
108 static void ref_time_packets(capture_file *cf);
110 /* Seconds spent processing packets between pushing UI updates. */
111 #define PROGBAR_UPDATE_INTERVAL 0.150
113 /* Show the progress bar after this many seconds. */
114 #define PROGBAR_SHOW_DELAY 0.5
117 * We could probably use g_signal_...() instead of the callbacks below but that
118 * would require linking our CLI programs to libgobject and creating an object
119 * instance for the signals.
122 cf_callback_t cb_fct;
124 } cf_callback_data_t;
126 static GList *cf_callbacks = NULL;
129 cf_callback_invoke(int event, gpointer data)
131 cf_callback_data_t *cb;
132 GList *cb_item = cf_callbacks;
134 /* there should be at least one interested */
135 g_assert(cb_item != NULL);
137 while (cb_item != NULL) {
138 cb = (cf_callback_data_t *)cb_item->data;
139 cb->cb_fct(event, data, cb->user_data);
140 cb_item = g_list_next(cb_item);
146 cf_callback_add(cf_callback_t func, gpointer user_data)
148 cf_callback_data_t *cb;
150 cb = g_new(cf_callback_data_t,1);
152 cb->user_data = user_data;
154 cf_callbacks = g_list_prepend(cf_callbacks, cb);
158 cf_callback_remove(cf_callback_t func, gpointer user_data)
160 cf_callback_data_t *cb;
161 GList *cb_item = cf_callbacks;
163 while (cb_item != NULL) {
164 cb = (cf_callback_data_t *)cb_item->data;
165 if (cb->cb_fct == func && cb->user_data == user_data) {
166 cf_callbacks = g_list_remove(cf_callbacks, cb);
170 cb_item = g_list_next(cb_item);
173 g_assert_not_reached();
177 cf_timestamp_auto_precision(capture_file *cf)
181 /* don't try to get the file's precision if none is opened */
182 if (cf->state == FILE_CLOSED) {
186 /* Set the column widths of those columns that show the time in
187 "command-line-specified" format. */
188 for (i = 0; i < cf->cinfo.num_cols; i++) {
189 if (col_has_time_fmt(&cf->cinfo, i)) {
190 packet_list_resize_column(i);
196 cf_get_computed_elapsed(capture_file *cf)
198 return cf->computed_elapsed;
202 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
205 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
210 g_get_current_time(&time_now);
212 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
213 time_now.tv_usec - start_time->tv_usec;
215 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
218 static const nstime_t *
219 ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
221 if (prov->prev_dis && prov->prev_dis->num == frame_num)
222 return &prov->prev_dis->abs_ts;
224 if (prov->prev_cap && prov->prev_cap->num == frame_num)
225 return &prov->prev_cap->abs_ts;
228 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
230 return (fd) ? &fd->abs_ts : NULL;
237 ws_epan_new(capture_file *cf)
239 static const struct packet_provider_funcs funcs = {
241 cap_file_provider_get_interface_name,
242 cap_file_provider_get_interface_description,
243 cap_file_provider_get_user_comment
246 return epan_new(&cf->provider, &funcs);
250 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
255 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
259 /* The open succeeded. Close whatever capture file we had open,
260 and fill in the information for this file. */
263 /* Initialize the record metadata. */
264 wtap_rec_init(&cf->rec);
266 /* XXX - we really want to initialize this after we've read all
267 the packets, so we know how much we'll ultimately need. */
268 ws_buffer_init(&cf->buf, 1500);
270 /* Create new epan session for dissection.
271 * (The old one was freed in cf_close().)
273 cf->epan = ws_epan_new(cf);
275 /* We're about to start reading the file. */
276 cf->state = FILE_READ_IN_PROGRESS;
278 cf->provider.wth = wth;
281 /* Set the file name because we need it to set the follow stream filter.
282 XXX - is that still true? We need it for other reasons, though,
284 cf->filename = g_strdup(fname);
286 /* Indicate whether it's a permanent or temporary file. */
287 cf->is_tempfile = is_tempfile;
289 /* No user changes yet. */
290 cf->unsaved_changes = FALSE;
292 cf->computed_elapsed = 0;
294 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
295 cf->open_type = type;
296 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
298 cf->packet_comment_count = 0;
299 cf->displayed_count = 0;
300 cf->marked_count = 0;
301 cf->ignored_count = 0;
302 cf->ref_time_count = 0;
303 cf->drops_known = FALSE;
305 cf->snap = wtap_snapshot_length(cf->provider.wth);
307 /* Allocate a frame_data_sequence for the frames in this file */
308 cf->provider.frames = new_frame_data_sequence();
310 nstime_set_zero(&cf->elapsed_time);
311 cf->provider.ref = NULL;
312 cf->provider.prev_dis = NULL;
313 cf->provider.prev_cap = NULL;
316 packet_list_queue_draw();
317 cf_callback_invoke(cf_cb_file_opened, cf);
319 if ((cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER)
320 || (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_PEM)) {
321 /* tell the BER dissector the file name */
322 ber_set_filename(cf->filename);
325 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
326 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
331 cfile_open_failure_alert_box(fname, *err, err_info);
336 * Add an encapsulation type to cf->linktypes.
339 cf_add_encapsulation_type(capture_file *cf, int encap)
343 for (i = 0; i < cf->linktypes->len; i++) {
344 if (g_array_index(cf->linktypes, gint, i) == encap)
345 return; /* it's already there */
347 /* It's not already there - add it. */
348 g_array_append_val(cf->linktypes, encap);
351 /* Reset everything to a pristine state */
353 cf_close(capture_file *cf)
355 cf->stop_flag = FALSE;
356 if (cf->state == FILE_CLOSED)
357 return; /* Nothing to do */
359 /* Die if we're in the middle of reading a file. */
360 g_assert(cf->state != FILE_READ_IN_PROGRESS);
361 g_assert(!cf->read_lock);
363 cf_callback_invoke(cf_cb_file_closing, cf);
365 /* close things, if not already closed before */
366 color_filters_cleanup();
368 if (cf->provider.wth) {
369 wtap_close(cf->provider.wth);
370 cf->provider.wth = NULL;
372 /* We have no file open... */
373 if (cf->filename != NULL) {
374 /* If it's a temporary file, remove it. */
376 ws_unlink(cf->filename);
377 g_free(cf->filename);
380 /* ...which means we have no changes to that file to save. */
381 cf->unsaved_changes = FALSE;
383 /* no open_routine type */
384 cf->open_type = WTAP_TYPE_AUTO;
386 /* Clean up the record metadata. */
387 wtap_rec_cleanup(&cf->rec);
389 /* Free up the packet buffer. */
390 ws_buffer_free(&cf->buf);
392 dfilter_free(cf->rfcode);
394 if (cf->provider.frames != NULL) {
395 free_frame_data_sequence(cf->provider.frames);
396 cf->provider.frames = NULL;
398 if (cf->provider.frames_user_comments) {
399 g_tree_destroy(cf->provider.frames_user_comments);
400 cf->provider.frames_user_comments = NULL;
402 cf_unselect_packet(cf); /* nothing to select */
403 cf->first_displayed = 0;
404 cf->last_displayed = 0;
406 /* No frames, no frame selected, no field in that frame selected. */
408 cf->current_frame = 0;
410 cf->finfo_selected = NULL;
412 /* No frame link-layer types, either. */
413 if (cf->linktypes != NULL) {
414 g_array_free(cf->linktypes, TRUE);
415 cf->linktypes = NULL;
418 /* Clear the packet list. */
419 packet_list_freeze();
424 nstime_set_zero(&cf->elapsed_time);
426 reset_tap_listeners();
431 /* We have no file open. */
432 cf->state = FILE_CLOSED;
434 cf_callback_invoke(cf_cb_file_closed, cf);
438 * TRUE if the progress dialog doesn't exist and it looks like we'll
439 * take > 2s to load, FALSE otherwise.
441 static inline gboolean
442 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
446 if (progdlg) return FALSE;
447 elapsed = g_timer_elapsed(prog_timer, NULL);
448 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
449 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
456 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
460 progbar_val = (gfloat) file_pos / (gfloat) size;
461 if (progbar_val > 1.0) {
463 /* The file probably grew while we were reading it.
464 * Update file size, and try again.
466 size = wtap_file_size(cf->provider.wth, NULL);
469 progbar_val = (gfloat) file_pos / (gfloat) size;
471 /* If it's still > 1, either "wtap_file_size()" failed (in which
472 * case there's not much we can do about it), or the file
473 * *shrank* (in which case there's not much we can do about
474 * it); just clip the progress value at 1.0.
476 if (progbar_val > 1.0f)
480 g_snprintf(status_str, status_size,
481 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
482 file_pos / 1024, size / 1024);
488 cf_read(capture_file *cf, gboolean reloading)
491 gchar *err_info = NULL;
493 progdlg_t *volatile progbar = NULL;
494 GTimer *prog_timer = g_timer_new();
498 volatile gboolean create_proto_tree;
501 volatile gboolean is_read_aborted = FALSE;
503 /* The update_progress_dlg call below might end up accepting a user request to
504 * trigger redissection/rescans which can modify/destroy the dissection
505 * context ("cf->epan"). That condition should be prevented by callers, but in
506 * case it occurs let's fail gracefully.
509 g_warning("Failing due to recursive cf_read(\"%s\", %d) call!",
510 cf->filename, reloading);
511 return CF_READ_ERROR;
513 cf->read_lock = TRUE;
515 /* Compile the current display filter.
516 * We assume this will not fail since cf->dfilter is only set in
517 * cf_filter IFF the filter was valid.
519 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
520 g_assert(!cf->dfilter || (compiled && dfcode));
522 /* Get the union of the flags for all tap listeners. */
523 tap_flags = union_of_tap_listener_flags();
526 * Determine whether we need to create a protocol tree.
529 * we're going to apply a display filter;
531 * one of the tap listeners is going to apply a filter;
533 * one of the tap listeners requires a protocol tree;
535 * a postdissector wants field values or protocols on
539 (dfcode != NULL || have_filtering_tap_listeners() ||
540 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
542 reset_tap_listeners();
544 name_ptr = g_filename_display_basename(cf->filename);
547 cf_callback_invoke(cf_cb_file_reload_started, cf);
549 cf_callback_invoke(cf_cb_file_read_started, cf);
551 /* Record whether the file is compressed.
552 XXX - do we know this at open time? */
553 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
555 /* The packet list window will be empty until the file is completly loaded */
556 packet_list_freeze();
558 cf->stop_flag = FALSE;
559 g_get_current_time(&start_time);
561 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
571 gchar status_str[100];
575 /* If any tap listeners require the columns, construct them. */
576 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
578 /* Find the size of the file. */
579 size = wtap_file_size(cf->provider.wth, NULL);
581 g_timer_start(prog_timer);
583 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
586 file_pos = wtap_read_so_far(cf->provider.wth);
588 /* Create the progress bar if necessary. */
589 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
590 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
592 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
593 TRUE, &cf->stop_flag, &start_time, progbar_val);
595 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
596 TRUE, &cf->stop_flag, &start_time, progbar_val);
600 * Update the progress bar, but do it only after
601 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
602 * and packets_bar_update will likely trigger UI paint events, which
603 * might take a while depending on the platform and display. Reset
604 * our timer *after* painting.
606 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
607 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
608 /* update the packet bar content on the first run or frequently on very large files */
609 update_progress_dlg(progbar, progbar_val, status_str);
610 compute_elapsed(cf, &start_time);
611 packets_bar_update();
612 g_timer_start(prog_timer);
615 * The previous GUI triggers should not have destroyed the running
616 * session. If that did happen, it could blow up when read_record tries
617 * to use the destroyed edt.session, so detect it right here.
619 g_assert(edt.session == cf->epan);
622 if (cf->state == FILE_READ_ABORTED) {
623 /* Well, the user decided to exit Wireshark. Break out of the
624 loop, and let the code below (which is called even if there
625 aren't any packets left to read) exit. */
626 is_read_aborted = TRUE;
630 /* Well, the user decided to abort the read. He/She will be warned and
631 it might be enough for him/her to work with the already loaded
633 This is especially true for very large capture files, where you don't
634 want to wait loading the whole file (which may last minutes or even
635 hours even on fast machines) just to see that it was the wrong file. */
638 read_record(cf, dfcode, &edt, cinfo, data_offset);
641 CATCH(OutOfMemoryError) {
642 simple_message_box(ESD_TYPE_ERROR, NULL,
643 "More information and workarounds can be found at\n"
644 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
645 "Sorry, but Wireshark has run out of memory and has to terminate now.");
647 /* Could we close the current capture and free up memory from that? */
649 /* we have to terminate, as we cannot recover from the memory error */
655 /* Free the display name */
658 /* Cleanup and release all dfilter resources */
659 dfilter_free(dfcode);
661 epan_dissect_cleanup(&edt);
663 /* We're done reading the file; destroy the progress bar if it was created. */
665 destroy_progress_dlg(progbar);
666 g_timer_destroy(prog_timer);
668 /* We're done reading sequentially through the file. */
669 cf->state = FILE_READ_DONE;
671 /* Close the sequential I/O side, to free up memory it requires. */
672 wtap_sequential_close(cf->provider.wth);
674 /* Allow the protocol dissectors to free up memory that they
675 * don't need after the sequential run-through of the packets. */
676 postseq_cleanup_all_protocols();
678 /* compute the time it took to load the file */
679 compute_elapsed(cf, &start_time);
681 /* Set the file encapsulation type now; we don't know what it is until
682 we've looked at all the packets, as we don't know until then whether
683 there's more than one type (and thus whether it's
684 WTAP_ENCAP_PER_PACKET). */
685 cf->lnk_t = wtap_file_encap(cf->provider.wth);
687 cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed);
692 cf_callback_invoke(cf_cb_file_reload_finished, cf);
694 cf_callback_invoke(cf_cb_file_read_finished, cf);
696 /* If we have any displayed packets to select, select the first of those
697 packets by making the first row the selected row. */
698 if (cf->first_displayed != 0) {
699 packet_list_select_first_row();
702 /* It is safe again to execute redissections. */
703 g_assert(cf->read_lock);
704 cf->read_lock = FALSE;
706 if (is_read_aborted) {
708 * Well, the user decided to exit Wireshark while reading this *offline*
709 * capture file (Live captures are handled by something like
710 * cf_continue_tail). Clean up accordingly.
713 cf->redissection_queued = RESCAN_NONE;
714 return CF_READ_ABORTED;
717 if (cf->redissection_queued != RESCAN_NONE) {
718 /* Redissection was queued up. Clear the request and perform it now. */
719 gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT;
720 rescan_packets(cf, "Reprocessing", "all packets", redissect);
724 simple_message_box(ESD_TYPE_WARN, NULL,
725 "The remaining packets in the file were discarded.\n"
727 "As a lot of packets from the original file will be missing,\n"
728 "remember to be careful when saving the current content to a file.\n",
729 "File loading was cancelled.");
730 return CF_READ_ERROR;
734 /* Put up a message box noting that the read failed somewhere along
735 the line. Don't throw out the stuff we managed to read, though,
737 cfile_read_failure_alert_box(NULL, err, err_info);
738 return CF_READ_ERROR;
745 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
748 volatile int newly_displayed_packets = 0;
751 gboolean create_proto_tree;
755 /* Compile the current display filter.
756 * We assume this will not fail since cf->dfilter is only set in
757 * cf_filter IFF the filter was valid.
759 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
760 g_assert(!cf->dfilter || (compiled && dfcode));
762 /* Get the union of the flags for all tap listeners. */
763 tap_flags = union_of_tap_listener_flags();
766 * Determine whether we need to create a protocol tree.
769 * we're going to apply a display filter;
771 * one of the tap listeners is going to apply a filter;
773 * one of the tap listeners requires a protocol tree;
775 * a postdissector wants field values or protocols on
779 (dfcode != NULL || have_filtering_tap_listeners() ||
780 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
784 /* Don't freeze/thaw the list when doing live capture */
785 /*packet_list_freeze();*/
787 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
789 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
792 gint64 data_offset = 0;
795 /* If any tap listeners require the columns, construct them. */
796 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
798 while (to_read != 0) {
799 wtap_cleareof(cf->provider.wth);
800 if (!wtap_read(cf->provider.wth, err, &err_info, &data_offset)) {
803 if (cf->state == FILE_READ_ABORTED) {
804 /* Well, the user decided to exit Wireshark. Break out of the
805 loop, and let the code below (which is called even if there
806 aren't any packets left to read) exit. */
809 if (read_record(cf, dfcode, &edt, (column_info *) cinfo, data_offset)) {
810 newly_displayed_packets++;
815 CATCH(OutOfMemoryError) {
816 simple_message_box(ESD_TYPE_ERROR, NULL,
817 "More information and workarounds can be found at\n"
818 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
819 "Sorry, but Wireshark has run out of memory and has to terminate now.");
821 /* Could we close the current capture and free up memory from that? */
822 return CF_READ_ABORTED;
824 /* we have to terminate, as we cannot recover from the memory error */
830 /* Update the file encapsulation; it might have changed based on the
831 packets we've read. */
832 cf->lnk_t = wtap_file_encap(cf->provider.wth);
834 /* Cleanup and release all dfilter resources */
835 dfilter_free(dfcode);
837 epan_dissect_cleanup(&edt);
839 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
840 cf->count, cf->state, *err);*/
842 /* Don't freeze/thaw the list when doing live capture */
843 /*packet_list_thaw();*/
844 /* With the new packet list the first packet
845 * isn't automatically selected.
847 if (!cf->current_frame)
848 packet_list_select_first_row();
850 /* moving to the end of the packet list - if the user requested so and
851 we have some new packets. */
852 if (newly_displayed_packets && cf->count != 0)
853 packet_list_moveto_end();
855 if (cf->state == FILE_READ_ABORTED) {
856 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
857 so that our caller can kill off the capture child process;
858 this will cause an EOF on the pipe from the child, so
859 "cf_finish_tail()" will be called, and it will clean up
861 return CF_READ_ABORTED;
862 } else if (*err != 0) {
863 /* We got an error reading the capture file.
864 XXX - pop up a dialog box instead? */
865 if (err_info != NULL) {
866 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
867 wtap_strerror(*err), cf->filename, err_info);
870 g_warning("Error \"%s\" while reading \"%s\"",
871 wtap_strerror(*err), cf->filename);
873 return CF_READ_ERROR;
879 cf_fake_continue_tail(capture_file *cf) {
880 cf->state = FILE_READ_DONE;
884 cf_finish_tail(capture_file *cf, int *err)
891 gboolean create_proto_tree;
895 /* Compile the current display filter.
896 * We assume this will not fail since cf->dfilter is only set in
897 * cf_filter IFF the filter was valid.
899 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
900 g_assert(!cf->dfilter || (compiled && dfcode));
902 /* Get the union of the flags for all tap listeners. */
903 tap_flags = union_of_tap_listener_flags();
905 /* If any tap listeners require the columns, construct them. */
906 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
909 * Determine whether we need to create a protocol tree.
912 * we're going to apply a display filter;
914 * one of the tap listeners is going to apply a filter;
916 * one of the tap listeners requires a protocol tree;
918 * a postdissector wants field values or protocols on
922 (dfcode != NULL || have_filtering_tap_listeners() ||
923 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
925 if (cf->provider.wth == NULL) {
927 return CF_READ_ERROR;
930 /* Don't freeze/thaw the list when doing live capture */
931 /*packet_list_freeze();*/
933 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
935 while ((wtap_read(cf->provider.wth, err, &err_info, &data_offset))) {
936 if (cf->state == FILE_READ_ABORTED) {
937 /* Well, the user decided to abort the read. Break out of the
938 loop, and let the code below (which is called even if there
939 aren't any packets left to read) exit. */
942 read_record(cf, dfcode, &edt, cinfo, data_offset);
945 /* Cleanup and release all dfilter resources */
946 dfilter_free(dfcode);
948 epan_dissect_cleanup(&edt);
950 /* Don't freeze/thaw the list when doing live capture */
951 /*packet_list_thaw();*/
953 if (cf->state == FILE_READ_ABORTED) {
954 /* Well, the user decided to abort the read. We're only called
955 when the child capture process closes the pipe to us (meaning
956 it's probably exited), so we can just close the capture
957 file; we return CF_READ_ABORTED so our caller can do whatever
958 is appropriate when that happens. */
960 return CF_READ_ABORTED;
963 /* We're done reading sequentially through the file. */
964 cf->state = FILE_READ_DONE;
966 /* We're done reading sequentially through the file; close the
967 sequential I/O side, to free up memory it requires. */
968 wtap_sequential_close(cf->provider.wth);
970 /* Allow the protocol dissectors to free up memory that they
971 * don't need after the sequential run-through of the packets. */
972 postseq_cleanup_all_protocols();
974 /* Update the file encapsulation; it might have changed based on the
975 packets we've read. */
976 cf->lnk_t = wtap_file_encap(cf->provider.wth);
978 /* Update the details in the file-set dialog, as the capture file
979 * has likely grown since we first stat-ed it */
980 fileset_update_file(cf->filename);
983 /* We got an error reading the capture file.
984 XXX - pop up a dialog box? */
985 if (err_info != NULL) {
986 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
987 wtap_strerror(*err), cf->filename, err_info);
990 g_warning("Error \"%s\" while reading \"%s\"",
991 wtap_strerror(*err), cf->filename);
993 return CF_READ_ERROR;
998 #endif /* HAVE_LIBPCAP */
1001 cf_get_display_name(capture_file *cf)
1005 /* Return a name to use in displays */
1006 if (!cf->is_tempfile) {
1007 /* Get the last component of the file name, and use that. */
1009 displayname = g_filename_display_basename(cf->filename);
1011 displayname=g_strdup("(No file)");
1014 /* The file we read is a temporary file from a live capture or
1015 a merge operation; we don't mention its name, but, if it's
1016 from a capture, give the source of the capture. */
1018 displayname = g_strdup(cf->source);
1020 displayname = g_strdup("(Untitled)");
1027 cf_get_basename(capture_file *cf)
1031 /* Return a name to use in the GUI for the basename for files to
1032 which we save statistics */
1033 if (!cf->is_tempfile) {
1034 /* Get the last component of the file name, and use that. */
1036 displayname = g_filename_display_basename(cf->filename);
1038 /* If the file name ends with any extension that corresponds
1039 to a file type we support - including compressed versions
1040 of those files - strip it off. */
1041 size_t displayname_len = strlen(displayname);
1042 GSList *extensions = wtap_get_all_file_extensions_list();
1044 for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) {
1045 /* Does the file name end with that extension? */
1046 const char *extension = (char *)suffix->data;
1047 size_t extension_len = strlen(extension);
1048 if (displayname_len > extension_len &&
1049 displayname[displayname_len - extension_len - 1] == '.' &&
1050 strcmp(&displayname[displayname_len - extension_len], extension) == 0) {
1051 /* Yes. Strip the extension off, and return the result. */
1052 displayname[displayname_len - extension_len - 1] = '\0';
1056 wtap_free_extensions_list(extensions);
1058 displayname=g_strdup("");
1061 /* The file we read is a temporary file from a live capture or
1062 a merge operation; we don't mention its name, but, if it's
1063 from a capture, give the source of the capture. */
1065 displayname = g_strdup(cf->source);
1067 displayname = g_strdup("");
1073 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1079 cf->source = g_strdup(source);
1081 cf->source = g_strdup("");
1085 const gchar *cf_get_tempfile_source(capture_file *cf) {
1093 /* XXX - use a macro instead? */
1095 cf_get_packet_count(capture_file *cf)
1100 /* XXX - use a macro instead? */
1102 cf_is_tempfile(capture_file *cf)
1104 return cf->is_tempfile;
1107 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1109 cf->is_tempfile = is_tempfile;
1113 /* XXX - use a macro instead? */
1114 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1116 cf->drops_known = drops_known;
1119 /* XXX - use a macro instead? */
1120 void cf_set_drops(capture_file *cf, guint32 drops)
1125 /* XXX - use a macro instead? */
1126 gboolean cf_get_drops_known(capture_file *cf)
1128 return cf->drops_known;
1131 /* XXX - use a macro instead? */
1132 guint32 cf_get_drops(capture_file *cf)
1137 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1139 cf->rfcode = rfcode;
1143 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1144 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1145 wtap_rec *rec, const guint8 *buf, gboolean add_to_packet_list)
1147 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1148 &cf->provider.ref, cf->provider.prev_dis);
1149 cf->provider.prev_cap = fdata;
1151 if (dfcode != NULL) {
1152 epan_dissect_prime_with_dfilter(edt, dfcode);
1155 /* Prepare coloring rules, this ensures that display filter rules containing
1156 * frame.color_rule references are still processed.
1157 * TODO: actually detect that situation or maybe apply other optimizations? */
1158 if (edt->tree && color_filters_used()) {
1159 color_filters_prime_edt(edt);
1160 fdata->flags.need_colorize = 1;
1164 if (!fdata->flags.visited) {
1165 /* This is the first pass, so prime the epan_dissect_t with the
1166 hfids postdissectors want on the first pass. */
1167 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1170 /* Dissect the frame. */
1171 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1172 frame_tvbuff_new(&cf->provider, fdata, buf),
1175 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1176 if (dfcode != NULL) {
1177 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1179 if (fdata->flags.passed_dfilter) {
1180 /* This frame passed the display filter but it may depend on other
1181 * (potentially not displayed) frames. Find those frames and mark them
1184 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1187 fdata->flags.passed_dfilter = 1;
1189 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1190 cf->displayed_count++;
1192 if (add_to_packet_list) {
1193 /* We fill the needed columns from new_packet_list */
1194 packet_list_append(cinfo, fdata);
1197 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1199 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1200 cf->provider.prev_dis = fdata;
1202 /* If we haven't yet seen the first frame, this is it. */
1203 if (cf->first_displayed == 0)
1204 cf->first_displayed = fdata->num;
1206 /* This is the last frame we've seen so far. */
1207 cf->last_displayed = fdata->num;
1210 epan_dissect_reset(edt);
1214 * Read in a new record.
1215 * Returns TRUE if the packet was added to the packet (record) list,
1219 read_record(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1220 column_info *cinfo, gint64 offset)
1222 wtap_rec *rec = wtap_get_rec(cf->provider.wth);
1223 const guint8 *buf = wtap_get_buf_ptr(cf->provider.wth);
1226 gboolean passed = TRUE;
1227 gboolean added = FALSE;
1229 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1230 it's not already there.
1231 XXX - yes, this is O(N), so if every packet had a different
1232 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1233 there are probably going to be a small number of encapsulation types
1235 if (rec->rec_type == REC_TYPE_PACKET) {
1236 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
1239 /* The frame number of this packet, if we add it to the set of frames,
1240 would be one more than the count of frames in the file so far. */
1241 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes);
1244 epan_dissect_t rf_edt;
1246 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1247 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1248 epan_dissect_run(&rf_edt, cf->cd_t, rec,
1249 frame_tvbuff_new(&cf->provider, &fdlocal, buf),
1251 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1252 epan_dissect_cleanup(&rf_edt);
1258 /* This does a shallow copy of fdlocal, which is good enough. */
1259 fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1262 if (rec->opt_comment != NULL)
1263 cf->packet_comment_count++;
1264 cf->f_datalen = offset + fdlocal.cap_len;
1266 /* When a redissection is in progress (or queued), do not process packets.
1267 * This will be done once all (new) packets have been scanned. */
1268 if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) {
1269 add_packet_to_packet_list(fdata, cf, edt, dfcode,
1270 cinfo, rec, buf, TRUE);
1278 typedef struct _callback_data_t {
1281 GTimeVal start_time;
1289 merge_callback(merge_event event, int num _U_,
1290 const merge_in_file_t in_files[], const guint in_file_count,
1294 callback_data_t *cb_data = (callback_data_t*) data;
1296 g_assert(cb_data != NULL);
1300 case MERGE_EVENT_INPUT_FILES_OPENED:
1304 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1308 case MERGE_EVENT_READY_TO_MERGE:
1309 /* Get the sum of the sizes of all the files. */
1310 for (i = 0; i < in_file_count; i++)
1311 cb_data->f_len += in_files[i].size;
1313 cb_data->prog_timer = g_timer_new();
1314 g_timer_start(cb_data->prog_timer);
1316 g_get_current_time(&cb_data->start_time);
1319 case MERGE_EVENT_RECORD_WAS_READ:
1321 /* Create the progress bar if necessary.
1322 We check on every iteration of the loop, so that it takes no
1323 longer than the standard time to create it (otherwise, for a
1324 large file, we might take considerably longer than that standard
1325 time in order to get to the next progress bar step). */
1326 if (cb_data->progbar == NULL) {
1327 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1328 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1332 * Update the progress bar, but do it only after
1333 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1334 * and packets_bar_update will likely trigger UI paint events, which
1335 * might take a while depending on the platform and display. Reset
1336 * our timer *after* painting.
1338 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1340 gint64 file_pos = 0;
1341 /* Get the sum of the seek positions in all of the files. */
1342 for (i = 0; i < in_file_count; i++)
1343 file_pos += wtap_read_so_far(in_files[i].wth);
1345 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1346 if (progbar_val > 1.0f) {
1347 /* Some file probably grew while we were reading it.
1348 That "shouldn't happen", so we'll just clip the progress
1353 if (cb_data->progbar != NULL) {
1354 gchar status_str[100];
1355 g_snprintf(status_str, sizeof(status_str),
1356 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1357 file_pos / 1024, cb_data->f_len / 1024);
1358 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1360 g_timer_start(cb_data->prog_timer);
1365 case MERGE_EVENT_DONE:
1366 /* We're done merging the files; destroy the progress bar if it was created. */
1367 if (cb_data->progbar != NULL)
1368 destroy_progress_dlg(cb_data->progbar);
1369 g_timer_destroy(cb_data->prog_timer);
1373 return cb_data->stop_flag;
1379 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1380 int in_file_count, char *const *in_filenames,
1381 int file_type, gboolean do_append)
1384 gchar *err_info = NULL;
1386 guint32 err_framenum;
1387 merge_result status;
1388 merge_progress_callback_t cb;
1389 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1391 /* prepare our callback routine */
1392 cb_data->pd_window = pd_window;
1393 cb.callback_func = merge_callback;
1396 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1398 /* merge the files */
1399 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1400 (const char *const *) in_filenames,
1401 in_file_count, do_append,
1402 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1403 "Wireshark", &cb, &err, &err_info,
1404 &err_fileno, &err_framenum);
1412 case MERGE_USER_ABORTED:
1413 /* this isn't really an error, though we will return CF_ERROR later */
1416 case MERGE_ERR_CANT_OPEN_INFILE:
1417 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1420 case MERGE_ERR_CANT_OPEN_OUTFILE:
1421 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1424 case MERGE_ERR_CANT_READ_INFILE:
1425 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1428 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1429 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1430 err_framenum, in_filenames[err_fileno]);
1433 case MERGE_ERR_CANT_WRITE_OUTFILE:
1434 cfile_write_failure_alert_box(in_filenames[err_fileno],
1435 *out_filenamep, err, err_info,
1436 err_framenum, file_type);
1439 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1440 cfile_close_failure_alert_box(*out_filenamep, err);
1444 simple_error_message_box("Unknown merge_files error %d", status);
1448 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1450 if (status != MERGE_OK) {
1451 /* Callers aren't expected to treat an error or an explicit abort
1452 differently - we put up error dialogs ourselves, so they don't
1460 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1462 const char *filter_new = dftext ? dftext : "";
1463 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1466 GTimeVal start_time;
1468 /* if new filter equals old one, do nothing unless told to do so */
1469 if (!force && strcmp(filter_new, filter_old) == 0) {
1475 if (dftext == NULL) {
1476 /* The new filter is an empty filter (i.e., display all packets).
1477 * so leave dfcode==NULL
1481 * We have a filter; make a copy of it (as we'll be saving it),
1482 * and try to compile it.
1484 dftext = g_strdup(dftext);
1485 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1486 /* The attempt failed; report an error. */
1487 simple_message_box(ESD_TYPE_ERROR, NULL,
1488 "See the help for a description of the display filter syntax.",
1489 "\"%s\" isn't a valid display filter: %s",
1497 if (dfcode == NULL) {
1498 /* Yes - free the filter text, and set it to null. */
1504 /* We have a valid filter. Replace the current filter. */
1505 g_free(cf->dfilter);
1506 cf->dfilter = dftext;
1507 g_get_current_time(&start_time);
1510 /* Now rescan the packet list, applying the new filter, but not
1511 * throwing away information constructed on a previous pass.
1512 * If a dissection is already in progress, queue it.
1514 if (cf->redissection_queued == RESCAN_NONE) {
1515 if (cf->read_lock) {
1516 cf->redissection_queued = RESCAN_SCAN;
1517 } else if (cf->state != FILE_CLOSED) {
1518 if (dftext == NULL) {
1519 rescan_packets(cf, "Resetting", "Filter", FALSE);
1521 rescan_packets(cf, "Filtering", dftext, FALSE);
1526 /* Cleanup and release all dfilter resources */
1527 dfilter_free(dfcode);
1533 cf_reftime_packets(capture_file *cf)
1535 ref_time_packets(cf);
1539 cf_redissect_packets(capture_file *cf)
1541 if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) {
1542 /* Dissection in progress, signal redissection rather than rescanning. That
1543 * would destroy the current (in-progress) dissection in "cf_read" which
1544 * will cause issues when "cf_read" tries to add packets to the list.
1545 * If a previous rescan was requested, "upgrade" it to a full redissection.
1547 cf->redissection_queued = RESCAN_REDISSECT;
1549 if (cf->redissection_queued != RESCAN_NONE) {
1550 /* Redissection is (already) queued, wait for "cf_read" to finish. */
1554 if (cf->state != FILE_CLOSED) {
1555 /* Restart dissection in case no cf_read is pending. */
1556 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1561 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1562 wtap_rec *rec, Buffer *buf)
1567 if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
1568 cfile_read_failure_alert_box(cf->filename, err, err_info);
1575 cf_read_record(capture_file *cf, frame_data *fdata)
1577 return cf_read_record_r(cf, fdata, &cf->rec, &cf->buf);
1580 /* Rescan the list of packets, reconstructing the CList.
1582 "action" describes why we're doing this; it's used in the progress
1585 "action_item" describes what we're doing; it's used in the progress
1588 "redissect" is TRUE if we need to make the dissectors reconstruct
1589 any state information they have (because a preference that affects
1590 some dissector has changed, meaning some dissector might construct
1591 its state differently from the way it was constructed the last time). */
1593 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1595 /* Rescan packets new packet list */
1598 progdlg_t *progbar = NULL;
1599 GTimer *prog_timer = g_timer_new();
1601 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1602 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1603 gboolean selected_frame_seen;
1605 GTimeVal start_time;
1606 gchar status_str[100];
1610 gboolean create_proto_tree;
1612 gboolean add_to_packet_list = FALSE;
1614 guint32 frames_count;
1615 gboolean queued_rescan_type = RESCAN_NONE;
1617 /* Rescan in progress, clear pending actions. */
1618 cf->redissection_queued = RESCAN_NONE;
1619 g_assert(!cf->read_lock);
1620 cf->read_lock = TRUE;
1622 /* Compile the current display filter.
1623 * We assume this will not fail since cf->dfilter is only set in
1624 * cf_filter IFF the filter was valid.
1626 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1627 g_assert(!cf->dfilter || (compiled && dfcode));
1629 /* Get the union of the flags for all tap listeners. */
1630 tap_flags = union_of_tap_listener_flags();
1632 /* If any tap listeners require the columns, construct them. */
1633 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1636 * Determine whether we need to create a protocol tree.
1639 * we're going to apply a display filter;
1641 * one of the tap listeners is going to apply a filter;
1643 * one of the tap listeners requires a protocol tree;
1645 * we're redissecting and a postdissector wants field
1646 * values or protocols on the first pass.
1649 (dfcode != NULL || have_filtering_tap_listeners() ||
1650 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1651 (redissect && postdissectors_want_hfids()));
1653 reset_tap_listeners();
1654 /* Which frame, if any, is the currently selected frame?
1655 XXX - should the selected frame or the focus frame be the "current"
1656 frame, that frame being the one from which "Find Frame" searches
1658 selected_frame = cf->current_frame;
1660 /* Mark frame num as not found */
1661 selected_frame_num = -1;
1663 /* Freeze the packet list while we redo it, so we don't get any
1664 screen updates while it happens. */
1665 packet_list_freeze();
1668 /* We need to re-initialize all the state information that protocols
1669 keep, because some preference that controls a dissector has changed,
1670 which might cause the state information to be constructed differently
1671 by that dissector. */
1673 /* We might receive new packets while redissecting, and we don't
1674 want to dissect those before their time. */
1675 cf->redissecting = TRUE;
1677 /* 'reset' dissection session */
1678 epan_free(cf->epan);
1679 if (cf->edt && cf->edt->pi.fd) {
1680 /* All pointers in "per frame proto data" for the currently selected
1681 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1682 Free them here to avoid unintended usage in packet_list_clear(). */
1683 frame_data_destroy(cf->edt->pi.fd);
1685 cf->epan = ws_epan_new(cf);
1686 cf->cinfo.epan = cf->epan;
1688 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1689 called via epan_new() / init_dissection() when reloading Lua plugins. */
1690 if (!create_proto_tree && have_filtering_tap_listeners()) {
1691 create_proto_tree = TRUE;
1694 /* We need to redissect the packets so we have to discard our old
1695 * packet list store. */
1696 packet_list_clear();
1697 add_to_packet_list = TRUE;
1700 /* We don't yet know which will be the first and last frames displayed. */
1701 cf->first_displayed = 0;
1702 cf->last_displayed = 0;
1704 /* We currently don't display any packets */
1705 cf->displayed_count = 0;
1707 /* Iterate through the list of frames. Call a routine for each frame
1708 to check whether it should be displayed and, if so, add it to
1709 the display list. */
1710 cf->provider.ref = NULL;
1711 cf->provider.prev_dis = NULL;
1712 cf->provider.prev_cap = NULL;
1715 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1717 g_timer_start(prog_timer);
1718 /* Count of packets at which we've looked. */
1720 /* Progress so far. */
1723 cf->stop_flag = FALSE;
1724 g_get_current_time(&start_time);
1726 /* no previous row yet */
1727 prev_frame_num = -1;
1730 preceding_frame_num = -1;
1731 preceding_frame = NULL;
1732 following_frame_num = -1;
1733 following_frame = NULL;
1735 selected_frame_seen = FALSE;
1737 frames_count = cf->count;
1739 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1741 for (framenum = 1; framenum <= frames_count; framenum++) {
1742 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1744 /* Create the progress bar if necessary.
1745 We check on every iteration of the loop, so that it takes no
1746 longer than the standard time to create it (otherwise, for a
1747 large file, we might take considerably longer than that standard
1748 time in order to get to the next progress bar step). */
1749 if (progbar == NULL)
1750 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1756 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1757 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1758 * likely trigger UI paint events, which might take a while depending on
1759 * the platform and display. Reset our timer *after* painting.
1761 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1762 /* let's not divide by zero. I should never be started
1763 * with count == 0, so let's assert that
1765 g_assert(cf->count > 0);
1766 progbar_val = (gfloat) count / frames_count;
1768 if (progbar != NULL) {
1769 g_snprintf(status_str, sizeof(status_str),
1770 "%4u of %u frames", count, frames_count);
1771 update_progress_dlg(progbar, progbar_val, status_str);
1774 g_timer_start(prog_timer);
1777 queued_rescan_type = cf->redissection_queued;
1778 if (queued_rescan_type != RESCAN_NONE) {
1779 /* A redissection was requested while an existing redissection was
1784 if (cf->stop_flag) {
1785 /* Well, the user decided to abort the filtering. Just stop.
1787 XXX - go back to the previous filter? Users probably just
1788 want not to wait for a filtering operation to finish;
1789 unless we cancel by having no filter, reverting to the
1790 previous filter will probably be even more expensive than
1791 continuing the filtering, as it involves going back to the
1792 beginning and filtering, and even with no filter we currently
1793 have to re-generate the entire clist, which is also expensive.
1795 I'm not sure what Network Monitor does, but it doesn't appear
1796 to give you an unfiltered display if you cancel. */
1803 /* Since all state for the frame was destroyed, mark the frame
1804 * as not visited, free the GSList referring to the state
1805 * data (the per-frame data itself was freed by
1806 * "init_dissection()"), and null out the GSList pointer. */
1807 frame_data_reset(fdata);
1808 frames_count = cf->count;
1811 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1812 fdata->flags.dependent_of_displayed = 0;
1814 if (!cf_read_record(cf, fdata))
1815 break; /* error reading the frame */
1817 /* If the previous frame is displayed, and we haven't yet seen the
1818 selected frame, remember that frame - it's the closest one we've
1819 yet seen before the selected frame. */
1820 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1821 preceding_frame_num = prev_frame_num;
1822 preceding_frame = prev_frame;
1825 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1827 ws_buffer_start_ptr(&cf->buf),
1828 add_to_packet_list);
1830 /* If this frame is displayed, and this is the first frame we've
1831 seen displayed after the selected frame, remember this frame -
1832 it's the closest one we've yet seen at or after the selected
1834 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1835 following_frame_num = fdata->num;
1836 following_frame = fdata;
1838 if (fdata == selected_frame) {
1839 selected_frame_seen = TRUE;
1840 if (fdata->flags.passed_dfilter)
1841 selected_frame_num = fdata->num;
1844 /* Remember this frame - it'll be the previous frame
1845 on the next pass through the loop. */
1846 prev_frame_num = fdata->num;
1850 epan_dissect_cleanup(&edt);
1852 /* We are done redissecting the packet list. */
1853 cf->redissecting = FALSE;
1856 frames_count = cf->count;
1857 /* Clear out what remains of the visited flags and per-frame data
1860 XXX - that may cause various forms of bogosity when dissecting
1861 these frames, as they won't have been seen by this sequential
1862 pass, but the only alternative I see is to keep scanning them
1863 even though the user requested that the scan stop, and that
1864 would leave the user stuck with an Wireshark grinding on
1865 until it finishes. Should we just stick them with that? */
1866 for (; framenum <= frames_count; framenum++) {
1867 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1868 frame_data_reset(fdata);
1872 /* We're done filtering the packets; destroy the progress bar if it
1874 if (progbar != NULL)
1875 destroy_progress_dlg(progbar);
1876 g_timer_destroy(prog_timer);
1878 /* Unfreeze the packet list. */
1879 if (!add_to_packet_list)
1880 packet_list_recreate_visible_rows();
1882 /* Compute the time it took to filter the file */
1883 compute_elapsed(cf, &start_time);
1887 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1889 if (selected_frame_num == -1) {
1890 /* The selected frame didn't pass the filter. */
1891 if (selected_frame == NULL) {
1892 /* That's because there *was* no selected frame. Make the first
1893 displayed frame the current frame. */
1894 selected_frame_num = 0;
1896 /* Find the nearest displayed frame to the selected frame (whether
1897 it's before or after that frame) and make that the current frame.
1898 If the next and previous displayed frames are equidistant from the
1899 selected frame, choose the next one. */
1900 g_assert(following_frame == NULL ||
1901 following_frame->num >= selected_frame->num);
1902 g_assert(preceding_frame == NULL ||
1903 preceding_frame->num <= selected_frame->num);
1904 if (following_frame == NULL) {
1905 /* No frame after the selected frame passed the filter, so we
1906 have to select the last displayed frame before the selected
1908 selected_frame_num = preceding_frame_num;
1909 selected_frame = preceding_frame;
1910 } else if (preceding_frame == NULL) {
1911 /* No frame before the selected frame passed the filter, so we
1912 have to select the first displayed frame after the selected
1914 selected_frame_num = following_frame_num;
1915 selected_frame = following_frame;
1917 /* Frames before and after the selected frame passed the filter, so
1918 we'll select the previous frame */
1919 selected_frame_num = preceding_frame_num;
1920 selected_frame = preceding_frame;
1925 if (selected_frame_num == -1) {
1926 /* There are no frames displayed at all. */
1927 cf_unselect_packet(cf);
1929 /* Either the frame that was selected passed the filter, or we've
1930 found the nearest displayed frame to that frame. Select it, make
1931 it the focus row, and make it visible. */
1932 /* Set to invalid to force update of packet list and packet details */
1933 cf->current_row = -1;
1934 if (selected_frame_num == 0) {
1935 packet_list_select_first_row();
1937 if (!packet_list_select_row_from_data(selected_frame)) {
1938 /* We didn't find a row corresponding to this frame.
1939 This means that the frame isn't being displayed currently,
1940 so we can't select it. */
1941 simple_message_box(ESD_TYPE_INFO, NULL,
1942 "The capture file is probably not fully dissected.",
1943 "End of capture exceeded.");
1948 /* Cleanup and release all dfilter resources */
1949 dfilter_free(dfcode);
1951 /* It is safe again to execute redissections. */
1952 g_assert(cf->read_lock);
1953 cf->read_lock = FALSE;
1955 /* If another rescan (due to dfilter change) or redissection (due to profile
1956 * change) was requested, the rescan above is aborted and restarted here. */
1957 if (queued_rescan_type != RESCAN_NONE) {
1958 redissect = redissect || queued_rescan_type == RESCAN_REDISSECT;
1959 rescan_packets(cf, "Reprocessing", "all packets", redissect);
1965 * Scan through all frame data and recalculate the ref time
1966 * without rereading the file.
1967 * XXX - do we need a progres bar or is this fast enough?
1970 ref_time_packets(capture_file *cf)
1976 cf->provider.ref = NULL;
1977 cf->provider.prev_dis = NULL;
1980 for (framenum = 1; framenum <= cf->count; framenum++) {
1981 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1983 /* just add some value here until we know if it is being displayed or not */
1984 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1990 /* If we don't have the time stamp of the first packet in the
1991 capture, it's because this is the first packet. Save the time
1992 stamp of this packet as the time stamp of the first packet. */
1993 if (cf->provider.ref == NULL)
1994 cf->provider.ref = fdata;
1995 /* if this frames is marked as a reference time frame, reset
1996 firstsec and firstusec to this frame */
1997 if (fdata->flags.ref_time)
1998 cf->provider.ref = fdata;
2000 /* If we don't have the time stamp of the previous displayed packet,
2001 it's because this is the first displayed packet. Save the time
2002 stamp of this packet as the time stamp of the previous displayed
2004 if (cf->provider.prev_dis == NULL) {
2005 cf->provider.prev_dis = fdata;
2008 /* Get the time elapsed between the first packet and this packet. */
2009 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
2010 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
2012 /* If it's greater than the current elapsed time, set the elapsed time
2013 to it (we check for "greater than" so as not to be confused by
2014 time moving backwards). */
2015 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2016 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2017 cf->elapsed_time = rel_ts;
2020 /* If this frame is displayed, get the time elapsed between the
2021 previous displayed packet and this packet. */
2022 if ( fdata->flags.passed_dfilter ) {
2023 fdata->prev_dis_num = cf->provider.prev_dis->num;
2024 cf->provider.prev_dis = fdata;
2030 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2031 /* This frame either passed the display filter list or is marked as
2032 a time reference frame. All time reference frames are displayed
2033 even if they don't pass the display filter */
2034 if (fdata->flags.ref_time) {
2035 /* if this was a TIME REF frame we should reset the cum_bytes field */
2036 cf->cum_bytes = fdata->pkt_len;
2037 fdata->cum_bytes = cf->cum_bytes;
2039 /* increase cum_bytes with this packets length */
2040 cf->cum_bytes += fdata->pkt_len;
2053 process_specified_records(capture_file *cf, packet_range_t *range,
2054 const char *string1, const char *string2, gboolean terminate_is_stop,
2055 gboolean (*callback)(capture_file *, frame_data *,
2056 wtap_rec *, const guint8 *, void *),
2057 void *callback_args,
2058 gboolean show_progress_bar)
2063 psp_return_t ret = PSP_FINISHED;
2065 progdlg_t *progbar = NULL;
2066 GTimer *prog_timer = g_timer_new();
2069 GTimeVal progbar_start_time;
2070 gchar progbar_status_str[100];
2071 range_process_e process_this;
2074 wtap_rec_init(&rec);
2075 ws_buffer_init(&buf, 1500);
2077 g_timer_start(prog_timer);
2078 /* Count of packets at which we've looked. */
2080 /* Progress so far. */
2083 if (cf->read_lock) {
2084 g_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename);
2087 cf->read_lock = TRUE;
2089 cf->stop_flag = FALSE;
2090 g_get_current_time(&progbar_start_time);
2093 packet_range_process_init(range);
2095 /* Iterate through all the packets, printing the packets that
2096 were selected by the current display filter. */
2097 for (framenum = 1; framenum <= cf->count; framenum++) {
2098 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
2100 /* Create the progress bar if necessary.
2101 We check on every iteration of the loop, so that it takes no
2102 longer than the standard time to create it (otherwise, for a
2103 large file, we might take considerably longer than that standard
2104 time in order to get to the next progress bar step). */
2105 if (show_progress_bar && progbar == NULL)
2106 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2109 &progbar_start_time,
2113 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2114 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2115 * likely trigger UI paint events, which might take a while depending on
2116 * the platform and display. Reset our timer *after* painting.
2118 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2119 /* let's not divide by zero. I should never be started
2120 * with count == 0, so let's assert that
2122 g_assert(cf->count > 0);
2123 progbar_val = (gfloat) progbar_count / cf->count;
2125 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2126 "%4u of %u packets", progbar_count, cf->count);
2127 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2129 g_timer_start(prog_timer);
2132 if (cf->stop_flag) {
2133 /* Well, the user decided to abort the operation. Just stop,
2134 and arrange to return PSP_STOPPED to our caller, so they know
2135 it was stopped explicitly. */
2142 if (range != NULL) {
2143 /* do we have to process this packet? */
2144 process_this = packet_range_process_packet(range, fdata);
2145 if (process_this == range_process_next) {
2146 /* this packet uninteresting, continue with next one */
2148 } else if (process_this == range_processing_finished) {
2149 /* all interesting packets processed, stop the loop */
2154 /* Get the packet */
2155 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2156 /* Attempt to get the packet failed. */
2160 /* Process the packet */
2161 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2162 /* Callback failed. We assume it reported the error appropriately. */
2168 /* We're done printing the packets; destroy the progress bar if
2170 if (progbar != NULL)
2171 destroy_progress_dlg(progbar);
2172 g_timer_destroy(prog_timer);
2174 g_assert(cf->read_lock);
2175 cf->read_lock = FALSE;
2177 wtap_rec_cleanup(&rec);
2178 ws_buffer_free(&buf);
2186 } retap_callback_args_t;
2189 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2190 const guint8 *pd, void *argsp)
2192 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2194 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2195 frame_tvbuff_new(&cf->provider, fdata, pd),
2196 fdata, args->cinfo);
2197 epan_dissect_reset(&args->edt);
2203 cf_retap_packets(capture_file *cf)
2205 packet_range_t range;
2206 retap_callback_args_t callback_args;
2207 gboolean create_proto_tree;
2211 /* Presumably the user closed the capture file. */
2213 return CF_READ_ABORTED;
2216 cf_callback_invoke(cf_cb_file_retap_started, cf);
2218 /* Get the union of the flags for all tap listeners. */
2219 tap_flags = union_of_tap_listener_flags();
2221 /* If any tap listeners require the columns, construct them. */
2222 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2225 * Determine whether we need to create a protocol tree.
2228 * one of the tap listeners is going to apply a filter;
2230 * one of the tap listeners requires a protocol tree.
2233 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2235 /* Reset the tap listeners. */
2236 reset_tap_listeners();
2238 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2240 /* Iterate through the list of packets, dissecting all packets and
2241 re-running the taps. */
2242 packet_range_init(&range, cf);
2243 packet_range_process_init(&range);
2245 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2246 "all packets", TRUE, retap_packet,
2247 &callback_args, TRUE);
2249 packet_range_cleanup(&range);
2250 epan_dissect_cleanup(&callback_args.edt);
2252 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2256 /* Completed successfully. */
2260 /* Well, the user decided to abort the refiltering.
2261 Return CF_READ_ABORTED so our caller knows they did that. */
2262 return CF_READ_ABORTED;
2265 /* Error while retapping. */
2266 return CF_READ_ERROR;
2269 g_assert_not_reached();
2274 print_args_t *print_args;
2275 gboolean print_header_line;
2276 char *header_line_buf;
2277 int header_line_buf_len;
2278 gboolean print_formfeed;
2279 gboolean print_separator;
2283 int num_visible_cols;
2286 } print_callback_args_t;
2289 print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2290 const guint8 *pd, void *argsp)
2292 print_callback_args_t *args = (print_callback_args_t *)argsp;
2298 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2299 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2300 col_item_t* col_item;
2302 /* Fill in the column information if we're printing the summary
2304 if (args->print_args->print_summary) {
2305 col_custom_prime_edt(&args->edt, &cf->cinfo);
2306 epan_dissect_run(&args->edt, cf->cd_t, rec,
2307 frame_tvbuff_new(&cf->provider, fdata, pd),
2309 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2311 epan_dissect_run(&args->edt, cf->cd_t, rec,
2312 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2314 if (args->print_formfeed) {
2315 if (!new_page(args->print_args->stream))
2319 * Print another header line if we print a packet summary on the
2322 if (args->print_args->print_col_headings)
2323 args->print_header_line = TRUE;
2325 if (args->print_separator) {
2326 if (!print_line(args->print_args->stream, 0, ""))
2332 * We generate bookmarks, if the output format supports them.
2333 * The name is "__frameN__".
2335 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2337 if (args->print_args->print_summary) {
2338 if (!args->print_args->print_col_headings)
2339 args->print_header_line = FALSE;
2340 if (args->print_header_line) {
2341 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2343 args->print_header_line = FALSE; /* we might not need to print any more */
2345 cp = &args->line_buf[0];
2347 for (i = 0; i < args->num_visible_cols; i++) {
2348 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2349 /* Find the length of the string for this column. */
2350 column_len = (int) strlen(col_item->col_data);
2351 if (args->col_widths[i] > column_len)
2352 column_len = args->col_widths[i];
2354 /* Make sure there's room in the line buffer for the column; if not,
2355 double its length. */
2356 line_len += column_len + 1; /* "+1" for space */
2357 if (line_len > args->line_buf_len) {
2358 cp_off = (int) (cp - args->line_buf);
2359 args->line_buf_len = 2 * line_len;
2360 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2361 cp = args->line_buf + cp_off;
2364 /* Right-justify the packet number column. */
2365 if (col_item->col_fmt == COL_NUMBER)
2366 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2368 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2370 if (i != args->num_visible_cols - 1)
2376 * Generate a bookmark, using the summary line as the title.
2378 if (!print_bookmark(args->print_args->stream, bookmark_name,
2382 if (!print_line(args->print_args->stream, 0, args->line_buf))
2386 * Generate a bookmark, using "Frame N" as the title, as we're not
2387 * printing the summary line.
2389 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2390 if (!print_bookmark(args->print_args->stream, bookmark_name,
2393 } /* if (print_summary) */
2395 if (args->print_args->print_dissections != print_dissections_none) {
2396 if (args->print_args->print_summary) {
2397 /* Separate the summary line from the tree with a blank line. */
2398 if (!print_line(args->print_args->stream, 0, ""))
2402 /* Print the information in that tree. */
2403 if (!proto_tree_print(args->print_args->print_dissections,
2404 args->print_args->print_hex, &args->edt, NULL,
2405 args->print_args->stream))
2408 /* Print a blank line if we print anything after this (aka more than one packet). */
2409 args->print_separator = TRUE;
2411 /* Print a header line if we print any more packet summaries */
2412 if (args->print_args->print_col_headings)
2413 args->print_header_line = TRUE;
2416 if (args->print_args->print_hex) {
2417 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2418 if (!print_line(args->print_args->stream, 0, ""))
2421 /* Print the full packet data as hex. */
2422 if (!print_hex_data(args->print_args->stream, &args->edt))
2425 /* Print a blank line if we print anything after this (aka more than one packet). */
2426 args->print_separator = TRUE;
2428 /* Print a header line if we print any more packet summaries */
2429 if (args->print_args->print_col_headings)
2430 args->print_header_line = TRUE;
2431 } /* if (args->print_args->print_dissections != print_dissections_none) */
2433 epan_dissect_reset(&args->edt);
2435 /* do we want to have a formfeed between each packet from now on? */
2436 if (args->print_args->print_formfeed) {
2437 args->print_formfeed = TRUE;
2443 epan_dissect_reset(&args->edt);
2448 cf_print_packets(capture_file *cf, print_args_t *print_args,
2449 gboolean show_progress_bar)
2451 print_callback_args_t callback_args;
2454 int i, cp_off, column_len, line_len;
2455 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2459 gboolean proto_tree_needed;
2461 callback_args.print_args = print_args;
2462 callback_args.print_header_line = print_args->print_col_headings;
2463 callback_args.header_line_buf = NULL;
2464 callback_args.header_line_buf_len = 256;
2465 callback_args.print_formfeed = FALSE;
2466 callback_args.print_separator = FALSE;
2467 callback_args.line_buf = NULL;
2468 callback_args.line_buf_len = 256;
2469 callback_args.col_widths = NULL;
2470 callback_args.num_visible_cols = 0;
2471 callback_args.visible_cols = NULL;
2473 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2474 destroy_print_stream(print_args->stream);
2475 return CF_PRINT_WRITE_ERROR;
2478 if (print_args->print_summary) {
2479 /* We're printing packet summaries. Allocate the header line buffer
2480 and get the column widths. */
2481 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2483 /* Find the number of visible columns and the last visible column */
2484 for (i = 0; i < prefs.num_cols; i++) {
2486 clp = g_list_nth(prefs.col_list, i);
2487 if (clp == NULL) /* Sanity check, Invalid column requested */
2490 cfmt = (fmt_data *) clp->data;
2491 if (cfmt->visible) {
2493 last_visible_col = i;
2497 /* if num_visible_col is 0, we are done */
2498 if (num_visible_col == 0) {
2499 g_free(callback_args.header_line_buf);
2503 /* Find the widths for each of the columns - maximum of the
2504 width of the title and the width of the data - and construct
2505 a buffer with a line containing the column titles. */
2506 callback_args.num_visible_cols = num_visible_col;
2507 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2508 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2509 cp = &callback_args.header_line_buf[0];
2511 visible_col_count = 0;
2512 for (i = 0; i < cf->cinfo.num_cols; i++) {
2514 clp = g_list_nth(prefs.col_list, i);
2515 if (clp == NULL) /* Sanity check, Invalid column requested */
2518 cfmt = (fmt_data *) clp->data;
2519 if (cfmt->visible == FALSE)
2522 /* Save the order of visible columns */
2523 callback_args.visible_cols[visible_col_count] = i;
2525 /* Don't pad the last column. */
2526 if (i == last_visible_col)
2527 callback_args.col_widths[visible_col_count] = 0;
2529 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2530 data_width = get_column_char_width(get_column_format(i));
2531 if (data_width > callback_args.col_widths[visible_col_count])
2532 callback_args.col_widths[visible_col_count] = data_width;
2535 /* Find the length of the string for this column. */
2536 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2537 if (callback_args.col_widths[visible_col_count] > column_len)
2538 column_len = callback_args.col_widths[visible_col_count];
2540 /* Make sure there's room in the line buffer for the column; if not,
2541 double its length. */
2542 line_len += column_len + 1; /* "+1" for space */
2543 if (line_len > callback_args.header_line_buf_len) {
2544 cp_off = (int) (cp - callback_args.header_line_buf);
2545 callback_args.header_line_buf_len = 2 * line_len;
2546 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2547 callback_args.header_line_buf_len + 1);
2548 cp = callback_args.header_line_buf + cp_off;
2551 /* Right-justify the packet number column. */
2552 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2553 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2555 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2557 if (i != cf->cinfo.num_cols - 1)
2560 visible_col_count++;
2564 /* Now start out the main line buffer with the same length as the
2565 header line buffer. */
2566 callback_args.line_buf_len = callback_args.header_line_buf_len;
2567 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2568 } /* if (print_summary) */
2570 /* Create the protocol tree, and make it visible, if we're printing
2571 the dissection or the hex data.
2572 XXX - do we need it if we're just printing the hex data? */
2574 callback_args.print_args->print_dissections != print_dissections_none ||
2575 callback_args.print_args->print_hex ||
2576 have_custom_cols(&cf->cinfo) || have_field_extractors();
2577 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2579 /* Iterate through the list of packets, printing the packets we were
2581 ret = process_specified_records(cf, &print_args->range, "Printing",
2582 "selected packets", TRUE, print_packet,
2583 &callback_args, show_progress_bar);
2584 epan_dissect_cleanup(&callback_args.edt);
2585 g_free(callback_args.header_line_buf);
2586 g_free(callback_args.line_buf);
2587 g_free(callback_args.col_widths);
2588 g_free(callback_args.visible_cols);
2593 /* Completed successfully. */
2597 /* Well, the user decided to abort the printing.
2599 XXX - note that what got generated before they did that
2600 will get printed if we're piping to a print program; we'd
2601 have to write to a file and then hand that to the print
2602 program to make it actually not print anything. */
2606 /* Error while printing.
2608 XXX - note that what got generated before they did that
2609 will get printed if we're piping to a print program; we'd
2610 have to write to a file and then hand that to the print
2611 program to make it actually not print anything. */
2612 destroy_print_stream(print_args->stream);
2613 return CF_PRINT_WRITE_ERROR;
2616 if (!print_finale(print_args->stream)) {
2617 destroy_print_stream(print_args->stream);
2618 return CF_PRINT_WRITE_ERROR;
2621 if (!destroy_print_stream(print_args->stream))
2622 return CF_PRINT_WRITE_ERROR;
2630 print_args_t *print_args;
2631 } write_packet_callback_args_t;
2634 write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2635 const guint8 *pd, void *argsp)
2637 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2639 /* Create the protocol tree, but don't fill in the column information. */
2640 epan_dissect_run(&args->edt, cf->cd_t, rec,
2641 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2643 /* Write out the information in that tree. */
2644 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE);
2646 epan_dissect_reset(&args->edt);
2648 return !ferror(args->fh);
2652 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2654 write_packet_callback_args_t callback_args;
2658 fh = ws_fopen(print_args->file, "w");
2660 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2662 write_pdml_preamble(fh, cf->filename);
2665 return CF_PRINT_WRITE_ERROR;
2668 callback_args.fh = fh;
2669 callback_args.print_args = print_args;
2670 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2672 /* Iterate through the list of packets, printing the packets we were
2674 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2675 "selected packets", TRUE,
2676 write_pdml_packet, &callback_args, TRUE);
2678 epan_dissect_cleanup(&callback_args.edt);
2683 /* Completed successfully. */
2687 /* Well, the user decided to abort the printing. */
2691 /* Error while printing. */
2693 return CF_PRINT_WRITE_ERROR;
2696 write_pdml_finale(fh);
2699 return CF_PRINT_WRITE_ERROR;
2702 /* XXX - check for an error */
2709 write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2710 const guint8 *pd, void *argsp)
2712 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2714 /* Fill in the column information */
2715 col_custom_prime_edt(&args->edt, &cf->cinfo);
2716 epan_dissect_run(&args->edt, cf->cd_t, rec,
2717 frame_tvbuff_new(&cf->provider, fdata, pd),
2719 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2721 /* Write out the column information. */
2722 write_psml_columns(&args->edt, args->fh, FALSE);
2724 epan_dissect_reset(&args->edt);
2726 return !ferror(args->fh);
2730 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2732 write_packet_callback_args_t callback_args;
2736 gboolean proto_tree_needed;
2738 fh = ws_fopen(print_args->file, "w");
2740 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2742 write_psml_preamble(&cf->cinfo, fh);
2745 return CF_PRINT_WRITE_ERROR;
2748 callback_args.fh = fh;
2749 callback_args.print_args = print_args;
2751 /* Fill in the column information, only create the protocol tree
2752 if having custom columns or field extractors. */
2753 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2754 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2756 /* Iterate through the list of packets, printing the packets we were
2758 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2759 "selected packets", TRUE,
2760 write_psml_packet, &callback_args, TRUE);
2762 epan_dissect_cleanup(&callback_args.edt);
2767 /* Completed successfully. */
2771 /* Well, the user decided to abort the printing. */
2775 /* Error while printing. */
2777 return CF_PRINT_WRITE_ERROR;
2780 write_psml_finale(fh);
2783 return CF_PRINT_WRITE_ERROR;
2786 /* XXX - check for an error */
2793 write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2794 const guint8 *pd, void *argsp)
2796 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2798 /* Fill in the column information */
2799 col_custom_prime_edt(&args->edt, &cf->cinfo);
2800 epan_dissect_run(&args->edt, cf->cd_t, rec,
2801 frame_tvbuff_new(&cf->provider, fdata, pd),
2803 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2805 /* Write out the column information. */
2806 write_csv_columns(&args->edt, args->fh);
2808 epan_dissect_reset(&args->edt);
2810 return !ferror(args->fh);
2814 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2816 write_packet_callback_args_t callback_args;
2817 gboolean proto_tree_needed;
2821 fh = ws_fopen(print_args->file, "w");
2823 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2825 write_csv_column_titles(&cf->cinfo, fh);
2828 return CF_PRINT_WRITE_ERROR;
2831 callback_args.fh = fh;
2832 callback_args.print_args = print_args;
2834 /* only create the protocol tree if having custom columns or field extractors. */
2835 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2836 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2838 /* Iterate through the list of packets, printing the packets we were
2840 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2841 "selected packets", TRUE,
2842 write_csv_packet, &callback_args, TRUE);
2844 epan_dissect_cleanup(&callback_args.edt);
2849 /* Completed successfully. */
2853 /* Well, the user decided to abort the printing. */
2857 /* Error while printing. */
2859 return CF_PRINT_WRITE_ERROR;
2862 /* XXX - check for an error */
2869 carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2870 const guint8 *pd, void *argsp)
2872 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2874 epan_dissect_run(&args->edt, cf->cd_t, rec,
2875 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2876 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2877 epan_dissect_reset(&args->edt);
2879 return !ferror(args->fh);
2883 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2885 write_packet_callback_args_t callback_args;
2889 fh = ws_fopen(print_args->file, "w");
2892 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2896 return CF_PRINT_WRITE_ERROR;
2899 callback_args.fh = fh;
2900 callback_args.print_args = print_args;
2901 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2903 /* Iterate through the list of packets, printing the packets we were
2905 ret = process_specified_records(cf, &print_args->range,
2907 "selected packets", TRUE,
2908 carrays_write_packet, &callback_args, TRUE);
2910 epan_dissect_cleanup(&callback_args.edt);
2914 /* Completed successfully. */
2917 /* Well, the user decided to abort the printing. */
2920 /* Error while printing. */
2922 return CF_PRINT_WRITE_ERROR;
2930 write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2931 const guint8 *pd, void *argsp)
2933 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2935 /* Create the protocol tree, but don't fill in the column information. */
2936 epan_dissect_run(&args->edt, cf->cd_t, rec,
2937 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2939 /* Write out the information in that tree. */
2940 write_json_proto_tree(NULL, args->print_args->print_dissections,
2941 args->print_args->print_hex, NULL, PF_NONE,
2942 &args->edt, &cf->cinfo, proto_node_group_children_by_unique, args->fh);
2944 epan_dissect_reset(&args->edt);
2946 return !ferror(args->fh);
2950 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2952 write_packet_callback_args_t callback_args;
2956 fh = ws_fopen(print_args->file, "w");
2958 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2960 write_json_preamble(fh);
2963 return CF_PRINT_WRITE_ERROR;
2966 callback_args.fh = fh;
2967 callback_args.print_args = print_args;
2968 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2970 /* Iterate through the list of packets, printing the packets we were
2972 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2973 "selected packets", TRUE,
2974 write_json_packet, &callback_args, TRUE);
2976 epan_dissect_cleanup(&callback_args.edt);
2981 /* Completed successfully. */
2985 /* Well, the user decided to abort the printing. */
2989 /* Error while printing. */
2991 return CF_PRINT_WRITE_ERROR;
2994 write_json_finale(fh);
2997 return CF_PRINT_WRITE_ERROR;
3000 /* XXX - check for an error */
3007 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3008 search_direction dir)
3012 mdata.string = string;
3013 mdata.string_len = strlen(string);
3014 return find_packet(cf, match_protocol_tree, &mdata, dir);
3018 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3020 mdata->frame_matched = FALSE;
3021 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3022 mdata->string_len = strlen(mdata->string);
3024 /* Iterate through all the nodes looking for matching text */
3025 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3026 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3030 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3032 match_data *mdata = (match_data *)criterion;
3035 /* Load the frame's data. */
3036 if (!cf_read_record(cf, fdata)) {
3037 /* Attempt to get the packet failed. */
3041 /* Construct the protocol tree, including the displayed text */
3042 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3043 /* We don't need the column information */
3044 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3045 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3048 /* Iterate through all the nodes, seeing if they have text that matches. */
3050 mdata->frame_matched = FALSE;
3051 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3052 epan_dissect_cleanup(&edt);
3053 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3057 match_subtree_text(proto_node *node, gpointer data)
3059 match_data *mdata = (match_data *) data;
3060 const gchar *string = mdata->string;
3061 size_t string_len = mdata->string_len;
3062 capture_file *cf = mdata->cf;
3063 field_info *fi = PNODE_FINFO(node);
3064 gchar label_str[ITEM_LABEL_LENGTH];
3071 /* dissection with an invisible proto tree? */
3074 if (mdata->frame_matched) {
3075 /* We already had a match; don't bother doing any more work. */
3079 /* Don't match invisible entries. */
3080 if (PROTO_ITEM_IS_HIDDEN(node))
3083 /* was a free format label produced? */
3085 label_ptr = fi->rep->representation;
3087 /* no, make a generic label */
3088 label_ptr = label_str;
3089 proto_item_fill_label(fi, label_str);
3093 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3094 mdata->frame_matched = TRUE;
3099 /* Does that label match? */
3100 label_len = strlen(label_ptr);
3101 for (i = 0; i < label_len; i++) {
3102 c_char = label_ptr[i];
3104 c_char = g_ascii_toupper(c_char);
3105 if (c_char == string[c_match]) {
3107 if (c_match == string_len) {
3108 /* No need to look further; we have a match */
3109 mdata->frame_matched = TRUE;
3118 /* Recurse into the subtree, if it exists */
3119 if (node->first_child != NULL)
3120 proto_tree_children_foreach(node, match_subtree_text, mdata);
3124 cf_find_packet_summary_line(capture_file *cf, const char *string,
3125 search_direction dir)
3129 mdata.string = string;
3130 mdata.string_len = strlen(string);
3131 return find_packet(cf, match_summary_line, &mdata, dir);
3135 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3137 match_data *mdata = (match_data *)criterion;
3138 const gchar *string = mdata->string;
3139 size_t string_len = mdata->string_len;
3141 const char *info_column;
3142 size_t info_column_len;
3143 match_result result = MR_NOTMATCHED;
3149 /* Load the frame's data. */
3150 if (!cf_read_record(cf, fdata)) {
3151 /* Attempt to get the packet failed. */
3155 /* Don't bother constructing the protocol tree */
3156 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3157 /* Get the column information */
3158 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3159 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3162 /* Find the Info column */
3163 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3164 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3165 /* Found it. See if we match. */
3166 info_column = edt.pi.cinfo->columns[colx].col_data;
3167 info_column_len = strlen(info_column);
3169 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3170 result = MR_MATCHED;
3174 for (i = 0; i < info_column_len; i++) {
3175 c_char = info_column[i];
3177 c_char = g_ascii_toupper(c_char);
3178 if (c_char == string[c_match]) {
3180 if (c_match == string_len) {
3181 result = MR_MATCHED;
3191 epan_dissect_cleanup(&edt);
3198 } cbs_t; /* "Counted byte string" */
3202 * The current match_* routines only support ASCII case insensitivity and don't
3203 * convert UTF-8 inputs to UTF-16 for matching.
3205 * We could modify them to use the GLib Unicode routines or the International
3206 * Components for Unicode library but it's not apparent that we could do so
3207 * without consuming a lot more CPU and memory or that searching would be
3208 * significantly better.
3212 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3213 search_direction dir)
3218 info.data_len = string_size;
3220 /* Regex, String or hex search? */
3222 /* Regular Expression search */
3223 return find_packet(cf, match_regex, NULL, dir);
3224 } else if (cf->string) {
3225 /* String search - what type of string? */
3226 switch (cf->scs_type) {
3228 case SCS_NARROW_AND_WIDE:
3229 return find_packet(cf, match_narrow_and_wide, &info, dir);
3232 return find_packet(cf, match_narrow, &info, dir);
3235 return find_packet(cf, match_wide, &info, dir);
3238 g_assert_not_reached();
3242 return find_packet(cf, match_binary, &info, dir);
3246 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3248 cbs_t *info = (cbs_t *)criterion;
3249 const guint8 *ascii_text = info->data;
3250 size_t textlen = info->data_len;
3251 match_result result;
3258 /* Load the frame's data. */
3259 if (!cf_read_record(cf, fdata)) {
3260 /* Attempt to get the packet failed. */
3264 result = MR_NOTMATCHED;
3265 buf_len = fdata->cap_len;
3266 pd = ws_buffer_start_ptr(&cf->buf);
3268 while (i < buf_len) {
3271 c_char = g_ascii_toupper(c_char);
3272 if (c_char != '\0') {
3273 if (c_char == ascii_text[c_match]) {
3275 if (c_match == textlen) {
3276 result = MR_MATCHED;
3277 cf->search_pos = i; /* Save the position of the last character
3278 for highlighting the field. */
3279 cf->search_len = (guint32)textlen;
3284 g_assert(i>=c_match);
3285 i -= (guint32)c_match;
3295 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3298 cbs_t *info = (cbs_t *)criterion;
3299 const guint8 *ascii_text = info->data;
3300 size_t textlen = info->data_len;
3301 match_result result;
3307 /* Load the frame's data. */
3308 if (!cf_read_record(cf, fdata)) {
3309 /* Attempt to get the packet failed. */
3313 result = MR_NOTMATCHED;
3314 buf_len = fdata->cap_len;
3315 pd = ws_buffer_start_ptr(&cf->buf);
3317 while (i < buf_len) {
3320 c_char = g_ascii_toupper(c_char);
3321 if (c_char == ascii_text[c_match]) {
3323 if (c_match == textlen) {
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)textlen;
3332 g_assert(i>=c_match);
3333 i -= (guint32)c_match;
3343 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3345 cbs_t *info = (cbs_t *)criterion;
3346 const guint8 *ascii_text = info->data;
3347 size_t textlen = info->data_len;
3348 match_result result;
3355 /* Load the frame's data. */
3356 if (!cf_read_record(cf, fdata)) {
3357 /* Attempt to get the packet failed. */
3361 result = MR_NOTMATCHED;
3362 buf_len = fdata->cap_len;
3363 pd = ws_buffer_start_ptr(&cf->buf);
3365 while (i < buf_len) {
3368 c_char = g_ascii_toupper(c_char);
3369 if (c_char == ascii_text[c_match]) {
3371 if (c_match == textlen) {
3372 result = MR_MATCHED;
3373 cf->search_pos = i; /* Save the position of the last character
3374 for highlighting the field. */
3375 cf->search_len = (guint32)textlen;
3381 g_assert(i>=(c_match*2));
3382 i -= (guint32)c_match*2;
3391 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3393 cbs_t *info = (cbs_t *)criterion;
3394 const guint8 *binary_data = info->data;
3395 size_t datalen = info->data_len;
3396 match_result result;
3402 /* Load the frame's data. */
3403 if (!cf_read_record(cf, fdata)) {
3404 /* Attempt to get the packet failed. */
3408 result = MR_NOTMATCHED;
3409 buf_len = fdata->cap_len;
3410 pd = ws_buffer_start_ptr(&cf->buf);
3412 while (i < buf_len) {
3413 if (pd[i] == binary_data[c_match]) {
3415 if (c_match == datalen) {
3416 result = MR_MATCHED;
3417 cf->search_pos = i; /* Save the position of the last character
3418 for highlighting the field. */
3419 cf->search_len = (guint32)datalen;
3424 g_assert(i>=c_match);
3425 i -= (guint32)c_match;
3434 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3436 match_result result = MR_NOTMATCHED;
3437 GMatchInfo *match_info = NULL;
3439 /* Load the frame's data. */
3440 if (!cf_read_record(cf, fdata)) {
3441 /* Attempt to get the packet failed. */
3445 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3446 0, (GRegexMatchFlags) 0, &match_info, NULL))
3448 gint start_pos = 0, end_pos = 0;
3449 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3450 cf->search_pos = end_pos - 1;
3451 cf->search_len = end_pos - start_pos;
3452 result = MR_MATCHED;
3458 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3459 search_direction dir)
3461 return find_packet(cf, match_dfilter, sfcode, dir);
3465 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3466 search_direction dir)
3471 if (!dfilter_compile(filter, &sfcode, NULL)) {
3473 * XXX - this shouldn't happen, as the filter string is machine
3478 if (sfcode == NULL) {
3480 * XXX - this shouldn't happen, as the filter string is machine
3485 result = find_packet(cf, match_dfilter, sfcode, dir);
3486 dfilter_free(sfcode);
3491 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3493 dfilter_t *sfcode = (dfilter_t *)criterion;
3495 match_result result;
3497 /* Load the frame's data. */
3498 if (!cf_read_record(cf, fdata)) {
3499 /* Attempt to get the packet failed. */
3503 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3504 epan_dissect_prime_with_dfilter(&edt, sfcode);
3505 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3506 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3508 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3509 epan_dissect_cleanup(&edt);
3514 cf_find_packet_marked(capture_file *cf, search_direction dir)
3516 return find_packet(cf, match_marked, NULL, dir);
3520 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3522 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3526 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3528 return find_packet(cf, match_time_reference, NULL, dir);
3532 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3534 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3538 find_packet(capture_file *cf,
3539 match_result (*match_function)(capture_file *, frame_data *, void *),
3540 void *criterion, search_direction dir)
3542 frame_data *start_fd;
3544 guint32 prev_framenum;
3546 frame_data *new_fd = NULL;
3547 progdlg_t *progbar = NULL;
3548 GTimer *prog_timer = g_timer_new();
3552 GTimeVal start_time;
3553 gchar status_str[100];
3555 match_result result;
3557 start_fd = cf->current_frame;
3558 if (start_fd != NULL) {
3559 prev_framenum = start_fd->num;
3561 prev_framenum = 0; /* No start packet selected. */
3564 /* Iterate through the list of packets, starting at the packet we've
3565 picked, calling a routine to run the filter on the packet, see if
3566 it matches, and stop if so. */
3568 framenum = prev_framenum;
3570 g_timer_start(prog_timer);
3571 /* Progress so far. */
3574 cf->stop_flag = FALSE;
3575 g_get_current_time(&start_time);
3577 title = cf->sfilter?cf->sfilter:"";
3579 /* Create the progress bar if necessary.
3580 We check on every iteration of the loop, so that it takes no
3581 longer than the standard time to create it (otherwise, for a
3582 large file, we might take considerably longer than that standard
3583 time in order to get to the next progress bar step). */
3584 if (progbar == NULL)
3585 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3586 FALSE, &cf->stop_flag, &start_time, progbar_val);
3589 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3590 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3591 * likely trigger UI paint events, which might take a while depending on
3592 * the platform and display. Reset our timer *after* painting.
3594 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3595 /* let's not divide by zero. I should never be started
3596 * with count == 0, so let's assert that
3598 g_assert(cf->count > 0);
3600 progbar_val = (gfloat) count / cf->count;
3602 g_snprintf(status_str, sizeof(status_str),
3603 "%4u of %u packets", count, cf->count);
3604 update_progress_dlg(progbar, progbar_val, status_str);
3606 g_timer_start(prog_timer);
3609 if (cf->stop_flag) {
3610 /* Well, the user decided to abort the search. Go back to the
3611 frame where we started. */
3616 /* Go past the current frame. */
3617 if (dir == SD_BACKWARD) {
3618 /* Go on to the previous frame. */
3619 if (framenum <= 1) {
3621 * XXX - other apps have a bit more of a detailed message
3622 * for this, and instead of offering "OK" and "Cancel",
3623 * they offer things such as "Continue" and "Cancel";
3624 * we need an API for popping up alert boxes with
3625 * {Verb} and "Cancel".
3628 if (prefs.gui_find_wrap) {
3629 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3630 framenum = cf->count; /* wrap around */
3632 statusbar_push_temporary_msg("Search reached the beginning.");
3633 framenum = prev_framenum; /* stay on previous packet */
3638 /* Go on to the next frame. */
3639 if (framenum == cf->count) {
3640 if (prefs.gui_find_wrap) {
3641 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3642 framenum = 1; /* wrap around */
3644 statusbar_push_temporary_msg("Search reached the end.");
3645 framenum = prev_framenum; /* stay on previous packet */
3651 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3654 /* Is this packet in the display? */
3655 if (fdata && fdata->flags.passed_dfilter) {
3656 /* Yes. Does it match the search criterion? */
3657 result = (*match_function)(cf, fdata, criterion);
3658 if (result == MR_ERROR) {
3659 /* Error; our caller has reported the error. Go back to the frame
3660 where we started. */
3663 } else if (result == MR_MATCHED) {
3664 /* Yes. Go to the new frame. */
3670 if (fdata == start_fd) {
3671 /* We're back to the frame we were on originally, and that frame
3672 doesn't match the search filter. The search failed. */
3677 /* We're done scanning the packets; destroy the progress bar if it
3679 if (progbar != NULL)
3680 destroy_progress_dlg(progbar);
3681 g_timer_destroy(prog_timer);
3683 if (new_fd != NULL) {
3684 /* Find and select */
3685 cf->search_in_progress = TRUE;
3686 found = packet_list_select_row_from_data(new_fd);
3687 cf->search_in_progress = FALSE;
3688 cf->search_pos = 0; /* Reset the position */
3689 cf->search_len = 0; /* Reset length */
3691 /* We didn't find a row corresponding to this frame.
3692 This means that the frame isn't being displayed currently,
3693 so we can't select it. */
3694 simple_message_box(ESD_TYPE_INFO, NULL,
3695 "The capture file is probably not fully dissected.",
3696 "End of capture exceeded.");
3699 return TRUE; /* success */
3701 return FALSE; /* failure */
3705 cf_goto_frame(capture_file *cf, guint fnumber)
3709 if (cf == NULL || cf->provider.frames == NULL) {
3710 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3711 statusbar_push_temporary_msg("There is no file loaded");
3712 return FALSE; /* we failed to go to that packet */
3715 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3717 if (fdata == NULL) {
3718 /* we didn't find a packet with that packet number */
3719 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3720 return FALSE; /* we failed to go to that packet */
3722 if (!fdata->flags.passed_dfilter) {
3723 /* that packet currently isn't displayed */
3724 /* XXX - add it to the set of displayed packets? */
3725 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3726 return FALSE; /* we failed to go to that packet */
3729 if (!packet_list_select_row_from_data(fdata)) {
3730 /* We didn't find a row corresponding to this frame.
3731 This means that the frame isn't being displayed currently,
3732 so we can't select it. */
3733 simple_message_box(ESD_TYPE_INFO, NULL,
3734 "The capture file is probably not fully dissected.",
3735 "End of capture exceeded.");
3738 return TRUE; /* we got to that packet */
3742 * Go to frame specified by currently selected protocol tree item.
3745 cf_goto_framenum(capture_file *cf)
3747 header_field_info *hfinfo;
3750 if (cf->finfo_selected) {
3751 hfinfo = cf->finfo_selected->hfinfo;
3753 if (hfinfo->type == FT_FRAMENUM) {
3754 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3756 return cf_goto_frame(cf, framenum);
3763 /* Select the packet on a given row. */
3765 cf_select_packet(capture_file *cf, int row)
3767 epan_dissect_t *old_edt;
3770 /* Get the frame data struct pointer for this frame */
3771 fdata = packet_list_get_row_data(row);
3773 if (fdata == NULL) {
3777 /* Get the data in that frame. */
3778 if (!cf_read_record (cf, fdata)) {
3782 /* Record that this frame is the current frame. */
3783 cf->current_frame = fdata;
3784 cf->current_row = row;
3787 /* Create the logical protocol tree. */
3788 /* We don't need the columns here. */
3789 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3791 tap_build_interesting(cf->edt);
3792 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3793 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3794 cf->current_frame, NULL);
3796 dfilter_macro_build_ftv_cache(cf->edt->tree);
3798 if (old_edt != NULL)
3799 epan_dissect_free(old_edt);
3803 /* Unselect the selected packet, if any. */
3805 cf_unselect_packet(capture_file *cf)
3807 epan_dissect_t *old_edt = cf->edt;
3811 /* No packet is selected. */
3812 cf->current_frame = NULL;
3813 cf->current_row = 0;
3815 /* Destroy the epan_dissect_t for the unselected packet. */
3816 if (old_edt != NULL)
3817 epan_dissect_free(old_edt);
3821 * Mark a particular frame.
3824 cf_mark_frame(capture_file *cf, frame_data *frame)
3826 if (! frame->flags.marked) {
3827 frame->flags.marked = TRUE;
3828 if (cf->count > cf->marked_count)
3834 * Unmark a particular frame.
3837 cf_unmark_frame(capture_file *cf, frame_data *frame)
3839 if (frame->flags.marked) {
3840 frame->flags.marked = FALSE;
3841 if (cf->marked_count > 0)
3847 * Ignore a particular frame.
3850 cf_ignore_frame(capture_file *cf, frame_data *frame)
3852 if (! frame->flags.ignored) {
3853 frame->flags.ignored = TRUE;
3854 if (cf->count > cf->ignored_count)
3855 cf->ignored_count++;
3860 * Un-ignore a particular frame.
3863 cf_unignore_frame(capture_file *cf, frame_data *frame)
3865 if (frame->flags.ignored) {
3866 frame->flags.ignored = FALSE;
3867 if (cf->ignored_count > 0)
3868 cf->ignored_count--;
3873 * Read the section comment.
3876 cf_read_section_comment(capture_file *cf)
3878 wtap_block_t shb_inf;
3882 /* XXX - support multiple SHBs */
3883 shb_inf = wtap_file_get_shb(cf->provider.wth);
3885 /* Get the first comment from the SHB. */
3886 /* XXX - support multiple comments */
3887 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3893 * Modify the section comment.
3896 cf_update_section_comment(capture_file *cf, gchar *comment)
3898 wtap_block_t shb_inf;
3902 /* XXX - support multiple SHBs */
3903 shb_inf = wtap_file_get_shb(cf->provider.wth);
3905 /* Get the first comment from the SHB. */
3906 /* XXX - support multiple comments */
3907 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3908 /* There's no comment - add one. */
3909 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3911 /* See if the comment has changed or not */
3912 if (strcmp(shb_comment, comment) == 0) {
3917 /* The comment has changed, let's update it */
3918 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3920 /* Mark the file as having unsaved changes */
3921 cf->unsaved_changes = TRUE;
3925 * Get the comment on a packet (record).
3926 * If the comment has been edited, it returns the result of the edit,
3927 * otherwise it returns the comment from the file.
3930 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3934 /* fetch user comment */
3935 if (fd->flags.has_user_comment)
3936 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3938 /* fetch phdr comment */
3939 if (fd->flags.has_phdr_comment) {
3940 wtap_rec rec; /* Record metadata */
3941 Buffer buf; /* Record data */
3943 wtap_rec_init(&rec);
3944 ws_buffer_init(&buf, 1500);
3946 if (!cf_read_record_r(cf, fd, &rec, &buf))
3947 { /* XXX, what we can do here? */ }
3949 comment = rec.opt_comment;
3950 wtap_rec_cleanup(&rec);
3951 ws_buffer_free(&buf);
3958 * Update(replace) the comment on a capture from a frame
3961 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3963 char *pkt_comment = cf_get_packet_comment(cf, fd);
3965 /* Check if the comment has changed */
3966 if (!g_strcmp0(pkt_comment, new_comment)) {
3967 g_free(pkt_comment);
3970 g_free(pkt_comment);
3973 cf->packet_comment_count--;
3976 cf->packet_comment_count++;
3978 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3980 expert_update_comment_count(cf->packet_comment_count);
3982 /* OK, we have unsaved changes. */
3983 cf->unsaved_changes = TRUE;
3988 * What types of comments does this capture file have?
3991 cf_comment_types(capture_file *cf)
3993 guint32 comment_types = 0;
3995 if (cf_read_section_comment(cf) != NULL)
3996 comment_types |= WTAP_COMMENT_PER_SECTION;
3997 if (cf->packet_comment_count != 0)
3998 comment_types |= WTAP_COMMENT_PER_PACKET;
3999 return comment_types;
4003 * Add a resolved address to this file's list of resolved addresses.
4006 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
4009 * XXX - support multiple resolved address lists, and add to the one
4010 * attached to this file?
4012 if (!add_ip_name_from_string(addr, name))
4015 /* OK, we have unsaved changes. */
4016 cf->unsaved_changes = TRUE;
4024 } save_callback_args_t;
4027 * Save a capture to a file, in a particular format, saving either
4028 * all packets, all currently-displayed packets, or all marked packets.
4030 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4031 * up a message box for the failure.
4034 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
4035 const guint8 *pd, void *argsp)
4037 save_callback_args_t *args = (save_callback_args_t *)argsp;
4041 const char *pkt_comment;
4043 /* Copy the record information from what was read in from the file. */
4046 /* Make changes based on anything that the user has done but that
4047 hasn't been saved yet. */
4048 if (fdata->flags.has_user_comment)
4049 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
4051 pkt_comment = rec->opt_comment;
4052 new_rec.opt_comment = g_strdup(pkt_comment);
4053 new_rec.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
4054 /* XXX - what if times have been shifted? */
4056 /* and save the packet */
4057 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
4058 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4063 g_free(new_rec.opt_comment);
4068 * Can this capture file be written out in any format using Wiretap
4069 * rather than by copying the raw data?
4072 cf_can_write_with_wiretap(capture_file *cf)
4074 /* We don't care whether we support the comments in this file or not;
4075 if we can't, we'll offer the user the option of discarding the
4077 return wtap_dump_can_write(cf->linktypes, 0);
4081 * Should we let the user do a save?
4085 * the file has unsaved changes, and we can save it in some
4086 * format through Wiretap
4090 * the file is a temporary file and has no unsaved changes (so
4091 * that "saving" it just means copying it).
4093 * XXX - we shouldn't allow files to be edited if they can't be saved,
4094 * so cf->unsaved_changes should be true only if the file can be saved.
4096 * We don't care whether we support the comments in this file or not;
4097 * if we can't, we'll offer the user the option of discarding the
4101 cf_can_save(capture_file *cf)
4103 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4104 /* Saved changes, and we can write it out with Wiretap. */
4108 if (cf->is_tempfile && !cf->unsaved_changes) {
4110 * Temporary file with no unsaved changes, so we can just do a
4116 /* Nothing to save. */
4121 * Should we let the user do a "save as"?
4125 * we can save it in some format through Wiretap
4129 * the file is a temporary file and has no unsaved changes (so
4130 * that "saving" it just means copying it).
4132 * XXX - we shouldn't allow files to be edited if they can't be saved,
4133 * so cf->unsaved_changes should be true only if the file can be saved.
4135 * We don't care whether we support the comments in this file or not;
4136 * if we can't, we'll offer the user the option of discarding the
4140 cf_can_save_as(capture_file *cf)
4142 if (wtap_dump_can_write(cf->linktypes, 0)) {
4143 /* We can write it out with Wiretap. */
4147 if (cf->is_tempfile && !cf->unsaved_changes) {
4149 * Temporary file with no unsaved changes, so we can just do a
4155 /* Nothing to save. */
4160 * Does this file have unsaved data?
4163 cf_has_unsaved_data(capture_file *cf)
4166 * If this is a temporary file, or a file with unsaved changes, it
4169 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4173 * Quick scan to find packet offsets.
4175 static cf_read_status_t
4176 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4178 const wtap_rec *rec;
4183 progdlg_t *progbar = NULL;
4184 GTimer *prog_timer = g_timer_new();
4187 GTimeVal start_time;
4188 gchar status_str[100];
4193 /* Close the old handle. */
4194 wtap_close(cf->provider.wth);
4196 /* Open the new file. */
4197 /* XXX: this will go through all open_routines for a matching one. But right
4198 now rescan_file() is only used when a file is being saved to a different
4199 format than the original, and the user is not given a choice of which
4200 reader to use (only which format to save it in), so doing this makes
4202 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4203 if (cf->provider.wth == NULL) {
4204 cfile_open_failure_alert_box(fname, err, err_info);
4205 return CF_READ_ERROR;
4208 /* We're scanning a file whose contents should be the same as what
4209 we had before, so we don't discard dissection state etc.. */
4212 /* Set the file name because we need it to set the follow stream filter.
4213 XXX - is that still true? We need it for other reasons, though,
4215 cf->filename = g_strdup(fname);
4217 /* Indicate whether it's a permanent or temporary file. */
4218 cf->is_tempfile = is_tempfile;
4220 /* No user changes yet. */
4221 cf->unsaved_changes = FALSE;
4223 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4224 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4226 cf->snap = wtap_snapshot_length(cf->provider.wth);
4228 name_ptr = g_filename_display_basename(cf->filename);
4230 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4232 /* Record whether the file is compressed.
4233 XXX - do we know this at open time? */
4234 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
4236 /* Find the size of the file. */
4237 size = wtap_file_size(cf->provider.wth, NULL);
4239 g_timer_start(prog_timer);
4241 cf->stop_flag = FALSE;
4242 g_get_current_time(&start_time);
4245 rec = wtap_get_rec(cf->provider.wth);
4246 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4248 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4249 fdata->file_off = data_offset;
4252 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4254 /* Create the progress bar if necessary. */
4255 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4256 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4257 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4258 TRUE, &cf->stop_flag, &start_time, progbar_val);
4262 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4263 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4264 * likely trigger UI paint events, which might take a while depending on
4265 * the platform and display. Reset our timer *after* painting.
4267 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4268 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4269 /* update the packet bar content on the first run or frequently on very large files */
4270 update_progress_dlg(progbar, progbar_val, status_str);
4271 compute_elapsed(cf, &start_time);
4272 packets_bar_update();
4273 g_timer_start(prog_timer);
4277 if (cf->stop_flag) {
4278 /* Well, the user decided to abort the rescan. Sadly, as this
4279 isn't a reread, recovering is difficult, so we'll just
4280 close the current capture. */
4284 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4285 it's not already there.
4286 XXX - yes, this is O(N), so if every packet had a different
4287 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4288 there are probably going to be a small number of encapsulation types
4290 if (rec->rec_type == REC_TYPE_PACKET) {
4291 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4295 /* Free the display name */
4298 /* We're done reading the file; destroy the progress bar if it was created. */
4299 if (progbar != NULL)
4300 destroy_progress_dlg(progbar);
4301 g_timer_destroy(prog_timer);
4303 /* We're done reading sequentially through the file. */
4304 cf->state = FILE_READ_DONE;
4306 /* Close the sequential I/O side, to free up memory it requires. */
4307 wtap_sequential_close(cf->provider.wth);
4309 /* compute the time it took to load the file */
4310 compute_elapsed(cf, &start_time);
4312 /* Set the file encapsulation type now; we don't know what it is until
4313 we've looked at all the packets, as we don't know until then whether
4314 there's more than one type (and thus whether it's
4315 WTAP_ENCAP_PER_PACKET). */
4316 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4318 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4320 if (cf->stop_flag) {
4321 /* Our caller will give up at this point. */
4322 return CF_READ_ABORTED;
4326 /* Put up a message box noting that the read failed somewhere along
4327 the line. Don't throw out the stuff we managed to read, though,
4329 cfile_read_failure_alert_box(NULL, err, err_info);
4330 return CF_READ_ERROR;
4336 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4337 gboolean compressed, gboolean discard_comments,
4338 gboolean dont_reopen)
4341 gchar *fname_new = NULL;
4344 addrinfo_lists_t *addr_lists;
4348 gchar *display_basename;
4355 save_callback_args_t callback_args;
4356 gboolean needs_reload = FALSE;
4358 /* XXX caller should avoid saving the file while a read is pending
4359 * (e.g. by delaying the save action) */
4360 if (cf->read_lock) {
4361 g_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname);
4364 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4366 addr_lists = get_addrinfo_list();
4368 if (save_format == cf->cd_t && compressed == cf->iscompressed
4369 && !discard_comments && !cf->unsaved_changes
4370 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4371 /* We're saving in the format it's already in, and we're not discarding
4372 comments, and there are no changes we have in memory that aren't saved
4373 to the file, and we have no name resolution information to write or
4374 the file format we're saving in doesn't support writing name
4375 resolution information, so we can just move or copy the raw data. */
4377 if (cf->is_tempfile) {
4378 /* The file being saved is a temporary file from a live
4379 capture, so it doesn't need to stay around under that name;
4380 first, try renaming the capture buffer file to the new name.
4381 This acts as a "safe save", in that, if the file already
4382 exists, the existing file will be removed only if the rename
4385 Sadly, on Windows, as we have the current capture file
4386 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4387 (to cause the rename to remove an existing target), as
4388 done by ws_stdio_rename() (ws_rename() is #defined to
4389 be ws_stdio_rename() on Windows) will fail.
4391 According to the MSDN documentation for CreateFile(), if,
4392 when we open a capture file, we were to directly do a CreateFile(),
4393 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4394 convert it to a file descriptor with _open_osfhandle(),
4395 that would allow the file to be renamed out from under us.
4397 However, that doesn't work in practice. Perhaps the problem
4398 is that the process doing the rename is the process that
4399 has the file open. */
4401 if (ws_rename(cf->filename, fname) == 0) {
4402 /* That succeeded - there's no need to copy the source file. */
4403 how_to_save = SAVE_WITH_MOVE;
4405 if (errno == EXDEV) {
4406 /* They're on different file systems, so we have to copy the
4408 how_to_save = SAVE_WITH_COPY;
4410 /* The rename failed, but not because they're on different
4411 file systems - put up an error message. (Or should we
4412 just punt and try to copy? The only reason why I'd
4413 expect the rename to fail and the copy to succeed would
4414 be if we didn't have permission to remove the file from
4415 the temporary directory, and that might be fixable - but
4416 is it worth requiring the user to go off and fix it?) */
4417 cf_rename_failure_alert_box(fname, errno);
4422 /* Windows - copy the file to its new location. */
4423 how_to_save = SAVE_WITH_COPY;
4426 /* It's a permanent file, so we should copy it, and not remove the
4428 how_to_save = SAVE_WITH_COPY;
4431 if (how_to_save == SAVE_WITH_COPY) {
4432 /* Copy the file, if we haven't moved it. If we're overwriting
4433 an existing file, we do it with a "safe save", by writing
4434 to a new file and, if the write succeeds, renaming the
4435 new file on top of the old file. */
4436 if (file_exists(fname)) {
4437 fname_new = g_strdup_printf("%s~", fname);
4438 if (!copy_file_binary_mode(cf->filename, fname_new))
4441 if (!copy_file_binary_mode(cf->filename, fname))
4446 /* Either we're saving in a different format or we're saving changes,
4447 such as added, modified, or removed comments, that haven't yet
4448 been written to the underlying file; we can't do that by copying
4449 or moving the capture file, we have to do it by writing the packets
4452 GArray *shb_hdrs = NULL;
4453 wtapng_iface_descriptions_t *idb_inf = NULL;
4454 GArray *nrb_hdrs = NULL;
4457 /* XXX: what free's this shb_hdr? */
4458 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4459 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4460 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4462 /* Determine what file encapsulation type we should use. */
4463 encap = wtap_dump_file_encap_type(cf->linktypes);
4465 if (file_exists(fname)) {
4466 /* We're overwriting an existing file; write out to a new file,
4467 and, if that succeeds, rename the new file on top of the
4468 old file. That makes this a "safe save", so that we don't
4469 lose the old file if we have a problem writing out the new
4470 file. (If the existing file is the current capture file,
4471 we *HAVE* to do that, otherwise we're overwriting the file
4472 from which we're reading the packets that we're writing!) */
4473 fname_new = g_strdup_printf("%s~", fname);
4474 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4475 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4477 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4478 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4484 cfile_dump_open_failure_alert_box(fname, err, save_format);
4488 /* Add address resolution */
4489 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4491 /* Iterate through the list of packets, processing all the packets. */
4492 callback_args.pdh = pdh;
4493 callback_args.fname = fname;
4494 callback_args.file_type = save_format;
4495 switch (process_specified_records(cf, NULL, "Saving", "packets",
4496 TRUE, save_record, &callback_args, TRUE)) {
4499 /* Completed successfully. */
4503 /* The user decided to abort the saving.
4504 If we're writing to a temporary file, remove it.
4505 XXX - should we do so even if we're not writing to a
4507 wtap_dump_close(pdh, &err);
4508 if (fname_new != NULL)
4509 ws_unlink(fname_new);
4510 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4511 return CF_WRITE_ABORTED;
4514 /* Error while saving.
4515 If we're writing to a temporary file, remove it. */
4516 if (fname_new != NULL)
4517 ws_unlink(fname_new);
4518 wtap_dump_close(pdh, &err);
4522 needs_reload = wtap_dump_get_needs_reload(pdh);
4524 if (!wtap_dump_close(pdh, &err)) {
4525 cfile_close_failure_alert_box(fname, err);
4529 how_to_save = SAVE_WITH_WTAP;
4532 if (fname_new != NULL) {
4533 /* We wrote out to fname_new, and should rename it on top of
4534 fname. fname_new is now closed, so that should be possible even
4535 on Windows. However, on Windows, we first need to close whatever
4536 file descriptors we have open for fname. */
4538 wtap_fdclose(cf->provider.wth);
4540 /* Now do the rename. */
4541 if (ws_rename(fname_new, fname) == -1) {
4542 /* Well, the rename failed. */
4543 cf_rename_failure_alert_box(fname, errno);
4545 /* Attempt to reopen the random file descriptor using the
4546 current file's filename. (At this point, the sequential
4547 file descriptor is closed.) */
4548 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4549 /* Oh, well, we're screwed. */
4550 display_basename = g_filename_display_basename(cf->filename);
4551 simple_error_message_box(
4552 file_open_error_message(err, FALSE), display_basename);
4553 g_free(display_basename);
4560 /* If this was a temporary file, and we didn't do the save by doing
4561 a move, so the tempoary file is still around under its old name,
4563 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4564 /* If this fails, there's not much we can do, so just ignore errors. */
4565 ws_unlink(cf->filename);
4568 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4569 cf->unsaved_changes = FALSE;
4572 switch (how_to_save) {
4574 case SAVE_WITH_MOVE:
4575 /* We just moved the file, so the wtap structure refers to the
4576 new file, and all the information other than the filename
4577 and the "is temporary" status applies to the new file; just
4579 g_free(cf->filename);
4580 cf->filename = g_strdup(fname);
4581 cf->is_tempfile = FALSE;
4582 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4585 case SAVE_WITH_COPY:
4586 /* We just copied the file, so all the information other than
4587 the wtap structure, the filename, and the "is temporary"
4588 status applies to the new file; just update that. */
4589 wtap_close(cf->provider.wth);
4590 /* Although we're just "copying" and then opening the copy, it will
4591 try all open_routine readers to open the copy, so we need to
4592 reset the cfile's open_type. */
4593 cf->open_type = WTAP_TYPE_AUTO;
4594 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4595 if (cf->provider.wth == NULL) {
4596 cfile_open_failure_alert_box(fname, err, err_info);
4599 g_free(cf->filename);
4600 cf->filename = g_strdup(fname);
4601 cf->is_tempfile = FALSE;
4603 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4606 case SAVE_WITH_WTAP:
4607 /* Open and read the file we saved to.
4609 XXX - this is somewhat of a waste; we already have the
4610 packets, all this gets us is updated file type information
4611 (which we could just stuff into "cf"), and having the new
4612 file be the one we have opened and from which we're reading
4613 the data, and it means we have to spend time opening and
4614 reading the file, which could be a significant amount of
4615 time if the file is large.
4617 If the capture-file-writing code were to return the
4618 seek offset of each packet it writes, we could save that
4619 in the frame_data structure for the frame, and just open
4620 the file without reading it again...
4622 ...as long as, for gzipped files, the process of writing
4623 out the file *also* generates the information needed to
4624 support fast random access to the compressed file. */
4625 /* rescan_file will cause us to try all open_routines, so
4626 reset cfile's open_type */
4627 cf->open_type = WTAP_TYPE_AUTO;
4628 /* There are cases when SAVE_WITH_WTAP can result in new packets
4629 being written to the file, e.g ERF records
4630 In that case, we need to reload the whole file */
4632 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4633 if (cf_read(cf, TRUE) != CF_READ_OK) {
4634 /* The rescan failed; just close the file. Either
4635 a dialog was popped up for the failure, so the
4636 user knows what happened, or they stopped the
4637 rescan, in which case they know what happened. */
4638 /* XXX: This is inconsistent with normal open/reload behaviour. */
4644 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4645 /* The rescan failed; just close the file. Either
4646 a dialog was popped up for the failure, so the
4647 user knows what happened, or they stopped the
4648 rescan, in which case they know what happened. */
4655 /* If we were told to discard the comments, do so. */
4656 if (discard_comments) {
4657 /* Remove SHB comment, if any. */
4658 wtap_write_shb_comment(cf->provider.wth, NULL);
4660 /* remove all user comments */
4661 for (framenum = 1; framenum <= cf->count; framenum++) {
4662 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4664 fdata->flags.has_phdr_comment = FALSE;
4665 fdata->flags.has_user_comment = FALSE;
4668 if (cf->provider.frames_user_comments) {
4669 g_tree_destroy(cf->provider.frames_user_comments);
4670 cf->provider.frames_user_comments = NULL;
4673 cf->packet_comment_count = 0;
4679 if (fname_new != NULL) {
4680 /* We were trying to write to a temporary file; get rid of it if it
4681 exists. (We don't care whether this fails, as, if it fails,
4682 there's not much we can do about it. I guess if it failed for
4683 a reason other than "it doesn't exist", we could report an
4684 error, so the user knows there's a junk file that they might
4685 want to clean up.) */
4686 ws_unlink(fname_new);
4689 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4690 return CF_WRITE_ERROR;
4694 cf_export_specified_packets(capture_file *cf, const char *fname,
4695 packet_range_t *range, guint save_format,
4696 gboolean compressed)
4698 gchar *fname_new = NULL;
4701 save_callback_args_t callback_args;
4702 GArray *shb_hdrs = NULL;
4703 wtapng_iface_descriptions_t *idb_inf = NULL;
4704 GArray *nrb_hdrs = NULL;
4707 packet_range_process_init(range);
4709 /* We're writing out specified packets from the specified capture
4710 file to another file. Even if all captured packets are to be
4711 written, don't special-case the operation - read each packet
4712 and then write it out if it's one of the specified ones. */
4714 /* XXX: what free's this shb_hdr? */
4715 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4716 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4717 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4719 /* Determine what file encapsulation type we should use. */
4720 encap = wtap_dump_file_encap_type(cf->linktypes);
4722 if (file_exists(fname)) {
4723 /* We're overwriting an existing file; write out to a new file,
4724 and, if that succeeds, rename the new file on top of the
4725 old file. That makes this a "safe save", so that we don't
4726 lose the old file if we have a problem writing out the new
4727 file. (If the existing file is the current capture file,
4728 we *HAVE* to do that, otherwise we're overwriting the file
4729 from which we're reading the packets that we're writing!) */
4730 fname_new = g_strdup_printf("%s~", fname);
4731 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4732 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4734 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4735 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4741 cfile_dump_open_failure_alert_box(fname, err, save_format);
4745 /* Add address resolution */
4746 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4748 /* Iterate through the list of packets, processing the packets we were
4751 XXX - we've already called "packet_range_process_init(range)", but
4752 "process_specified_records()" will do it again. Fortunately,
4753 that's harmless in this case, as we haven't done anything to
4754 "range" since we initialized it. */
4755 callback_args.pdh = pdh;
4756 callback_args.fname = fname;
4757 callback_args.file_type = save_format;
4758 switch (process_specified_records(cf, range, "Writing", "specified records",
4759 TRUE, save_record, &callback_args, TRUE)) {
4762 /* Completed successfully. */
4766 /* The user decided to abort the saving.
4767 If we're writing to a temporary file, remove it.
4768 XXX - should we do so even if we're not writing to a
4770 wtap_dump_close(pdh, &err);
4771 if (fname_new != NULL)
4772 ws_unlink(fname_new);
4773 return CF_WRITE_ABORTED;
4777 /* Error while saving.
4778 If we're writing to a temporary file, remove it. */
4779 if (fname_new != NULL)
4780 ws_unlink(fname_new);
4781 wtap_dump_close(pdh, &err);
4785 if (!wtap_dump_close(pdh, &err)) {
4786 cfile_close_failure_alert_box(fname, err);
4790 if (fname_new != NULL) {
4791 /* We wrote out to fname_new, and should rename it on top of
4792 fname; fname is now closed, so that should be possible even
4793 on Windows. Do the rename. */
4794 if (ws_rename(fname_new, fname) == -1) {
4795 /* Well, the rename failed. */
4796 cf_rename_failure_alert_box(fname, errno);
4804 if (fname_new != NULL) {
4805 /* We were trying to write to a temporary file; get rid of it if it
4806 exists. (We don't care whether this fails, as, if it fails,
4807 there's not much we can do about it. I guess if it failed for
4808 a reason other than "it doesn't exist", we could report an
4809 error, so the user knows there's a junk file that they might
4810 want to clean up.) */
4811 ws_unlink(fname_new);
4814 return CF_WRITE_ERROR;
4818 * XXX - whether we mention the source pathname, the target pathname,
4819 * or both depends on the error and on what we find if we look for
4820 * one or both of them.
4823 cf_rename_failure_alert_box(const char *filename, int err)
4825 gchar *display_basename;
4827 display_basename = g_filename_display_basename(filename);
4831 /* XXX - should check whether the source exists and, if not,
4832 report it as the problem and, if so, report the destination
4834 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4839 /* XXX - if we're doing a rename after a safe save, we should
4840 probably say something else. */
4841 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4846 /* XXX - this should probably mention both the source and destination
4848 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4849 display_basename, wtap_strerror(err));
4852 g_free(display_basename);
4855 /* Reload the current capture file. */
4857 cf_reload(capture_file *cf) {
4859 gboolean is_tempfile;
4862 if (cf->read_lock) {
4863 g_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename);
4867 /* If the file could be opened, "cf_open()" calls "cf_close()"
4868 to get rid of state for the old capture file before filling in state
4869 for the new capture file. "cf_close()" will remove the file if
4870 it's a temporary file; we don't want that to happen (for one thing,
4871 it'd prevent subsequent reopens from working). Remember whether it's
4872 a temporary file, mark it as not being a temporary file, and then
4873 reopen it as the type of file it was.
4875 Also, "cf_close()" will free "cf->filename", so we must make
4876 a copy of it first. */
4877 filename = g_strdup(cf->filename);
4878 is_tempfile = cf->is_tempfile;
4879 cf->is_tempfile = FALSE;
4880 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4881 switch (cf_read(cf, TRUE)) {
4885 /* Just because we got an error, that doesn't mean we were unable
4886 to read any of the file; we handle what we could get from the
4890 case CF_READ_ABORTED:
4891 /* The user bailed out of re-reading the capture file; the
4892 capture file has been closed - just free the capture file name
4893 string and return (without changing the last containing
4899 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4900 Instead, the file was left open, so we should restore "cf->is_tempfile"
4903 XXX - change the menu? Presumably "cf_open()" will do that;
4904 make sure it does! */
4905 cf->is_tempfile = is_tempfile;
4907 /* "cf_open()" made a copy of the file name we handed it, so
4908 we should free up our copy. */
4918 * indent-tabs-mode: nil
4921 * ex: set shiftwidth=2 tabstop=8 expandtab:
4922 * :indentSize=2:tabSize=8:noTabs=true: