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 /* We're about to start reading the file. */
271 cf->state = FILE_READ_IN_PROGRESS;
273 cf->provider.wth = wth;
276 /* Set the file name because we need it to set the follow stream filter.
277 XXX - is that still true? We need it for other reasons, though,
279 cf->filename = g_strdup(fname);
281 /* Indicate whether it's a permanent or temporary file. */
282 cf->is_tempfile = is_tempfile;
284 /* No user changes yet. */
285 cf->unsaved_changes = FALSE;
287 cf->computed_elapsed = 0;
289 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
290 cf->open_type = type;
291 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
293 cf->packet_comment_count = 0;
294 cf->displayed_count = 0;
295 cf->marked_count = 0;
296 cf->ignored_count = 0;
297 cf->ref_time_count = 0;
298 cf->drops_known = FALSE;
300 cf->snap = wtap_snapshot_length(cf->provider.wth);
302 /* Allocate a frame_data_sequence for the frames in this file */
303 cf->provider.frames = new_frame_data_sequence();
305 nstime_set_zero(&cf->elapsed_time);
306 cf->provider.ref = NULL;
307 cf->provider.prev_dis = NULL;
308 cf->provider.prev_cap = NULL;
311 /* Create new epan session for dissection.
312 * (The old one was freed in cf_close().)
314 cf->epan = ws_epan_new(cf);
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 /* tell the BER dissector the file name */
321 ber_set_filename(cf->filename);
324 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
325 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
330 cfile_open_failure_alert_box(fname, *err, err_info);
335 * Add an encapsulation type to cf->linktypes.
338 cf_add_encapsulation_type(capture_file *cf, int encap)
342 for (i = 0; i < cf->linktypes->len; i++) {
343 if (g_array_index(cf->linktypes, gint, i) == encap)
344 return; /* it's already there */
346 /* It's not already there - add it. */
347 g_array_append_val(cf->linktypes, encap);
350 /* Reset everything to a pristine state */
352 cf_close(capture_file *cf)
354 cf->stop_flag = FALSE;
355 if (cf->state == FILE_CLOSED)
356 return; /* Nothing to do */
358 /* Die if we're in the middle of reading a file. */
359 g_assert(cf->state != FILE_READ_IN_PROGRESS);
360 g_assert(!cf->read_lock);
362 cf_callback_invoke(cf_cb_file_closing, cf);
364 /* close things, if not already closed before */
365 color_filters_cleanup();
367 if (cf->provider.wth) {
368 wtap_close(cf->provider.wth);
369 cf->provider.wth = NULL;
371 /* We have no file open... */
372 if (cf->filename != NULL) {
373 /* If it's a temporary file, remove it. */
375 ws_unlink(cf->filename);
376 g_free(cf->filename);
379 /* ...which means we have no changes to that file to save. */
380 cf->unsaved_changes = FALSE;
382 /* no open_routine type */
383 cf->open_type = WTAP_TYPE_AUTO;
385 /* Clean up the record metadata. */
386 wtap_rec_cleanup(&cf->rec);
388 /* Free up the packet buffer. */
389 ws_buffer_free(&cf->buf);
391 dfilter_free(cf->rfcode);
393 if (cf->provider.frames != NULL) {
394 free_frame_data_sequence(cf->provider.frames);
395 cf->provider.frames = NULL;
397 if (cf->provider.frames_user_comments) {
398 g_tree_destroy(cf->provider.frames_user_comments);
399 cf->provider.frames_user_comments = NULL;
401 cf_unselect_packet(cf); /* nothing to select */
402 cf->first_displayed = 0;
403 cf->last_displayed = 0;
405 /* No frames, no frame selected, no field in that frame selected. */
407 cf->current_frame = 0;
409 cf->finfo_selected = NULL;
411 /* No frame link-layer types, either. */
412 if (cf->linktypes != NULL) {
413 g_array_free(cf->linktypes, TRUE);
414 cf->linktypes = NULL;
417 /* Clear the packet list. */
418 packet_list_freeze();
423 nstime_set_zero(&cf->elapsed_time);
425 reset_tap_listeners();
430 /* We have no file open. */
431 cf->state = FILE_CLOSED;
433 cf_callback_invoke(cf_cb_file_closed, cf);
437 * TRUE if the progress dialog doesn't exist and it looks like we'll
438 * take > 2s to load, FALSE otherwise.
440 static inline gboolean
441 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
445 if (progdlg) return FALSE;
446 elapsed = g_timer_elapsed(prog_timer, NULL);
447 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
448 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
455 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
459 progbar_val = (gfloat) file_pos / (gfloat) size;
460 if (progbar_val > 1.0) {
462 /* The file probably grew while we were reading it.
463 * Update file size, and try again.
465 size = wtap_file_size(cf->provider.wth, NULL);
468 progbar_val = (gfloat) file_pos / (gfloat) size;
470 /* If it's still > 1, either "wtap_file_size()" failed (in which
471 * case there's not much we can do about it), or the file
472 * *shrank* (in which case there's not much we can do about
473 * it); just clip the progress value at 1.0.
475 if (progbar_val > 1.0f)
479 g_snprintf(status_str, status_size,
480 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
481 file_pos / 1024, size / 1024);
487 cf_read(capture_file *cf, gboolean reloading)
490 gchar *err_info = NULL;
492 progdlg_t *volatile progbar = NULL;
493 GTimer *prog_timer = g_timer_new();
497 volatile gboolean create_proto_tree;
500 volatile gboolean is_read_aborted = FALSE;
502 /* The update_progress_dlg call below might end up accepting a user request to
503 * trigger redissection/rescans which can modify/destroy the dissection
504 * context ("cf->epan"). That condition should be prevented by callers, but in
505 * case it occurs let's fail gracefully.
508 g_warning("Failing due to recursive cf_read(\"%s\", %d) call!",
509 cf->filename, reloading);
510 return CF_READ_ERROR;
512 cf->read_lock = TRUE;
514 /* Compile the current display filter.
515 * We assume this will not fail since cf->dfilter is only set in
516 * cf_filter IFF the filter was valid.
518 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
519 g_assert(!cf->dfilter || (compiled && dfcode));
521 /* Get the union of the flags for all tap listeners. */
522 tap_flags = union_of_tap_listener_flags();
525 * Determine whether we need to create a protocol tree.
528 * we're going to apply a display filter;
530 * one of the tap listeners is going to apply a filter;
532 * one of the tap listeners requires a protocol tree;
534 * a postdissector wants field values or protocols on
538 (dfcode != NULL || have_filtering_tap_listeners() ||
539 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
541 reset_tap_listeners();
543 name_ptr = g_filename_display_basename(cf->filename);
546 cf_callback_invoke(cf_cb_file_reload_started, cf);
548 cf_callback_invoke(cf_cb_file_read_started, cf);
550 /* Record whether the file is compressed.
551 XXX - do we know this at open time? */
552 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
554 /* The packet list window will be empty until the file is completly loaded */
555 packet_list_freeze();
557 cf->stop_flag = FALSE;
558 g_get_current_time(&start_time);
560 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
570 gchar status_str[100];
574 /* If any tap listeners require the columns, construct them. */
575 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
577 /* Find the size of the file. */
578 size = wtap_file_size(cf->provider.wth, NULL);
580 g_timer_start(prog_timer);
582 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
585 file_pos = wtap_read_so_far(cf->provider.wth);
587 /* Create the progress bar if necessary. */
588 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
589 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
591 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
592 TRUE, &cf->stop_flag, &start_time, progbar_val);
594 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
595 TRUE, &cf->stop_flag, &start_time, progbar_val);
599 * Update the progress bar, but do it only after
600 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
601 * and packets_bar_update will likely trigger UI paint events, which
602 * might take a while depending on the platform and display. Reset
603 * our timer *after* painting.
605 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
606 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
607 /* update the packet bar content on the first run or frequently on very large files */
608 update_progress_dlg(progbar, progbar_val, status_str);
609 compute_elapsed(cf, &start_time);
610 packets_bar_update();
611 g_timer_start(prog_timer);
614 * The previous GUI triggers should not have destroyed the running
615 * session. If that did happen, it could blow up when read_record tries
616 * to use the destroyed edt.session, so detect it right here.
618 g_assert(edt.session == cf->epan);
621 if (cf->state == FILE_READ_ABORTED) {
622 /* Well, the user decided to exit Wireshark. Break out of the
623 loop, and let the code below (which is called even if there
624 aren't any packets left to read) exit. */
625 is_read_aborted = TRUE;
629 /* Well, the user decided to abort the read. He/She will be warned and
630 it might be enough for him/her to work with the already loaded
632 This is especially true for very large capture files, where you don't
633 want to wait loading the whole file (which may last minutes or even
634 hours even on fast machines) just to see that it was the wrong file. */
637 read_record(cf, dfcode, &edt, cinfo, data_offset);
640 CATCH(OutOfMemoryError) {
641 simple_message_box(ESD_TYPE_ERROR, NULL,
642 "More information and workarounds can be found at\n"
643 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
644 "Sorry, but Wireshark has run out of memory and has to terminate now.");
646 /* Could we close the current capture and free up memory from that? */
648 /* we have to terminate, as we cannot recover from the memory error */
654 /* Free the display name */
657 /* Cleanup and release all dfilter resources */
658 dfilter_free(dfcode);
660 epan_dissect_cleanup(&edt);
662 /* We're done reading the file; destroy the progress bar if it was created. */
664 destroy_progress_dlg(progbar);
665 g_timer_destroy(prog_timer);
667 /* We're done reading sequentially through the file. */
668 cf->state = FILE_READ_DONE;
670 /* Close the sequential I/O side, to free up memory it requires. */
671 wtap_sequential_close(cf->provider.wth);
673 /* Allow the protocol dissectors to free up memory that they
674 * don't need after the sequential run-through of the packets. */
675 postseq_cleanup_all_protocols();
677 /* compute the time it took to load the file */
678 compute_elapsed(cf, &start_time);
680 /* Set the file encapsulation type now; we don't know what it is until
681 we've looked at all the packets, as we don't know until then whether
682 there's more than one type (and thus whether it's
683 WTAP_ENCAP_PER_PACKET). */
684 cf->lnk_t = wtap_file_encap(cf->provider.wth);
686 cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed);
691 cf_callback_invoke(cf_cb_file_reload_finished, cf);
693 cf_callback_invoke(cf_cb_file_read_finished, cf);
695 /* If we have any displayed packets to select, select the first of those
696 packets by making the first row the selected row. */
697 if (cf->first_displayed != 0) {
698 packet_list_select_first_row();
701 /* It is safe again to execute redissections. */
702 g_assert(cf->read_lock);
703 cf->read_lock = FALSE;
705 if (is_read_aborted) {
707 * Well, the user decided to exit Wireshark while reading this *offline*
708 * capture file (Live captures are handled by something like
709 * cf_continue_tail). Clean up accordingly.
712 cf->redissection_queued = RESCAN_NONE;
713 return CF_READ_ABORTED;
716 if (cf->redissection_queued != RESCAN_NONE) {
717 /* Redissection was queued up. Clear the request and perform it now. */
718 gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT;
719 rescan_packets(cf, "Reprocessing", "all packets", redissect);
723 simple_message_box(ESD_TYPE_WARN, NULL,
724 "The remaining packets in the file were discarded.\n"
726 "As a lot of packets from the original file will be missing,\n"
727 "remember to be careful when saving the current content to a file.\n",
728 "File loading was cancelled.");
729 return CF_READ_ERROR;
733 /* Put up a message box noting that the read failed somewhere along
734 the line. Don't throw out the stuff we managed to read, though,
736 cfile_read_failure_alert_box(NULL, err, err_info);
737 return CF_READ_ERROR;
744 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
747 volatile int newly_displayed_packets = 0;
750 gboolean create_proto_tree;
754 /* Compile the current display filter.
755 * We assume this will not fail since cf->dfilter is only set in
756 * cf_filter IFF the filter was valid.
758 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
759 g_assert(!cf->dfilter || (compiled && dfcode));
761 /* Get the union of the flags for all tap listeners. */
762 tap_flags = union_of_tap_listener_flags();
765 * Determine whether we need to create a protocol tree.
768 * we're going to apply a display filter;
770 * one of the tap listeners is going to apply a filter;
772 * one of the tap listeners requires a protocol tree;
774 * a postdissector wants field values or protocols on
778 (dfcode != NULL || have_filtering_tap_listeners() ||
779 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
783 /* Don't freeze/thaw the list when doing live capture */
784 /*packet_list_freeze();*/
786 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
788 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
791 gint64 data_offset = 0;
794 /* If any tap listeners require the columns, construct them. */
795 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
797 while (to_read != 0) {
798 wtap_cleareof(cf->provider.wth);
799 if (!wtap_read(cf->provider.wth, err, &err_info, &data_offset)) {
802 if (cf->state == FILE_READ_ABORTED) {
803 /* Well, the user decided to exit Wireshark. Break out of the
804 loop, and let the code below (which is called even if there
805 aren't any packets left to read) exit. */
808 if (read_record(cf, dfcode, &edt, (column_info *) cinfo, data_offset)) {
809 newly_displayed_packets++;
814 CATCH(OutOfMemoryError) {
815 simple_message_box(ESD_TYPE_ERROR, NULL,
816 "More information and workarounds can be found at\n"
817 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
818 "Sorry, but Wireshark has run out of memory and has to terminate now.");
820 /* Could we close the current capture and free up memory from that? */
821 return CF_READ_ABORTED;
823 /* we have to terminate, as we cannot recover from the memory error */
829 /* Update the file encapsulation; it might have changed based on the
830 packets we've read. */
831 cf->lnk_t = wtap_file_encap(cf->provider.wth);
833 /* Cleanup and release all dfilter resources */
834 dfilter_free(dfcode);
836 epan_dissect_cleanup(&edt);
838 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
839 cf->count, cf->state, *err);*/
841 /* Don't freeze/thaw the list when doing live capture */
842 /*packet_list_thaw();*/
843 /* With the new packet list the first packet
844 * isn't automatically selected.
846 if (!cf->current_frame)
847 packet_list_select_first_row();
849 /* moving to the end of the packet list - if the user requested so and
850 we have some new packets. */
851 if (newly_displayed_packets && cf->count != 0)
852 packet_list_moveto_end();
854 if (cf->state == FILE_READ_ABORTED) {
855 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
856 so that our caller can kill off the capture child process;
857 this will cause an EOF on the pipe from the child, so
858 "cf_finish_tail()" will be called, and it will clean up
860 return CF_READ_ABORTED;
861 } else if (*err != 0) {
862 /* We got an error reading the capture file.
863 XXX - pop up a dialog box instead? */
864 if (err_info != NULL) {
865 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
866 wtap_strerror(*err), cf->filename, err_info);
869 g_warning("Error \"%s\" while reading \"%s\"",
870 wtap_strerror(*err), cf->filename);
872 return CF_READ_ERROR;
878 cf_fake_continue_tail(capture_file *cf) {
879 cf->state = FILE_READ_DONE;
883 cf_finish_tail(capture_file *cf, int *err)
890 gboolean create_proto_tree;
894 /* Compile the current display filter.
895 * We assume this will not fail since cf->dfilter is only set in
896 * cf_filter IFF the filter was valid.
898 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
899 g_assert(!cf->dfilter || (compiled && dfcode));
901 /* Get the union of the flags for all tap listeners. */
902 tap_flags = union_of_tap_listener_flags();
904 /* If any tap listeners require the columns, construct them. */
905 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
908 * Determine whether we need to create a protocol tree.
911 * we're going to apply a display filter;
913 * one of the tap listeners is going to apply a filter;
915 * one of the tap listeners requires a protocol tree;
917 * a postdissector wants field values or protocols on
921 (dfcode != NULL || have_filtering_tap_listeners() ||
922 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
924 if (cf->provider.wth == NULL) {
926 return CF_READ_ERROR;
929 /* Don't freeze/thaw the list when doing live capture */
930 /*packet_list_freeze();*/
932 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
934 while ((wtap_read(cf->provider.wth, err, &err_info, &data_offset))) {
935 if (cf->state == FILE_READ_ABORTED) {
936 /* Well, the user decided to abort the read. Break out of the
937 loop, and let the code below (which is called even if there
938 aren't any packets left to read) exit. */
941 read_record(cf, dfcode, &edt, cinfo, data_offset);
944 /* Cleanup and release all dfilter resources */
945 dfilter_free(dfcode);
947 epan_dissect_cleanup(&edt);
949 /* Don't freeze/thaw the list when doing live capture */
950 /*packet_list_thaw();*/
952 if (cf->state == FILE_READ_ABORTED) {
953 /* Well, the user decided to abort the read. We're only called
954 when the child capture process closes the pipe to us (meaning
955 it's probably exited), so we can just close the capture
956 file; we return CF_READ_ABORTED so our caller can do whatever
957 is appropriate when that happens. */
959 return CF_READ_ABORTED;
962 /* We're done reading sequentially through the file. */
963 cf->state = FILE_READ_DONE;
965 /* We're done reading sequentially through the file; close the
966 sequential I/O side, to free up memory it requires. */
967 wtap_sequential_close(cf->provider.wth);
969 /* Allow the protocol dissectors to free up memory that they
970 * don't need after the sequential run-through of the packets. */
971 postseq_cleanup_all_protocols();
973 /* Update the file encapsulation; it might have changed based on the
974 packets we've read. */
975 cf->lnk_t = wtap_file_encap(cf->provider.wth);
977 /* Update the details in the file-set dialog, as the capture file
978 * has likely grown since we first stat-ed it */
979 fileset_update_file(cf->filename);
982 /* We got an error reading the capture file.
983 XXX - pop up a dialog box? */
984 if (err_info != NULL) {
985 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
986 wtap_strerror(*err), cf->filename, err_info);
989 g_warning("Error \"%s\" while reading \"%s\"",
990 wtap_strerror(*err), cf->filename);
992 return CF_READ_ERROR;
997 #endif /* HAVE_LIBPCAP */
1000 cf_get_display_name(capture_file *cf)
1004 /* Return a name to use in displays */
1005 if (!cf->is_tempfile) {
1006 /* Get the last component of the file name, and use that. */
1008 displayname = g_filename_display_basename(cf->filename);
1010 displayname=g_strdup("(No file)");
1013 /* The file we read is a temporary file from a live capture or
1014 a merge operation; we don't mention its name, but, if it's
1015 from a capture, give the source of the capture. */
1017 displayname = g_strdup(cf->source);
1019 displayname = g_strdup("(Untitled)");
1026 cf_get_basename(capture_file *cf)
1030 /* Return a name to use in the GUI for the basename for files to
1031 which we save statistics */
1032 if (!cf->is_tempfile) {
1033 /* Get the last component of the file name, and use that. */
1035 displayname = g_filename_display_basename(cf->filename);
1037 /* If the file name ends with any extension that corresponds
1038 to a file type we support - including compressed versions
1039 of those files - strip it off. */
1040 size_t displayname_len = strlen(displayname);
1041 GSList *extensions = wtap_get_all_file_extensions_list();
1043 for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) {
1044 /* Does the file name end with that extension? */
1045 const char *extension = (char *)suffix->data;
1046 size_t extension_len = strlen(extension);
1047 if (displayname_len > extension_len &&
1048 displayname[displayname_len - extension_len - 1] == '.' &&
1049 strcmp(&displayname[displayname_len - extension_len], extension) == 0) {
1050 /* Yes. Strip the extension off, and return the result. */
1051 displayname[displayname_len - extension_len - 1] = '\0';
1055 wtap_free_extensions_list(extensions);
1057 displayname=g_strdup("");
1060 /* The file we read is a temporary file from a live capture or
1061 a merge operation; we don't mention its name, but, if it's
1062 from a capture, give the source of the capture. */
1064 displayname = g_strdup(cf->source);
1066 displayname = g_strdup("");
1072 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1078 cf->source = g_strdup(source);
1080 cf->source = g_strdup("");
1084 const gchar *cf_get_tempfile_source(capture_file *cf) {
1092 /* XXX - use a macro instead? */
1094 cf_get_packet_count(capture_file *cf)
1099 /* XXX - use a macro instead? */
1101 cf_is_tempfile(capture_file *cf)
1103 return cf->is_tempfile;
1106 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1108 cf->is_tempfile = is_tempfile;
1112 /* XXX - use a macro instead? */
1113 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1115 cf->drops_known = drops_known;
1118 /* XXX - use a macro instead? */
1119 void cf_set_drops(capture_file *cf, guint32 drops)
1124 /* XXX - use a macro instead? */
1125 gboolean cf_get_drops_known(capture_file *cf)
1127 return cf->drops_known;
1130 /* XXX - use a macro instead? */
1131 guint32 cf_get_drops(capture_file *cf)
1136 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1138 cf->rfcode = rfcode;
1142 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1143 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1144 wtap_rec *rec, const guint8 *buf, gboolean add_to_packet_list)
1146 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1147 &cf->provider.ref, cf->provider.prev_dis);
1148 cf->provider.prev_cap = fdata;
1150 if (dfcode != NULL) {
1151 epan_dissect_prime_with_dfilter(edt, dfcode);
1154 /* Prepare coloring rules, this ensures that display filter rules containing
1155 * frame.color_rule references are still processed.
1156 * TODO: actually detect that situation or maybe apply other optimizations? */
1157 if (edt->tree && color_filters_used()) {
1158 color_filters_prime_edt(edt);
1159 fdata->flags.need_colorize = 1;
1163 if (!fdata->flags.visited) {
1164 /* This is the first pass, so prime the epan_dissect_t with the
1165 hfids postdissectors want on the first pass. */
1166 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1169 /* Dissect the frame. */
1170 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1171 frame_tvbuff_new(&cf->provider, fdata, buf),
1174 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1175 if (dfcode != NULL) {
1176 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1178 if (fdata->flags.passed_dfilter) {
1179 /* This frame passed the display filter but it may depend on other
1180 * (potentially not displayed) frames. Find those frames and mark them
1183 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1186 fdata->flags.passed_dfilter = 1;
1188 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1189 cf->displayed_count++;
1191 if (add_to_packet_list) {
1192 /* We fill the needed columns from new_packet_list */
1193 packet_list_append(cinfo, fdata);
1196 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1198 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1199 cf->provider.prev_dis = fdata;
1201 /* If we haven't yet seen the first frame, this is it. */
1202 if (cf->first_displayed == 0)
1203 cf->first_displayed = fdata->num;
1205 /* This is the last frame we've seen so far. */
1206 cf->last_displayed = fdata->num;
1209 epan_dissect_reset(edt);
1213 * Read in a new record.
1214 * Returns TRUE if the packet was added to the packet (record) list,
1218 read_record(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1219 column_info *cinfo, gint64 offset)
1221 wtap_rec *rec = wtap_get_rec(cf->provider.wth);
1222 const guint8 *buf = wtap_get_buf_ptr(cf->provider.wth);
1225 gboolean passed = TRUE;
1226 gboolean added = FALSE;
1228 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1229 it's not already there.
1230 XXX - yes, this is O(N), so if every packet had a different
1231 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1232 there are probably going to be a small number of encapsulation types
1234 if (rec->rec_type == REC_TYPE_PACKET) {
1235 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
1238 /* The frame number of this packet, if we add it to the set of frames,
1239 would be one more than the count of frames in the file so far. */
1240 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes);
1243 epan_dissect_t rf_edt;
1245 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1246 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1247 epan_dissect_run(&rf_edt, cf->cd_t, rec,
1248 frame_tvbuff_new(&cf->provider, &fdlocal, buf),
1250 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1251 epan_dissect_cleanup(&rf_edt);
1257 /* This does a shallow copy of fdlocal, which is good enough. */
1258 fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1261 if (rec->opt_comment != NULL)
1262 cf->packet_comment_count++;
1263 cf->f_datalen = offset + fdlocal.cap_len;
1265 /* When a redissection is in progress (or queued), do not process packets.
1266 * This will be done once all (new) packets have been scanned. */
1267 if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) {
1268 add_packet_to_packet_list(fdata, cf, edt, dfcode,
1269 cinfo, rec, buf, TRUE);
1277 typedef struct _callback_data_t {
1280 GTimeVal start_time;
1288 merge_callback(merge_event event, int num _U_,
1289 const merge_in_file_t in_files[], const guint in_file_count,
1293 callback_data_t *cb_data = (callback_data_t*) data;
1295 g_assert(cb_data != NULL);
1299 case MERGE_EVENT_INPUT_FILES_OPENED:
1303 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1307 case MERGE_EVENT_READY_TO_MERGE:
1308 /* Get the sum of the sizes of all the files. */
1309 for (i = 0; i < in_file_count; i++)
1310 cb_data->f_len += in_files[i].size;
1312 cb_data->prog_timer = g_timer_new();
1313 g_timer_start(cb_data->prog_timer);
1315 g_get_current_time(&cb_data->start_time);
1318 case MERGE_EVENT_RECORD_WAS_READ:
1320 /* Create the progress bar if necessary.
1321 We check on every iteration of the loop, so that it takes no
1322 longer than the standard time to create it (otherwise, for a
1323 large file, we might take considerably longer than that standard
1324 time in order to get to the next progress bar step). */
1325 if (cb_data->progbar == NULL) {
1326 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1327 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1331 * Update the progress bar, but do it only after
1332 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1333 * and packets_bar_update will likely trigger UI paint events, which
1334 * might take a while depending on the platform and display. Reset
1335 * our timer *after* painting.
1337 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1339 gint64 file_pos = 0;
1340 /* Get the sum of the seek positions in all of the files. */
1341 for (i = 0; i < in_file_count; i++)
1342 file_pos += wtap_read_so_far(in_files[i].wth);
1344 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1345 if (progbar_val > 1.0f) {
1346 /* Some file probably grew while we were reading it.
1347 That "shouldn't happen", so we'll just clip the progress
1352 if (cb_data->progbar != NULL) {
1353 gchar status_str[100];
1354 g_snprintf(status_str, sizeof(status_str),
1355 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1356 file_pos / 1024, cb_data->f_len / 1024);
1357 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1359 g_timer_start(cb_data->prog_timer);
1364 case MERGE_EVENT_DONE:
1365 /* We're done merging the files; destroy the progress bar if it was created. */
1366 if (cb_data->progbar != NULL)
1367 destroy_progress_dlg(cb_data->progbar);
1368 g_timer_destroy(cb_data->prog_timer);
1372 return cb_data->stop_flag;
1378 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1379 int in_file_count, char *const *in_filenames,
1380 int file_type, gboolean do_append)
1383 gchar *err_info = NULL;
1385 guint32 err_framenum;
1386 merge_result status;
1387 merge_progress_callback_t cb;
1388 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1390 /* prepare our callback routine */
1391 cb_data->pd_window = pd_window;
1392 cb.callback_func = merge_callback;
1395 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1397 /* merge the files */
1398 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1399 (const char *const *) in_filenames,
1400 in_file_count, do_append,
1401 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1402 "Wireshark", &cb, &err, &err_info,
1403 &err_fileno, &err_framenum);
1411 case MERGE_USER_ABORTED:
1412 /* this isn't really an error, though we will return CF_ERROR later */
1415 case MERGE_ERR_CANT_OPEN_INFILE:
1416 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1419 case MERGE_ERR_CANT_OPEN_OUTFILE:
1420 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1423 case MERGE_ERR_CANT_READ_INFILE:
1424 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1427 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1428 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1429 err_framenum, in_filenames[err_fileno]);
1432 case MERGE_ERR_CANT_WRITE_OUTFILE:
1433 cfile_write_failure_alert_box(in_filenames[err_fileno],
1434 *out_filenamep, err, err_info,
1435 err_framenum, file_type);
1438 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1439 cfile_close_failure_alert_box(*out_filenamep, err);
1443 simple_error_message_box("Unknown merge_files error %d", status);
1447 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1449 if (status != MERGE_OK) {
1450 /* Callers aren't expected to treat an error or an explicit abort
1451 differently - we put up error dialogs ourselves, so they don't
1459 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1461 const char *filter_new = dftext ? dftext : "";
1462 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1465 GTimeVal start_time;
1467 /* if new filter equals old one, do nothing unless told to do so */
1468 if (!force && strcmp(filter_new, filter_old) == 0) {
1474 if (dftext == NULL) {
1475 /* The new filter is an empty filter (i.e., display all packets).
1476 * so leave dfcode==NULL
1480 * We have a filter; make a copy of it (as we'll be saving it),
1481 * and try to compile it.
1483 dftext = g_strdup(dftext);
1484 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1485 /* The attempt failed; report an error. */
1486 simple_message_box(ESD_TYPE_ERROR, NULL,
1487 "See the help for a description of the display filter syntax.",
1488 "\"%s\" isn't a valid display filter: %s",
1496 if (dfcode == NULL) {
1497 /* Yes - free the filter text, and set it to null. */
1503 /* We have a valid filter. Replace the current filter. */
1504 g_free(cf->dfilter);
1505 cf->dfilter = dftext;
1506 g_get_current_time(&start_time);
1509 /* Now rescan the packet list, applying the new filter, but not
1510 * throwing away information constructed on a previous pass.
1511 * If a dissection is already in progress, queue it.
1513 if (cf->redissection_queued == RESCAN_NONE) {
1514 if (cf->read_lock) {
1515 cf->redissection_queued = RESCAN_SCAN;
1516 } else if (cf->state != FILE_CLOSED) {
1517 if (dftext == NULL) {
1518 rescan_packets(cf, "Resetting", "Filter", FALSE);
1520 rescan_packets(cf, "Filtering", dftext, FALSE);
1525 /* Cleanup and release all dfilter resources */
1526 dfilter_free(dfcode);
1532 cf_reftime_packets(capture_file *cf)
1534 ref_time_packets(cf);
1538 cf_redissect_packets(capture_file *cf)
1540 if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) {
1541 /* Dissection in progress, signal redissection rather than rescanning. That
1542 * would destroy the current (in-progress) dissection in "cf_read" which
1543 * will cause issues when "cf_read" tries to add packets to the list.
1544 * If a previous rescan was requested, "upgrade" it to a full redissection.
1546 cf->redissection_queued = RESCAN_REDISSECT;
1548 if (cf->redissection_queued != RESCAN_NONE) {
1549 /* Redissection is (already) queued, wait for "cf_read" to finish. */
1553 if (cf->state != FILE_CLOSED) {
1554 /* Restart dissection in case no cf_read is pending. */
1555 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1560 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1561 wtap_rec *rec, Buffer *buf)
1566 if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
1567 cfile_read_failure_alert_box(cf->filename, err, err_info);
1574 cf_read_record(capture_file *cf, frame_data *fdata)
1576 return cf_read_record_r(cf, fdata, &cf->rec, &cf->buf);
1579 /* Rescan the list of packets, reconstructing the CList.
1581 "action" describes why we're doing this; it's used in the progress
1584 "action_item" describes what we're doing; it's used in the progress
1587 "redissect" is TRUE if we need to make the dissectors reconstruct
1588 any state information they have (because a preference that affects
1589 some dissector has changed, meaning some dissector might construct
1590 its state differently from the way it was constructed the last time). */
1592 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1594 /* Rescan packets new packet list */
1597 progdlg_t *progbar = NULL;
1598 GTimer *prog_timer = g_timer_new();
1600 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1601 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1602 gboolean selected_frame_seen;
1604 GTimeVal start_time;
1605 gchar status_str[100];
1609 gboolean create_proto_tree;
1611 gboolean add_to_packet_list = FALSE;
1613 guint32 frames_count;
1614 gboolean queued_rescan_type = RESCAN_NONE;
1616 /* Rescan in progress, clear pending actions. */
1617 cf->redissection_queued = RESCAN_NONE;
1618 g_assert(!cf->read_lock);
1619 cf->read_lock = TRUE;
1621 /* Compile the current display filter.
1622 * We assume this will not fail since cf->dfilter is only set in
1623 * cf_filter IFF the filter was valid.
1625 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1626 g_assert(!cf->dfilter || (compiled && dfcode));
1628 /* Get the union of the flags for all tap listeners. */
1629 tap_flags = union_of_tap_listener_flags();
1631 /* If any tap listeners require the columns, construct them. */
1632 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1635 * Determine whether we need to create a protocol tree.
1638 * we're going to apply a display filter;
1640 * one of the tap listeners is going to apply a filter;
1642 * one of the tap listeners requires a protocol tree;
1644 * we're redissecting and a postdissector wants field
1645 * values or protocols on the first pass.
1648 (dfcode != NULL || have_filtering_tap_listeners() ||
1649 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1650 (redissect && postdissectors_want_hfids()));
1652 reset_tap_listeners();
1653 /* Which frame, if any, is the currently selected frame?
1654 XXX - should the selected frame or the focus frame be the "current"
1655 frame, that frame being the one from which "Find Frame" searches
1657 selected_frame = cf->current_frame;
1659 /* Mark frame num as not found */
1660 selected_frame_num = -1;
1662 /* Freeze the packet list while we redo it, so we don't get any
1663 screen updates while it happens. */
1664 packet_list_freeze();
1667 /* We need to re-initialize all the state information that protocols
1668 keep, because some preference that controls a dissector has changed,
1669 which might cause the state information to be constructed differently
1670 by that dissector. */
1672 /* We might receive new packets while redissecting, and we don't
1673 want to dissect those before their time. */
1674 cf->redissecting = TRUE;
1676 /* 'reset' dissection session */
1677 epan_free(cf->epan);
1678 if (cf->edt && cf->edt->pi.fd) {
1679 /* All pointers in "per frame proto data" for the currently selected
1680 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1681 Free them here to avoid unintended usage in packet_list_clear(). */
1682 frame_data_destroy(cf->edt->pi.fd);
1684 cf->epan = ws_epan_new(cf);
1685 cf->cinfo.epan = cf->epan;
1687 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1688 called via epan_new() / init_dissection() when reloading Lua plugins. */
1689 if (!create_proto_tree && have_filtering_tap_listeners()) {
1690 create_proto_tree = TRUE;
1693 /* We need to redissect the packets so we have to discard our old
1694 * packet list store. */
1695 packet_list_clear();
1696 add_to_packet_list = TRUE;
1699 /* We don't yet know which will be the first and last frames displayed. */
1700 cf->first_displayed = 0;
1701 cf->last_displayed = 0;
1703 /* We currently don't display any packets */
1704 cf->displayed_count = 0;
1706 /* Iterate through the list of frames. Call a routine for each frame
1707 to check whether it should be displayed and, if so, add it to
1708 the display list. */
1709 cf->provider.ref = NULL;
1710 cf->provider.prev_dis = NULL;
1711 cf->provider.prev_cap = NULL;
1714 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1716 g_timer_start(prog_timer);
1717 /* Count of packets at which we've looked. */
1719 /* Progress so far. */
1722 cf->stop_flag = FALSE;
1723 g_get_current_time(&start_time);
1725 /* no previous row yet */
1726 prev_frame_num = -1;
1729 preceding_frame_num = -1;
1730 preceding_frame = NULL;
1731 following_frame_num = -1;
1732 following_frame = NULL;
1734 selected_frame_seen = FALSE;
1736 frames_count = cf->count;
1738 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1740 for (framenum = 1; framenum <= frames_count; framenum++) {
1741 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1743 /* Create the progress bar if necessary.
1744 We check on every iteration of the loop, so that it takes no
1745 longer than the standard time to create it (otherwise, for a
1746 large file, we might take considerably longer than that standard
1747 time in order to get to the next progress bar step). */
1748 if (progbar == NULL)
1749 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1755 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1756 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1757 * likely trigger UI paint events, which might take a while depending on
1758 * the platform and display. Reset our timer *after* painting.
1760 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1761 /* let's not divide by zero. I should never be started
1762 * with count == 0, so let's assert that
1764 g_assert(cf->count > 0);
1765 progbar_val = (gfloat) count / frames_count;
1767 if (progbar != NULL) {
1768 g_snprintf(status_str, sizeof(status_str),
1769 "%4u of %u frames", count, frames_count);
1770 update_progress_dlg(progbar, progbar_val, status_str);
1773 g_timer_start(prog_timer);
1776 queued_rescan_type = cf->redissection_queued;
1777 if (queued_rescan_type != RESCAN_NONE) {
1778 /* A redissection was requested while an existing redissection was
1783 if (cf->stop_flag) {
1784 /* Well, the user decided to abort the filtering. Just stop.
1786 XXX - go back to the previous filter? Users probably just
1787 want not to wait for a filtering operation to finish;
1788 unless we cancel by having no filter, reverting to the
1789 previous filter will probably be even more expensive than
1790 continuing the filtering, as it involves going back to the
1791 beginning and filtering, and even with no filter we currently
1792 have to re-generate the entire clist, which is also expensive.
1794 I'm not sure what Network Monitor does, but it doesn't appear
1795 to give you an unfiltered display if you cancel. */
1802 /* Since all state for the frame was destroyed, mark the frame
1803 * as not visited, free the GSList referring to the state
1804 * data (the per-frame data itself was freed by
1805 * "init_dissection()"), and null out the GSList pointer. */
1806 frame_data_reset(fdata);
1807 frames_count = cf->count;
1810 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1811 fdata->flags.dependent_of_displayed = 0;
1813 if (!cf_read_record(cf, fdata))
1814 break; /* error reading the frame */
1816 /* If the previous frame is displayed, and we haven't yet seen the
1817 selected frame, remember that frame - it's the closest one we've
1818 yet seen before the selected frame. */
1819 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1820 preceding_frame_num = prev_frame_num;
1821 preceding_frame = prev_frame;
1824 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1826 ws_buffer_start_ptr(&cf->buf),
1827 add_to_packet_list);
1829 /* If this frame is displayed, and this is the first frame we've
1830 seen displayed after the selected frame, remember this frame -
1831 it's the closest one we've yet seen at or after the selected
1833 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1834 following_frame_num = fdata->num;
1835 following_frame = fdata;
1837 if (fdata == selected_frame) {
1838 selected_frame_seen = TRUE;
1839 if (fdata->flags.passed_dfilter)
1840 selected_frame_num = fdata->num;
1843 /* Remember this frame - it'll be the previous frame
1844 on the next pass through the loop. */
1845 prev_frame_num = fdata->num;
1849 epan_dissect_cleanup(&edt);
1851 /* We are done redissecting the packet list. */
1852 cf->redissecting = FALSE;
1855 frames_count = cf->count;
1856 /* Clear out what remains of the visited flags and per-frame data
1859 XXX - that may cause various forms of bogosity when dissecting
1860 these frames, as they won't have been seen by this sequential
1861 pass, but the only alternative I see is to keep scanning them
1862 even though the user requested that the scan stop, and that
1863 would leave the user stuck with an Wireshark grinding on
1864 until it finishes. Should we just stick them with that? */
1865 for (; framenum <= frames_count; framenum++) {
1866 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1867 frame_data_reset(fdata);
1871 /* We're done filtering the packets; destroy the progress bar if it
1873 if (progbar != NULL)
1874 destroy_progress_dlg(progbar);
1875 g_timer_destroy(prog_timer);
1877 /* Unfreeze the packet list. */
1878 if (!add_to_packet_list)
1879 packet_list_recreate_visible_rows();
1881 /* Compute the time it took to filter the file */
1882 compute_elapsed(cf, &start_time);
1886 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1888 if (selected_frame_num == -1) {
1889 /* The selected frame didn't pass the filter. */
1890 if (selected_frame == NULL) {
1891 /* That's because there *was* no selected frame. Make the first
1892 displayed frame the current frame. */
1893 selected_frame_num = 0;
1895 /* Find the nearest displayed frame to the selected frame (whether
1896 it's before or after that frame) and make that the current frame.
1897 If the next and previous displayed frames are equidistant from the
1898 selected frame, choose the next one. */
1899 g_assert(following_frame == NULL ||
1900 following_frame->num >= selected_frame->num);
1901 g_assert(preceding_frame == NULL ||
1902 preceding_frame->num <= selected_frame->num);
1903 if (following_frame == NULL) {
1904 /* No frame after the selected frame passed the filter, so we
1905 have to select the last displayed frame before the selected
1907 selected_frame_num = preceding_frame_num;
1908 selected_frame = preceding_frame;
1909 } else if (preceding_frame == NULL) {
1910 /* No frame before the selected frame passed the filter, so we
1911 have to select the first displayed frame after the selected
1913 selected_frame_num = following_frame_num;
1914 selected_frame = following_frame;
1916 /* Frames before and after the selected frame passed the filter, so
1917 we'll select the previous frame */
1918 selected_frame_num = preceding_frame_num;
1919 selected_frame = preceding_frame;
1924 if (selected_frame_num == -1) {
1925 /* There are no frames displayed at all. */
1926 cf_unselect_packet(cf);
1928 /* Either the frame that was selected passed the filter, or we've
1929 found the nearest displayed frame to that frame. Select it, make
1930 it the focus row, and make it visible. */
1931 /* Set to invalid to force update of packet list and packet details */
1932 cf->current_row = -1;
1933 if (selected_frame_num == 0) {
1934 packet_list_select_first_row();
1936 if (!packet_list_select_row_from_data(selected_frame)) {
1937 /* We didn't find a row corresponding to this frame.
1938 This means that the frame isn't being displayed currently,
1939 so we can't select it. */
1940 simple_message_box(ESD_TYPE_INFO, NULL,
1941 "The capture file is probably not fully dissected.",
1942 "End of capture exceeded.");
1947 /* Cleanup and release all dfilter resources */
1948 dfilter_free(dfcode);
1950 /* It is safe again to execute redissections. */
1951 g_assert(cf->read_lock);
1952 cf->read_lock = FALSE;
1954 /* If another rescan (due to dfilter change) or redissection (due to profile
1955 * change) was requested, the rescan above is aborted and restarted here. */
1956 if (queued_rescan_type != RESCAN_NONE) {
1957 redissect = redissect || queued_rescan_type == RESCAN_REDISSECT;
1958 rescan_packets(cf, "Reprocessing", "all packets", redissect);
1964 * Scan through all frame data and recalculate the ref time
1965 * without rereading the file.
1966 * XXX - do we need a progres bar or is this fast enough?
1969 ref_time_packets(capture_file *cf)
1975 cf->provider.ref = NULL;
1976 cf->provider.prev_dis = NULL;
1979 for (framenum = 1; framenum <= cf->count; framenum++) {
1980 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1982 /* just add some value here until we know if it is being displayed or not */
1983 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1989 /* If we don't have the time stamp of the first packet in the
1990 capture, it's because this is the first packet. Save the time
1991 stamp of this packet as the time stamp of the first packet. */
1992 if (cf->provider.ref == NULL)
1993 cf->provider.ref = fdata;
1994 /* if this frames is marked as a reference time frame, reset
1995 firstsec and firstusec to this frame */
1996 if (fdata->flags.ref_time)
1997 cf->provider.ref = fdata;
1999 /* If we don't have the time stamp of the previous displayed packet,
2000 it's because this is the first displayed packet. Save the time
2001 stamp of this packet as the time stamp of the previous displayed
2003 if (cf->provider.prev_dis == NULL) {
2004 cf->provider.prev_dis = fdata;
2007 /* Get the time elapsed between the first packet and this packet. */
2008 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
2009 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
2011 /* If it's greater than the current elapsed time, set the elapsed time
2012 to it (we check for "greater than" so as not to be confused by
2013 time moving backwards). */
2014 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2015 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2016 cf->elapsed_time = rel_ts;
2019 /* If this frame is displayed, get the time elapsed between the
2020 previous displayed packet and this packet. */
2021 if ( fdata->flags.passed_dfilter ) {
2022 fdata->prev_dis_num = cf->provider.prev_dis->num;
2023 cf->provider.prev_dis = fdata;
2029 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2030 /* This frame either passed the display filter list or is marked as
2031 a time reference frame. All time reference frames are displayed
2032 even if they don't pass the display filter */
2033 if (fdata->flags.ref_time) {
2034 /* if this was a TIME REF frame we should reset the cum_bytes field */
2035 cf->cum_bytes = fdata->pkt_len;
2036 fdata->cum_bytes = cf->cum_bytes;
2038 /* increase cum_bytes with this packets length */
2039 cf->cum_bytes += fdata->pkt_len;
2052 process_specified_records(capture_file *cf, packet_range_t *range,
2053 const char *string1, const char *string2, gboolean terminate_is_stop,
2054 gboolean (*callback)(capture_file *, frame_data *,
2055 wtap_rec *, const guint8 *, void *),
2056 void *callback_args,
2057 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;
2073 wtap_rec_init(&rec);
2074 ws_buffer_init(&buf, 1500);
2076 g_timer_start(prog_timer);
2077 /* Count of packets at which we've looked. */
2079 /* Progress so far. */
2082 if (cf->read_lock) {
2083 g_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename);
2086 cf->read_lock = TRUE;
2088 cf->stop_flag = FALSE;
2089 g_get_current_time(&progbar_start_time);
2092 packet_range_process_init(range);
2094 /* Iterate through all the packets, printing the packets that
2095 were selected by the current display filter. */
2096 for (framenum = 1; framenum <= cf->count; framenum++) {
2097 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
2099 /* Create the progress bar if necessary.
2100 We check on every iteration of the loop, so that it takes no
2101 longer than the standard time to create it (otherwise, for a
2102 large file, we might take considerably longer than that standard
2103 time in order to get to the next progress bar step). */
2104 if (show_progress_bar && progbar == NULL)
2105 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2108 &progbar_start_time,
2112 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2113 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2114 * likely trigger UI paint events, which might take a while depending on
2115 * the platform and display. Reset our timer *after* painting.
2117 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2118 /* let's not divide by zero. I should never be started
2119 * with count == 0, so let's assert that
2121 g_assert(cf->count > 0);
2122 progbar_val = (gfloat) progbar_count / cf->count;
2124 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2125 "%4u of %u packets", progbar_count, cf->count);
2126 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2128 g_timer_start(prog_timer);
2131 if (cf->stop_flag) {
2132 /* Well, the user decided to abort the operation. Just stop,
2133 and arrange to return PSP_STOPPED to our caller, so they know
2134 it was stopped explicitly. */
2141 if (range != NULL) {
2142 /* do we have to process this packet? */
2143 process_this = packet_range_process_packet(range, fdata);
2144 if (process_this == range_process_next) {
2145 /* this packet uninteresting, continue with next one */
2147 } else if (process_this == range_processing_finished) {
2148 /* all interesting packets processed, stop the loop */
2153 /* Get the packet */
2154 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2155 /* Attempt to get the packet failed. */
2159 /* Process the packet */
2160 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2161 /* Callback failed. We assume it reported the error appropriately. */
2167 /* We're done printing the packets; destroy the progress bar if
2169 if (progbar != NULL)
2170 destroy_progress_dlg(progbar);
2171 g_timer_destroy(prog_timer);
2173 g_assert(cf->read_lock);
2174 cf->read_lock = FALSE;
2176 wtap_rec_cleanup(&rec);
2177 ws_buffer_free(&buf);
2185 } retap_callback_args_t;
2188 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2189 const guint8 *pd, void *argsp)
2191 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2193 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2194 frame_tvbuff_new(&cf->provider, fdata, pd),
2195 fdata, args->cinfo);
2196 epan_dissect_reset(&args->edt);
2202 cf_retap_packets(capture_file *cf)
2204 packet_range_t range;
2205 retap_callback_args_t callback_args;
2206 gboolean create_proto_tree;
2210 /* Presumably the user closed the capture file. */
2212 return CF_READ_ABORTED;
2215 cf_callback_invoke(cf_cb_file_retap_started, cf);
2217 /* Get the union of the flags for all tap listeners. */
2218 tap_flags = union_of_tap_listener_flags();
2220 /* If any tap listeners require the columns, construct them. */
2221 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2224 * Determine whether we need to create a protocol tree.
2227 * one of the tap listeners is going to apply a filter;
2229 * one of the tap listeners requires a protocol tree.
2232 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2234 /* Reset the tap listeners. */
2235 reset_tap_listeners();
2237 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2239 /* Iterate through the list of packets, dissecting all packets and
2240 re-running the taps. */
2241 packet_range_init(&range, cf);
2242 packet_range_process_init(&range);
2244 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2245 "all packets", TRUE, retap_packet,
2246 &callback_args, TRUE);
2248 packet_range_cleanup(&range);
2249 epan_dissect_cleanup(&callback_args.edt);
2251 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2255 /* Completed successfully. */
2259 /* Well, the user decided to abort the refiltering.
2260 Return CF_READ_ABORTED so our caller knows they did that. */
2261 return CF_READ_ABORTED;
2264 /* Error while retapping. */
2265 return CF_READ_ERROR;
2268 g_assert_not_reached();
2273 print_args_t *print_args;
2274 gboolean print_header_line;
2275 char *header_line_buf;
2276 int header_line_buf_len;
2277 gboolean print_formfeed;
2278 gboolean print_separator;
2282 int num_visible_cols;
2285 } print_callback_args_t;
2288 print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2289 const guint8 *pd, void *argsp)
2291 print_callback_args_t *args = (print_callback_args_t *)argsp;
2297 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2298 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2299 col_item_t* col_item;
2301 /* Fill in the column information if we're printing the summary
2303 if (args->print_args->print_summary) {
2304 col_custom_prime_edt(&args->edt, &cf->cinfo);
2305 epan_dissect_run(&args->edt, cf->cd_t, rec,
2306 frame_tvbuff_new(&cf->provider, fdata, pd),
2308 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2310 epan_dissect_run(&args->edt, cf->cd_t, rec,
2311 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2313 if (args->print_formfeed) {
2314 if (!new_page(args->print_args->stream))
2318 * Print another header line if we print a packet summary on the
2321 if (args->print_args->print_col_headings)
2322 args->print_header_line = TRUE;
2324 if (args->print_separator) {
2325 if (!print_line(args->print_args->stream, 0, ""))
2331 * We generate bookmarks, if the output format supports them.
2332 * The name is "__frameN__".
2334 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2336 if (args->print_args->print_summary) {
2337 if (!args->print_args->print_col_headings)
2338 args->print_header_line = FALSE;
2339 if (args->print_header_line) {
2340 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2342 args->print_header_line = FALSE; /* we might not need to print any more */
2344 cp = &args->line_buf[0];
2346 for (i = 0; i < args->num_visible_cols; i++) {
2347 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2348 /* Find the length of the string for this column. */
2349 column_len = (int) strlen(col_item->col_data);
2350 if (args->col_widths[i] > column_len)
2351 column_len = args->col_widths[i];
2353 /* Make sure there's room in the line buffer for the column; if not,
2354 double its length. */
2355 line_len += column_len + 1; /* "+1" for space */
2356 if (line_len > args->line_buf_len) {
2357 cp_off = (int) (cp - args->line_buf);
2358 args->line_buf_len = 2 * line_len;
2359 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2360 cp = args->line_buf + cp_off;
2363 /* Right-justify the packet number column. */
2364 if (col_item->col_fmt == COL_NUMBER)
2365 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2367 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2369 if (i != args->num_visible_cols - 1)
2375 * Generate a bookmark, using the summary line as the title.
2377 if (!print_bookmark(args->print_args->stream, bookmark_name,
2381 if (!print_line(args->print_args->stream, 0, args->line_buf))
2385 * Generate a bookmark, using "Frame N" as the title, as we're not
2386 * printing the summary line.
2388 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2389 if (!print_bookmark(args->print_args->stream, bookmark_name,
2392 } /* if (print_summary) */
2394 if (args->print_args->print_dissections != print_dissections_none) {
2395 if (args->print_args->print_summary) {
2396 /* Separate the summary line from the tree with a blank line. */
2397 if (!print_line(args->print_args->stream, 0, ""))
2401 /* Print the information in that tree. */
2402 if (!proto_tree_print(args->print_args->print_dissections,
2403 args->print_args->print_hex, &args->edt, NULL,
2404 args->print_args->stream))
2407 /* Print a blank line if we print anything after this (aka more than one packet). */
2408 args->print_separator = TRUE;
2410 /* Print a header line if we print any more packet summaries */
2411 if (args->print_args->print_col_headings)
2412 args->print_header_line = TRUE;
2415 if (args->print_args->print_hex) {
2416 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2417 if (!print_line(args->print_args->stream, 0, ""))
2420 /* Print the full packet data as hex. */
2421 if (!print_hex_data(args->print_args->stream, &args->edt))
2424 /* Print a blank line if we print anything after this (aka more than one packet). */
2425 args->print_separator = TRUE;
2427 /* Print a header line if we print any more packet summaries */
2428 if (args->print_args->print_col_headings)
2429 args->print_header_line = TRUE;
2430 } /* if (args->print_args->print_dissections != print_dissections_none) */
2432 epan_dissect_reset(&args->edt);
2434 /* do we want to have a formfeed between each packet from now on? */
2435 if (args->print_args->print_formfeed) {
2436 args->print_formfeed = TRUE;
2442 epan_dissect_reset(&args->edt);
2447 cf_print_packets(capture_file *cf, print_args_t *print_args,
2448 gboolean show_progress_bar)
2450 print_callback_args_t callback_args;
2453 int i, cp_off, column_len, line_len;
2454 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2458 gboolean proto_tree_needed;
2460 callback_args.print_args = print_args;
2461 callback_args.print_header_line = print_args->print_col_headings;
2462 callback_args.header_line_buf = NULL;
2463 callback_args.header_line_buf_len = 256;
2464 callback_args.print_formfeed = FALSE;
2465 callback_args.print_separator = FALSE;
2466 callback_args.line_buf = NULL;
2467 callback_args.line_buf_len = 256;
2468 callback_args.col_widths = NULL;
2469 callback_args.num_visible_cols = 0;
2470 callback_args.visible_cols = NULL;
2472 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2473 destroy_print_stream(print_args->stream);
2474 return CF_PRINT_WRITE_ERROR;
2477 if (print_args->print_summary) {
2478 /* We're printing packet summaries. Allocate the header line buffer
2479 and get the column widths. */
2480 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2482 /* Find the number of visible columns and the last visible column */
2483 for (i = 0; i < prefs.num_cols; i++) {
2485 clp = g_list_nth(prefs.col_list, i);
2486 if (clp == NULL) /* Sanity check, Invalid column requested */
2489 cfmt = (fmt_data *) clp->data;
2490 if (cfmt->visible) {
2492 last_visible_col = i;
2496 /* if num_visible_col is 0, we are done */
2497 if (num_visible_col == 0) {
2498 g_free(callback_args.header_line_buf);
2502 /* Find the widths for each of the columns - maximum of the
2503 width of the title and the width of the data - and construct
2504 a buffer with a line containing the column titles. */
2505 callback_args.num_visible_cols = num_visible_col;
2506 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2507 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2508 cp = &callback_args.header_line_buf[0];
2510 visible_col_count = 0;
2511 for (i = 0; i < cf->cinfo.num_cols; i++) {
2513 clp = g_list_nth(prefs.col_list, i);
2514 if (clp == NULL) /* Sanity check, Invalid column requested */
2517 cfmt = (fmt_data *) clp->data;
2518 if (cfmt->visible == FALSE)
2521 /* Save the order of visible columns */
2522 callback_args.visible_cols[visible_col_count] = i;
2524 /* Don't pad the last column. */
2525 if (i == last_visible_col)
2526 callback_args.col_widths[visible_col_count] = 0;
2528 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2529 data_width = get_column_char_width(get_column_format(i));
2530 if (data_width > callback_args.col_widths[visible_col_count])
2531 callback_args.col_widths[visible_col_count] = data_width;
2534 /* Find the length of the string for this column. */
2535 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2536 if (callback_args.col_widths[visible_col_count] > column_len)
2537 column_len = callback_args.col_widths[visible_col_count];
2539 /* Make sure there's room in the line buffer for the column; if not,
2540 double its length. */
2541 line_len += column_len + 1; /* "+1" for space */
2542 if (line_len > callback_args.header_line_buf_len) {
2543 cp_off = (int) (cp - callback_args.header_line_buf);
2544 callback_args.header_line_buf_len = 2 * line_len;
2545 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2546 callback_args.header_line_buf_len + 1);
2547 cp = callback_args.header_line_buf + cp_off;
2550 /* Right-justify the packet number column. */
2551 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2552 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2554 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2556 if (i != cf->cinfo.num_cols - 1)
2559 visible_col_count++;
2563 /* Now start out the main line buffer with the same length as the
2564 header line buffer. */
2565 callback_args.line_buf_len = callback_args.header_line_buf_len;
2566 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2567 } /* if (print_summary) */
2569 /* Create the protocol tree, and make it visible, if we're printing
2570 the dissection or the hex data.
2571 XXX - do we need it if we're just printing the hex data? */
2573 callback_args.print_args->print_dissections != print_dissections_none ||
2574 callback_args.print_args->print_hex ||
2575 have_custom_cols(&cf->cinfo) || have_field_extractors();
2576 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2578 /* Iterate through the list of packets, printing the packets we were
2580 ret = process_specified_records(cf, &print_args->range, "Printing",
2581 "selected packets", TRUE, print_packet,
2582 &callback_args, show_progress_bar);
2583 epan_dissect_cleanup(&callback_args.edt);
2584 g_free(callback_args.header_line_buf);
2585 g_free(callback_args.line_buf);
2586 g_free(callback_args.col_widths);
2587 g_free(callback_args.visible_cols);
2592 /* Completed successfully. */
2596 /* Well, the user decided to abort the printing.
2598 XXX - note that what got generated before they did that
2599 will get printed if we're piping to a print program; we'd
2600 have to write to a file and then hand that to the print
2601 program to make it actually not print anything. */
2605 /* Error while printing.
2607 XXX - note that what got generated before they did that
2608 will get printed if we're piping to a print program; we'd
2609 have to write to a file and then hand that to the print
2610 program to make it actually not print anything. */
2611 destroy_print_stream(print_args->stream);
2612 return CF_PRINT_WRITE_ERROR;
2615 if (!print_finale(print_args->stream)) {
2616 destroy_print_stream(print_args->stream);
2617 return CF_PRINT_WRITE_ERROR;
2620 if (!destroy_print_stream(print_args->stream))
2621 return CF_PRINT_WRITE_ERROR;
2629 print_args_t *print_args;
2630 } write_packet_callback_args_t;
2633 write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2634 const guint8 *pd, void *argsp)
2636 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2638 /* Create the protocol tree, but don't fill in the column information. */
2639 epan_dissect_run(&args->edt, cf->cd_t, rec,
2640 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2642 /* Write out the information in that tree. */
2643 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE);
2645 epan_dissect_reset(&args->edt);
2647 return !ferror(args->fh);
2651 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2653 write_packet_callback_args_t callback_args;
2657 fh = ws_fopen(print_args->file, "w");
2659 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2661 write_pdml_preamble(fh, cf->filename);
2664 return CF_PRINT_WRITE_ERROR;
2667 callback_args.fh = fh;
2668 callback_args.print_args = print_args;
2669 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2671 /* Iterate through the list of packets, printing the packets we were
2673 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2674 "selected packets", TRUE,
2675 write_pdml_packet, &callback_args, TRUE);
2677 epan_dissect_cleanup(&callback_args.edt);
2682 /* Completed successfully. */
2686 /* Well, the user decided to abort the printing. */
2690 /* Error while printing. */
2692 return CF_PRINT_WRITE_ERROR;
2695 write_pdml_finale(fh);
2698 return CF_PRINT_WRITE_ERROR;
2701 /* XXX - check for an error */
2708 write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2709 const guint8 *pd, void *argsp)
2711 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2713 /* Fill in the column information */
2714 col_custom_prime_edt(&args->edt, &cf->cinfo);
2715 epan_dissect_run(&args->edt, cf->cd_t, rec,
2716 frame_tvbuff_new(&cf->provider, fdata, pd),
2718 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2720 /* Write out the column information. */
2721 write_psml_columns(&args->edt, args->fh, FALSE);
2723 epan_dissect_reset(&args->edt);
2725 return !ferror(args->fh);
2729 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2731 write_packet_callback_args_t callback_args;
2735 gboolean proto_tree_needed;
2737 fh = ws_fopen(print_args->file, "w");
2739 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2741 write_psml_preamble(&cf->cinfo, fh);
2744 return CF_PRINT_WRITE_ERROR;
2747 callback_args.fh = fh;
2748 callback_args.print_args = print_args;
2750 /* Fill in the column information, only create the protocol tree
2751 if having custom columns or field extractors. */
2752 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2753 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2755 /* Iterate through the list of packets, printing the packets we were
2757 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2758 "selected packets", TRUE,
2759 write_psml_packet, &callback_args, TRUE);
2761 epan_dissect_cleanup(&callback_args.edt);
2766 /* Completed successfully. */
2770 /* Well, the user decided to abort the printing. */
2774 /* Error while printing. */
2776 return CF_PRINT_WRITE_ERROR;
2779 write_psml_finale(fh);
2782 return CF_PRINT_WRITE_ERROR;
2785 /* XXX - check for an error */
2792 write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2793 const guint8 *pd, void *argsp)
2795 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2797 /* Fill in the column information */
2798 col_custom_prime_edt(&args->edt, &cf->cinfo);
2799 epan_dissect_run(&args->edt, cf->cd_t, rec,
2800 frame_tvbuff_new(&cf->provider, fdata, pd),
2802 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2804 /* Write out the column information. */
2805 write_csv_columns(&args->edt, args->fh);
2807 epan_dissect_reset(&args->edt);
2809 return !ferror(args->fh);
2813 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2815 write_packet_callback_args_t callback_args;
2816 gboolean proto_tree_needed;
2820 fh = ws_fopen(print_args->file, "w");
2822 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2824 write_csv_column_titles(&cf->cinfo, fh);
2827 return CF_PRINT_WRITE_ERROR;
2830 callback_args.fh = fh;
2831 callback_args.print_args = print_args;
2833 /* only create the protocol tree if having custom columns or field extractors. */
2834 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2835 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2837 /* Iterate through the list of packets, printing the packets we were
2839 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2840 "selected packets", TRUE,
2841 write_csv_packet, &callback_args, TRUE);
2843 epan_dissect_cleanup(&callback_args.edt);
2848 /* Completed successfully. */
2852 /* Well, the user decided to abort the printing. */
2856 /* Error while printing. */
2858 return CF_PRINT_WRITE_ERROR;
2861 /* XXX - check for an error */
2868 carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2869 const guint8 *pd, void *argsp)
2871 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2873 epan_dissect_run(&args->edt, cf->cd_t, rec,
2874 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2875 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2876 epan_dissect_reset(&args->edt);
2878 return !ferror(args->fh);
2882 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2884 write_packet_callback_args_t callback_args;
2888 fh = ws_fopen(print_args->file, "w");
2891 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2895 return CF_PRINT_WRITE_ERROR;
2898 callback_args.fh = fh;
2899 callback_args.print_args = print_args;
2900 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2902 /* Iterate through the list of packets, printing the packets we were
2904 ret = process_specified_records(cf, &print_args->range,
2906 "selected packets", TRUE,
2907 carrays_write_packet, &callback_args, TRUE);
2909 epan_dissect_cleanup(&callback_args.edt);
2913 /* Completed successfully. */
2916 /* Well, the user decided to abort the printing. */
2919 /* Error while printing. */
2921 return CF_PRINT_WRITE_ERROR;
2929 write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2930 const guint8 *pd, void *argsp)
2932 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2934 /* Create the protocol tree, but don't fill in the column information. */
2935 epan_dissect_run(&args->edt, cf->cd_t, rec,
2936 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2938 /* Write out the information in that tree. */
2939 write_json_proto_tree(NULL, args->print_args->print_dissections,
2940 args->print_args->print_hex, NULL, PF_NONE,
2941 &args->edt, &cf->cinfo, proto_node_group_children_by_unique, args->fh);
2943 epan_dissect_reset(&args->edt);
2945 return !ferror(args->fh);
2949 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2951 write_packet_callback_args_t callback_args;
2955 fh = ws_fopen(print_args->file, "w");
2957 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2959 write_json_preamble(fh);
2962 return CF_PRINT_WRITE_ERROR;
2965 callback_args.fh = fh;
2966 callback_args.print_args = print_args;
2967 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2969 /* Iterate through the list of packets, printing the packets we were
2971 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2972 "selected packets", TRUE,
2973 write_json_packet, &callback_args, TRUE);
2975 epan_dissect_cleanup(&callback_args.edt);
2980 /* Completed successfully. */
2984 /* Well, the user decided to abort the printing. */
2988 /* Error while printing. */
2990 return CF_PRINT_WRITE_ERROR;
2993 write_json_finale(fh);
2996 return CF_PRINT_WRITE_ERROR;
2999 /* XXX - check for an error */
3006 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3007 search_direction dir)
3011 mdata.string = string;
3012 mdata.string_len = strlen(string);
3013 return find_packet(cf, match_protocol_tree, &mdata, dir);
3017 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3019 mdata->frame_matched = FALSE;
3020 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3021 mdata->string_len = strlen(mdata->string);
3023 /* Iterate through all the nodes looking for matching text */
3024 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3025 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3029 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3031 match_data *mdata = (match_data *)criterion;
3034 /* Load the frame's data. */
3035 if (!cf_read_record(cf, fdata)) {
3036 /* Attempt to get the packet failed. */
3040 /* Construct the protocol tree, including the displayed text */
3041 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3042 /* We don't need the column information */
3043 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3044 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3047 /* Iterate through all the nodes, seeing if they have text that matches. */
3049 mdata->frame_matched = FALSE;
3050 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3051 epan_dissect_cleanup(&edt);
3052 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3056 match_subtree_text(proto_node *node, gpointer data)
3058 match_data *mdata = (match_data *) data;
3059 const gchar *string = mdata->string;
3060 size_t string_len = mdata->string_len;
3061 capture_file *cf = mdata->cf;
3062 field_info *fi = PNODE_FINFO(node);
3063 gchar label_str[ITEM_LABEL_LENGTH];
3070 /* dissection with an invisible proto tree? */
3073 if (mdata->frame_matched) {
3074 /* We already had a match; don't bother doing any more work. */
3078 /* Don't match invisible entries. */
3079 if (PROTO_ITEM_IS_HIDDEN(node))
3082 /* was a free format label produced? */
3084 label_ptr = fi->rep->representation;
3086 /* no, make a generic label */
3087 label_ptr = label_str;
3088 proto_item_fill_label(fi, label_str);
3092 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3093 mdata->frame_matched = TRUE;
3098 /* Does that label match? */
3099 label_len = strlen(label_ptr);
3100 for (i = 0; i < label_len; i++) {
3101 c_char = label_ptr[i];
3103 c_char = g_ascii_toupper(c_char);
3104 if (c_char == string[c_match]) {
3106 if (c_match == string_len) {
3107 /* No need to look further; we have a match */
3108 mdata->frame_matched = TRUE;
3117 /* Recurse into the subtree, if it exists */
3118 if (node->first_child != NULL)
3119 proto_tree_children_foreach(node, match_subtree_text, mdata);
3123 cf_find_packet_summary_line(capture_file *cf, const char *string,
3124 search_direction dir)
3128 mdata.string = string;
3129 mdata.string_len = strlen(string);
3130 return find_packet(cf, match_summary_line, &mdata, dir);
3134 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3136 match_data *mdata = (match_data *)criterion;
3137 const gchar *string = mdata->string;
3138 size_t string_len = mdata->string_len;
3140 const char *info_column;
3141 size_t info_column_len;
3142 match_result result = MR_NOTMATCHED;
3148 /* Load the frame's data. */
3149 if (!cf_read_record(cf, fdata)) {
3150 /* Attempt to get the packet failed. */
3154 /* Don't bother constructing the protocol tree */
3155 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3156 /* Get the column information */
3157 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3158 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3161 /* Find the Info column */
3162 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3163 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3164 /* Found it. See if we match. */
3165 info_column = edt.pi.cinfo->columns[colx].col_data;
3166 info_column_len = strlen(info_column);
3168 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3169 result = MR_MATCHED;
3173 for (i = 0; i < info_column_len; i++) {
3174 c_char = info_column[i];
3176 c_char = g_ascii_toupper(c_char);
3177 if (c_char == string[c_match]) {
3179 if (c_match == string_len) {
3180 result = MR_MATCHED;
3190 epan_dissect_cleanup(&edt);
3197 } cbs_t; /* "Counted byte string" */
3201 * The current match_* routines only support ASCII case insensitivity and don't
3202 * convert UTF-8 inputs to UTF-16 for matching.
3204 * We could modify them to use the GLib Unicode routines or the International
3205 * Components for Unicode library but it's not apparent that we could do so
3206 * without consuming a lot more CPU and memory or that searching would be
3207 * significantly better.
3211 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3212 search_direction dir)
3217 info.data_len = string_size;
3219 /* Regex, String or hex search? */
3221 /* Regular Expression search */
3222 return find_packet(cf, match_regex, NULL, dir);
3223 } else if (cf->string) {
3224 /* String search - what type of string? */
3225 switch (cf->scs_type) {
3227 case SCS_NARROW_AND_WIDE:
3228 return find_packet(cf, match_narrow_and_wide, &info, dir);
3231 return find_packet(cf, match_narrow, &info, dir);
3234 return find_packet(cf, match_wide, &info, dir);
3237 g_assert_not_reached();
3241 return find_packet(cf, match_binary, &info, dir);
3245 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3247 cbs_t *info = (cbs_t *)criterion;
3248 const guint8 *ascii_text = info->data;
3249 size_t textlen = info->data_len;
3250 match_result result;
3257 /* Load the frame's data. */
3258 if (!cf_read_record(cf, fdata)) {
3259 /* Attempt to get the packet failed. */
3263 result = MR_NOTMATCHED;
3264 buf_len = fdata->cap_len;
3265 pd = ws_buffer_start_ptr(&cf->buf);
3267 while (i < buf_len) {
3270 c_char = g_ascii_toupper(c_char);
3271 if (c_char != '\0') {
3272 if (c_char == ascii_text[c_match]) {
3274 if (c_match == textlen) {
3275 result = MR_MATCHED;
3276 cf->search_pos = i; /* Save the position of the last character
3277 for highlighting the field. */
3278 cf->search_len = (guint32)textlen;
3283 g_assert(i>=c_match);
3284 i -= (guint32)c_match;
3294 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3297 cbs_t *info = (cbs_t *)criterion;
3298 const guint8 *ascii_text = info->data;
3299 size_t textlen = info->data_len;
3300 match_result result;
3306 /* Load the frame's data. */
3307 if (!cf_read_record(cf, fdata)) {
3308 /* Attempt to get the packet failed. */
3312 result = MR_NOTMATCHED;
3313 buf_len = fdata->cap_len;
3314 pd = ws_buffer_start_ptr(&cf->buf);
3316 while (i < buf_len) {
3319 c_char = g_ascii_toupper(c_char);
3320 if (c_char == ascii_text[c_match]) {
3322 if (c_match == textlen) {
3323 result = MR_MATCHED;
3324 cf->search_pos = i; /* Save the position of the last character
3325 for highlighting the field. */
3326 cf->search_len = (guint32)textlen;
3331 g_assert(i>=c_match);
3332 i -= (guint32)c_match;
3342 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3344 cbs_t *info = (cbs_t *)criterion;
3345 const guint8 *ascii_text = info->data;
3346 size_t textlen = info->data_len;
3347 match_result result;
3354 /* Load the frame's data. */
3355 if (!cf_read_record(cf, fdata)) {
3356 /* Attempt to get the packet failed. */
3360 result = MR_NOTMATCHED;
3361 buf_len = fdata->cap_len;
3362 pd = ws_buffer_start_ptr(&cf->buf);
3364 while (i < buf_len) {
3367 c_char = g_ascii_toupper(c_char);
3368 if (c_char == ascii_text[c_match]) {
3370 if (c_match == textlen) {
3371 result = MR_MATCHED;
3372 cf->search_pos = i; /* Save the position of the last character
3373 for highlighting the field. */
3374 cf->search_len = (guint32)textlen;
3380 g_assert(i>=(c_match*2));
3381 i -= (guint32)c_match*2;
3390 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3392 cbs_t *info = (cbs_t *)criterion;
3393 const guint8 *binary_data = info->data;
3394 size_t datalen = info->data_len;
3395 match_result result;
3401 /* Load the frame's data. */
3402 if (!cf_read_record(cf, fdata)) {
3403 /* Attempt to get the packet failed. */
3407 result = MR_NOTMATCHED;
3408 buf_len = fdata->cap_len;
3409 pd = ws_buffer_start_ptr(&cf->buf);
3411 while (i < buf_len) {
3412 if (pd[i] == binary_data[c_match]) {
3414 if (c_match == datalen) {
3415 result = MR_MATCHED;
3416 cf->search_pos = i; /* Save the position of the last character
3417 for highlighting the field. */
3418 cf->search_len = (guint32)datalen;
3423 g_assert(i>=c_match);
3424 i -= (guint32)c_match;
3433 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3435 match_result result = MR_NOTMATCHED;
3436 GMatchInfo *match_info = NULL;
3438 /* Load the frame's data. */
3439 if (!cf_read_record(cf, fdata)) {
3440 /* Attempt to get the packet failed. */
3444 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3445 0, (GRegexMatchFlags) 0, &match_info, NULL))
3447 gint start_pos = 0, end_pos = 0;
3448 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3449 cf->search_pos = end_pos - 1;
3450 cf->search_len = end_pos - start_pos;
3451 result = MR_MATCHED;
3457 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3458 search_direction dir)
3460 return find_packet(cf, match_dfilter, sfcode, dir);
3464 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3465 search_direction dir)
3470 if (!dfilter_compile(filter, &sfcode, NULL)) {
3472 * XXX - this shouldn't happen, as the filter string is machine
3477 if (sfcode == NULL) {
3479 * XXX - this shouldn't happen, as the filter string is machine
3484 result = find_packet(cf, match_dfilter, sfcode, dir);
3485 dfilter_free(sfcode);
3490 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3492 dfilter_t *sfcode = (dfilter_t *)criterion;
3494 match_result result;
3496 /* Load the frame's data. */
3497 if (!cf_read_record(cf, fdata)) {
3498 /* Attempt to get the packet failed. */
3502 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3503 epan_dissect_prime_with_dfilter(&edt, sfcode);
3504 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3505 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3507 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3508 epan_dissect_cleanup(&edt);
3513 cf_find_packet_marked(capture_file *cf, search_direction dir)
3515 return find_packet(cf, match_marked, NULL, dir);
3519 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3521 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3525 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3527 return find_packet(cf, match_time_reference, NULL, dir);
3531 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3533 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3537 find_packet(capture_file *cf,
3538 match_result (*match_function)(capture_file *, frame_data *, void *),
3539 void *criterion, search_direction dir)
3541 frame_data *start_fd;
3543 guint32 prev_framenum;
3545 frame_data *new_fd = NULL;
3546 progdlg_t *progbar = NULL;
3547 GTimer *prog_timer = g_timer_new();
3551 GTimeVal start_time;
3552 gchar status_str[100];
3554 match_result result;
3556 start_fd = cf->current_frame;
3557 if (start_fd != NULL) {
3558 prev_framenum = start_fd->num;
3560 prev_framenum = 0; /* No start packet selected. */
3563 /* Iterate through the list of packets, starting at the packet we've
3564 picked, calling a routine to run the filter on the packet, see if
3565 it matches, and stop if so. */
3567 framenum = prev_framenum;
3569 g_timer_start(prog_timer);
3570 /* Progress so far. */
3573 cf->stop_flag = FALSE;
3574 g_get_current_time(&start_time);
3576 title = cf->sfilter?cf->sfilter:"";
3578 /* Create the progress bar if necessary.
3579 We check on every iteration of the loop, so that it takes no
3580 longer than the standard time to create it (otherwise, for a
3581 large file, we might take considerably longer than that standard
3582 time in order to get to the next progress bar step). */
3583 if (progbar == NULL)
3584 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3585 FALSE, &cf->stop_flag, &start_time, progbar_val);
3588 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3589 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3590 * likely trigger UI paint events, which might take a while depending on
3591 * the platform and display. Reset our timer *after* painting.
3593 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3594 /* let's not divide by zero. I should never be started
3595 * with count == 0, so let's assert that
3597 g_assert(cf->count > 0);
3599 progbar_val = (gfloat) count / cf->count;
3601 g_snprintf(status_str, sizeof(status_str),
3602 "%4u of %u packets", count, cf->count);
3603 update_progress_dlg(progbar, progbar_val, status_str);
3605 g_timer_start(prog_timer);
3608 if (cf->stop_flag) {
3609 /* Well, the user decided to abort the search. Go back to the
3610 frame where we started. */
3615 /* Go past the current frame. */
3616 if (dir == SD_BACKWARD) {
3617 /* Go on to the previous frame. */
3618 if (framenum <= 1) {
3620 * XXX - other apps have a bit more of a detailed message
3621 * for this, and instead of offering "OK" and "Cancel",
3622 * they offer things such as "Continue" and "Cancel";
3623 * we need an API for popping up alert boxes with
3624 * {Verb} and "Cancel".
3627 if (prefs.gui_find_wrap) {
3628 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3629 framenum = cf->count; /* wrap around */
3631 statusbar_push_temporary_msg("Search reached the beginning.");
3632 framenum = prev_framenum; /* stay on previous packet */
3637 /* Go on to the next frame. */
3638 if (framenum == cf->count) {
3639 if (prefs.gui_find_wrap) {
3640 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3641 framenum = 1; /* wrap around */
3643 statusbar_push_temporary_msg("Search reached the end.");
3644 framenum = prev_framenum; /* stay on previous packet */
3650 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3653 /* Is this packet in the display? */
3654 if (fdata && fdata->flags.passed_dfilter) {
3655 /* Yes. Does it match the search criterion? */
3656 result = (*match_function)(cf, fdata, criterion);
3657 if (result == MR_ERROR) {
3658 /* Error; our caller has reported the error. Go back to the frame
3659 where we started. */
3662 } else if (result == MR_MATCHED) {
3663 /* Yes. Go to the new frame. */
3669 if (fdata == start_fd) {
3670 /* We're back to the frame we were on originally, and that frame
3671 doesn't match the search filter. The search failed. */
3676 /* We're done scanning the packets; destroy the progress bar if it
3678 if (progbar != NULL)
3679 destroy_progress_dlg(progbar);
3680 g_timer_destroy(prog_timer);
3682 if (new_fd != NULL) {
3683 /* Find and select */
3684 cf->search_in_progress = TRUE;
3685 found = packet_list_select_row_from_data(new_fd);
3686 cf->search_in_progress = FALSE;
3687 cf->search_pos = 0; /* Reset the position */
3688 cf->search_len = 0; /* Reset length */
3690 /* We didn't find a row corresponding to this frame.
3691 This means that the frame isn't being displayed currently,
3692 so we can't select it. */
3693 simple_message_box(ESD_TYPE_INFO, NULL,
3694 "The capture file is probably not fully dissected.",
3695 "End of capture exceeded.");
3698 return TRUE; /* success */
3700 return FALSE; /* failure */
3704 cf_goto_frame(capture_file *cf, guint fnumber)
3708 if (cf == NULL || cf->provider.frames == NULL) {
3709 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3710 statusbar_push_temporary_msg("There is no file loaded");
3711 return FALSE; /* we failed to go to that packet */
3714 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3716 if (fdata == NULL) {
3717 /* we didn't find a packet with that packet number */
3718 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3719 return FALSE; /* we failed to go to that packet */
3721 if (!fdata->flags.passed_dfilter) {
3722 /* that packet currently isn't displayed */
3723 /* XXX - add it to the set of displayed packets? */
3724 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3725 return FALSE; /* we failed to go to that packet */
3728 if (!packet_list_select_row_from_data(fdata)) {
3729 /* We didn't find a row corresponding to this frame.
3730 This means that the frame isn't being displayed currently,
3731 so we can't select it. */
3732 simple_message_box(ESD_TYPE_INFO, NULL,
3733 "The capture file is probably not fully dissected.",
3734 "End of capture exceeded.");
3737 return TRUE; /* we got to that packet */
3741 * Go to frame specified by currently selected protocol tree item.
3744 cf_goto_framenum(capture_file *cf)
3746 header_field_info *hfinfo;
3749 if (cf->finfo_selected) {
3750 hfinfo = cf->finfo_selected->hfinfo;
3752 if (hfinfo->type == FT_FRAMENUM) {
3753 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3755 return cf_goto_frame(cf, framenum);
3762 /* Select the packet on a given row. */
3764 cf_select_packet(capture_file *cf, int row)
3766 epan_dissect_t *old_edt;
3769 /* Get the frame data struct pointer for this frame */
3770 fdata = packet_list_get_row_data(row);
3772 if (fdata == NULL) {
3776 /* Get the data in that frame. */
3777 if (!cf_read_record (cf, fdata)) {
3781 /* Record that this frame is the current frame. */
3782 cf->current_frame = fdata;
3783 cf->current_row = row;
3786 /* Create the logical protocol tree. */
3787 /* We don't need the columns here. */
3788 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3790 tap_build_interesting(cf->edt);
3791 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3792 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3793 cf->current_frame, NULL);
3795 dfilter_macro_build_ftv_cache(cf->edt->tree);
3797 if (old_edt != NULL)
3798 epan_dissect_free(old_edt);
3802 /* Unselect the selected packet, if any. */
3804 cf_unselect_packet(capture_file *cf)
3806 epan_dissect_t *old_edt = cf->edt;
3810 /* No packet is selected. */
3811 cf->current_frame = NULL;
3812 cf->current_row = 0;
3814 /* Destroy the epan_dissect_t for the unselected packet. */
3815 if (old_edt != NULL)
3816 epan_dissect_free(old_edt);
3820 * Mark a particular frame.
3823 cf_mark_frame(capture_file *cf, frame_data *frame)
3825 if (! frame->flags.marked) {
3826 frame->flags.marked = TRUE;
3827 if (cf->count > cf->marked_count)
3833 * Unmark a particular frame.
3836 cf_unmark_frame(capture_file *cf, frame_data *frame)
3838 if (frame->flags.marked) {
3839 frame->flags.marked = FALSE;
3840 if (cf->marked_count > 0)
3846 * Ignore a particular frame.
3849 cf_ignore_frame(capture_file *cf, frame_data *frame)
3851 if (! frame->flags.ignored) {
3852 frame->flags.ignored = TRUE;
3853 if (cf->count > cf->ignored_count)
3854 cf->ignored_count++;
3859 * Un-ignore a particular frame.
3862 cf_unignore_frame(capture_file *cf, frame_data *frame)
3864 if (frame->flags.ignored) {
3865 frame->flags.ignored = FALSE;
3866 if (cf->ignored_count > 0)
3867 cf->ignored_count--;
3872 * Read the section comment.
3875 cf_read_section_comment(capture_file *cf)
3877 wtap_block_t shb_inf;
3881 /* XXX - support multiple SHBs */
3882 shb_inf = wtap_file_get_shb(cf->provider.wth);
3884 /* Get the first comment from the SHB. */
3885 /* XXX - support multiple comments */
3886 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3892 * Modify the section comment.
3895 cf_update_section_comment(capture_file *cf, gchar *comment)
3897 wtap_block_t shb_inf;
3901 /* XXX - support multiple SHBs */
3902 shb_inf = wtap_file_get_shb(cf->provider.wth);
3904 /* Get the first comment from the SHB. */
3905 /* XXX - support multiple comments */
3906 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3907 /* There's no comment - add one. */
3908 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3910 /* See if the comment has changed or not */
3911 if (strcmp(shb_comment, comment) == 0) {
3916 /* The comment has changed, let's update it */
3917 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3919 /* Mark the file as having unsaved changes */
3920 cf->unsaved_changes = TRUE;
3924 * Get the comment on a packet (record).
3925 * If the comment has been edited, it returns the result of the edit,
3926 * otherwise it returns the comment from the file.
3929 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3933 /* fetch user comment */
3934 if (fd->flags.has_user_comment)
3935 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3937 /* fetch phdr comment */
3938 if (fd->flags.has_phdr_comment) {
3939 wtap_rec rec; /* Record metadata */
3940 Buffer buf; /* Record data */
3942 wtap_rec_init(&rec);
3943 ws_buffer_init(&buf, 1500);
3945 if (!cf_read_record_r(cf, fd, &rec, &buf))
3946 { /* XXX, what we can do here? */ }
3948 comment = rec.opt_comment;
3949 wtap_rec_cleanup(&rec);
3950 ws_buffer_free(&buf);
3957 * Update(replace) the comment on a capture from a frame
3960 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3962 char *pkt_comment = cf_get_packet_comment(cf, fd);
3964 /* Check if the comment has changed */
3965 if (!g_strcmp0(pkt_comment, new_comment)) {
3966 g_free(pkt_comment);
3969 g_free(pkt_comment);
3972 cf->packet_comment_count--;
3975 cf->packet_comment_count++;
3977 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3979 expert_update_comment_count(cf->packet_comment_count);
3981 /* OK, we have unsaved changes. */
3982 cf->unsaved_changes = TRUE;
3987 * What types of comments does this capture file have?
3990 cf_comment_types(capture_file *cf)
3992 guint32 comment_types = 0;
3994 if (cf_read_section_comment(cf) != NULL)
3995 comment_types |= WTAP_COMMENT_PER_SECTION;
3996 if (cf->packet_comment_count != 0)
3997 comment_types |= WTAP_COMMENT_PER_PACKET;
3998 return comment_types;
4002 * Add a resolved address to this file's list of resolved addresses.
4005 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
4008 * XXX - support multiple resolved address lists, and add to the one
4009 * attached to this file?
4011 if (!add_ip_name_from_string(addr, name))
4014 /* OK, we have unsaved changes. */
4015 cf->unsaved_changes = TRUE;
4023 } save_callback_args_t;
4026 * Save a capture to a file, in a particular format, saving either
4027 * all packets, all currently-displayed packets, or all marked packets.
4029 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4030 * up a message box for the failure.
4033 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
4034 const guint8 *pd, void *argsp)
4036 save_callback_args_t *args = (save_callback_args_t *)argsp;
4040 const char *pkt_comment;
4042 /* Copy the record information from what was read in from the file. */
4045 /* Make changes based on anything that the user has done but that
4046 hasn't been saved yet. */
4047 if (fdata->flags.has_user_comment)
4048 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
4050 pkt_comment = rec->opt_comment;
4051 new_rec.opt_comment = g_strdup(pkt_comment);
4052 new_rec.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
4053 /* XXX - what if times have been shifted? */
4055 /* and save the packet */
4056 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
4057 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4062 g_free(new_rec.opt_comment);
4067 * Can this capture file be written out in any format using Wiretap
4068 * rather than by copying the raw data?
4071 cf_can_write_with_wiretap(capture_file *cf)
4073 /* We don't care whether we support the comments in this file or not;
4074 if we can't, we'll offer the user the option of discarding the
4076 return wtap_dump_can_write(cf->linktypes, 0);
4080 * Should we let the user do a save?
4084 * the file has unsaved changes, and we can save it in some
4085 * format through Wiretap
4089 * the file is a temporary file and has no unsaved changes (so
4090 * that "saving" it just means copying it).
4092 * XXX - we shouldn't allow files to be edited if they can't be saved,
4093 * so cf->unsaved_changes should be true only if the file can be saved.
4095 * We don't care whether we support the comments in this file or not;
4096 * if we can't, we'll offer the user the option of discarding the
4100 cf_can_save(capture_file *cf)
4102 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4103 /* Saved changes, and we can write it out with Wiretap. */
4107 if (cf->is_tempfile && !cf->unsaved_changes) {
4109 * Temporary file with no unsaved changes, so we can just do a
4115 /* Nothing to save. */
4120 * Should we let the user do a "save as"?
4124 * we can save it in some format through Wiretap
4128 * the file is a temporary file and has no unsaved changes (so
4129 * that "saving" it just means copying it).
4131 * XXX - we shouldn't allow files to be edited if they can't be saved,
4132 * so cf->unsaved_changes should be true only if the file can be saved.
4134 * We don't care whether we support the comments in this file or not;
4135 * if we can't, we'll offer the user the option of discarding the
4139 cf_can_save_as(capture_file *cf)
4141 if (wtap_dump_can_write(cf->linktypes, 0)) {
4142 /* We can write it out with Wiretap. */
4146 if (cf->is_tempfile && !cf->unsaved_changes) {
4148 * Temporary file with no unsaved changes, so we can just do a
4154 /* Nothing to save. */
4159 * Does this file have unsaved data?
4162 cf_has_unsaved_data(capture_file *cf)
4165 * If this is a temporary file, or a file with unsaved changes, it
4168 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4172 * Quick scan to find packet offsets.
4174 static cf_read_status_t
4175 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4177 const wtap_rec *rec;
4182 progdlg_t *progbar = NULL;
4183 GTimer *prog_timer = g_timer_new();
4186 GTimeVal start_time;
4187 gchar status_str[100];
4192 /* Close the old handle. */
4193 wtap_close(cf->provider.wth);
4195 /* Open the new file. */
4196 /* XXX: this will go through all open_routines for a matching one. But right
4197 now rescan_file() is only used when a file is being saved to a different
4198 format than the original, and the user is not given a choice of which
4199 reader to use (only which format to save it in), so doing this makes
4201 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4202 if (cf->provider.wth == NULL) {
4203 cfile_open_failure_alert_box(fname, err, err_info);
4204 return CF_READ_ERROR;
4207 /* We're scanning a file whose contents should be the same as what
4208 we had before, so we don't discard dissection state etc.. */
4211 /* Set the file name because we need it to set the follow stream filter.
4212 XXX - is that still true? We need it for other reasons, though,
4214 cf->filename = g_strdup(fname);
4216 /* Indicate whether it's a permanent or temporary file. */
4217 cf->is_tempfile = is_tempfile;
4219 /* No user changes yet. */
4220 cf->unsaved_changes = FALSE;
4222 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4223 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4225 cf->snap = wtap_snapshot_length(cf->provider.wth);
4227 name_ptr = g_filename_display_basename(cf->filename);
4229 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4231 /* Record whether the file is compressed.
4232 XXX - do we know this at open time? */
4233 cf->iscompressed = wtap_iscompressed(cf->provider.wth);
4235 /* Find the size of the file. */
4236 size = wtap_file_size(cf->provider.wth, NULL);
4238 g_timer_start(prog_timer);
4240 cf->stop_flag = FALSE;
4241 g_get_current_time(&start_time);
4244 rec = wtap_get_rec(cf->provider.wth);
4245 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4247 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4248 fdata->file_off = data_offset;
4251 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4253 /* Create the progress bar if necessary. */
4254 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4255 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4256 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4257 TRUE, &cf->stop_flag, &start_time, progbar_val);
4261 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4262 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4263 * likely trigger UI paint events, which might take a while depending on
4264 * the platform and display. Reset our timer *after* painting.
4266 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4267 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4268 /* update the packet bar content on the first run or frequently on very large files */
4269 update_progress_dlg(progbar, progbar_val, status_str);
4270 compute_elapsed(cf, &start_time);
4271 packets_bar_update();
4272 g_timer_start(prog_timer);
4276 if (cf->stop_flag) {
4277 /* Well, the user decided to abort the rescan. Sadly, as this
4278 isn't a reread, recovering is difficult, so we'll just
4279 close the current capture. */
4283 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4284 it's not already there.
4285 XXX - yes, this is O(N), so if every packet had a different
4286 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4287 there are probably going to be a small number of encapsulation types
4289 if (rec->rec_type == REC_TYPE_PACKET) {
4290 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4294 /* Free the display name */
4297 /* We're done reading the file; destroy the progress bar if it was created. */
4298 if (progbar != NULL)
4299 destroy_progress_dlg(progbar);
4300 g_timer_destroy(prog_timer);
4302 /* We're done reading sequentially through the file. */
4303 cf->state = FILE_READ_DONE;
4305 /* Close the sequential I/O side, to free up memory it requires. */
4306 wtap_sequential_close(cf->provider.wth);
4308 /* compute the time it took to load the file */
4309 compute_elapsed(cf, &start_time);
4311 /* Set the file encapsulation type now; we don't know what it is until
4312 we've looked at all the packets, as we don't know until then whether
4313 there's more than one type (and thus whether it's
4314 WTAP_ENCAP_PER_PACKET). */
4315 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4317 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4319 if (cf->stop_flag) {
4320 /* Our caller will give up at this point. */
4321 return CF_READ_ABORTED;
4325 /* Put up a message box noting that the read failed somewhere along
4326 the line. Don't throw out the stuff we managed to read, though,
4328 cfile_read_failure_alert_box(NULL, err, err_info);
4329 return CF_READ_ERROR;
4335 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4336 gboolean compressed, gboolean discard_comments,
4337 gboolean dont_reopen)
4340 gchar *fname_new = NULL;
4343 addrinfo_lists_t *addr_lists;
4347 gchar *display_basename;
4354 save_callback_args_t callback_args;
4355 gboolean needs_reload = FALSE;
4357 /* XXX caller should avoid saving the file while a read is pending
4358 * (e.g. by delaying the save action) */
4359 if (cf->read_lock) {
4360 g_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname);
4363 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4365 addr_lists = get_addrinfo_list();
4367 if (save_format == cf->cd_t && compressed == cf->iscompressed
4368 && !discard_comments && !cf->unsaved_changes
4369 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4370 /* We're saving in the format it's already in, and we're not discarding
4371 comments, and there are no changes we have in memory that aren't saved
4372 to the file, and we have no name resolution information to write or
4373 the file format we're saving in doesn't support writing name
4374 resolution information, so we can just move or copy the raw data. */
4376 if (cf->is_tempfile) {
4377 /* The file being saved is a temporary file from a live
4378 capture, so it doesn't need to stay around under that name;
4379 first, try renaming the capture buffer file to the new name.
4380 This acts as a "safe save", in that, if the file already
4381 exists, the existing file will be removed only if the rename
4384 Sadly, on Windows, as we have the current capture file
4385 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4386 (to cause the rename to remove an existing target), as
4387 done by ws_stdio_rename() (ws_rename() is #defined to
4388 be ws_stdio_rename() on Windows) will fail.
4390 According to the MSDN documentation for CreateFile(), if,
4391 when we open a capture file, we were to directly do a CreateFile(),
4392 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4393 convert it to a file descriptor with _open_osfhandle(),
4394 that would allow the file to be renamed out from under us.
4396 However, that doesn't work in practice. Perhaps the problem
4397 is that the process doing the rename is the process that
4398 has the file open. */
4400 if (ws_rename(cf->filename, fname) == 0) {
4401 /* That succeeded - there's no need to copy the source file. */
4402 how_to_save = SAVE_WITH_MOVE;
4404 if (errno == EXDEV) {
4405 /* They're on different file systems, so we have to copy the
4407 how_to_save = SAVE_WITH_COPY;
4409 /* The rename failed, but not because they're on different
4410 file systems - put up an error message. (Or should we
4411 just punt and try to copy? The only reason why I'd
4412 expect the rename to fail and the copy to succeed would
4413 be if we didn't have permission to remove the file from
4414 the temporary directory, and that might be fixable - but
4415 is it worth requiring the user to go off and fix it?) */
4416 cf_rename_failure_alert_box(fname, errno);
4421 /* Windows - copy the file to its new location. */
4422 how_to_save = SAVE_WITH_COPY;
4425 /* It's a permanent file, so we should copy it, and not remove the
4427 how_to_save = SAVE_WITH_COPY;
4430 if (how_to_save == SAVE_WITH_COPY) {
4431 /* Copy the file, if we haven't moved it. If we're overwriting
4432 an existing file, we do it with a "safe save", by writing
4433 to a new file and, if the write succeeds, renaming the
4434 new file on top of the old file. */
4435 if (file_exists(fname)) {
4436 fname_new = g_strdup_printf("%s~", fname);
4437 if (!copy_file_binary_mode(cf->filename, fname_new))
4440 if (!copy_file_binary_mode(cf->filename, fname))
4445 /* Either we're saving in a different format or we're saving changes,
4446 such as added, modified, or removed comments, that haven't yet
4447 been written to the underlying file; we can't do that by copying
4448 or moving the capture file, we have to do it by writing the packets
4451 GArray *shb_hdrs = NULL;
4452 wtapng_iface_descriptions_t *idb_inf = NULL;
4453 GArray *nrb_hdrs = NULL;
4456 /* XXX: what free's this shb_hdr? */
4457 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4458 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4459 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4461 /* Determine what file encapsulation type we should use. */
4462 encap = wtap_dump_file_encap_type(cf->linktypes);
4464 if (file_exists(fname)) {
4465 /* We're overwriting an existing file; write out to a new file,
4466 and, if that succeeds, rename the new file on top of the
4467 old file. That makes this a "safe save", so that we don't
4468 lose the old file if we have a problem writing out the new
4469 file. (If the existing file is the current capture file,
4470 we *HAVE* to do that, otherwise we're overwriting the file
4471 from which we're reading the packets that we're writing!) */
4472 fname_new = g_strdup_printf("%s~", fname);
4473 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4474 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4476 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4477 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4483 cfile_dump_open_failure_alert_box(fname, err, save_format);
4487 /* Add address resolution */
4488 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4490 /* Iterate through the list of packets, processing all the packets. */
4491 callback_args.pdh = pdh;
4492 callback_args.fname = fname;
4493 callback_args.file_type = save_format;
4494 switch (process_specified_records(cf, NULL, "Saving", "packets",
4495 TRUE, save_record, &callback_args, TRUE)) {
4498 /* Completed successfully. */
4502 /* The user decided to abort the saving.
4503 If we're writing to a temporary file, remove it.
4504 XXX - should we do so even if we're not writing to a
4506 wtap_dump_close(pdh, &err);
4507 if (fname_new != NULL)
4508 ws_unlink(fname_new);
4509 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4510 return CF_WRITE_ABORTED;
4513 /* Error while saving.
4514 If we're writing to a temporary file, remove it. */
4515 if (fname_new != NULL)
4516 ws_unlink(fname_new);
4517 wtap_dump_close(pdh, &err);
4521 needs_reload = wtap_dump_get_needs_reload(pdh);
4523 if (!wtap_dump_close(pdh, &err)) {
4524 cfile_close_failure_alert_box(fname, err);
4528 how_to_save = SAVE_WITH_WTAP;
4531 if (fname_new != NULL) {
4532 /* We wrote out to fname_new, and should rename it on top of
4533 fname. fname_new is now closed, so that should be possible even
4534 on Windows. However, on Windows, we first need to close whatever
4535 file descriptors we have open for fname. */
4537 wtap_fdclose(cf->provider.wth);
4539 /* Now do the rename. */
4540 if (ws_rename(fname_new, fname) == -1) {
4541 /* Well, the rename failed. */
4542 cf_rename_failure_alert_box(fname, errno);
4544 /* Attempt to reopen the random file descriptor using the
4545 current file's filename. (At this point, the sequential
4546 file descriptor is closed.) */
4547 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4548 /* Oh, well, we're screwed. */
4549 display_basename = g_filename_display_basename(cf->filename);
4550 simple_error_message_box(
4551 file_open_error_message(err, FALSE), display_basename);
4552 g_free(display_basename);
4559 /* If this was a temporary file, and we didn't do the save by doing
4560 a move, so the tempoary file is still around under its old name,
4562 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4563 /* If this fails, there's not much we can do, so just ignore errors. */
4564 ws_unlink(cf->filename);
4567 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4568 cf->unsaved_changes = FALSE;
4571 switch (how_to_save) {
4573 case SAVE_WITH_MOVE:
4574 /* We just moved the file, so the wtap structure refers to the
4575 new file, and all the information other than the filename
4576 and the "is temporary" status applies to the new file; just
4578 g_free(cf->filename);
4579 cf->filename = g_strdup(fname);
4580 cf->is_tempfile = FALSE;
4581 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4584 case SAVE_WITH_COPY:
4585 /* We just copied the file, so all the information other than
4586 the wtap structure, the filename, and the "is temporary"
4587 status applies to the new file; just update that. */
4588 wtap_close(cf->provider.wth);
4589 /* Although we're just "copying" and then opening the copy, it will
4590 try all open_routine readers to open the copy, so we need to
4591 reset the cfile's open_type. */
4592 cf->open_type = WTAP_TYPE_AUTO;
4593 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4594 if (cf->provider.wth == NULL) {
4595 cfile_open_failure_alert_box(fname, err, err_info);
4598 g_free(cf->filename);
4599 cf->filename = g_strdup(fname);
4600 cf->is_tempfile = FALSE;
4602 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4605 case SAVE_WITH_WTAP:
4606 /* Open and read the file we saved to.
4608 XXX - this is somewhat of a waste; we already have the
4609 packets, all this gets us is updated file type information
4610 (which we could just stuff into "cf"), and having the new
4611 file be the one we have opened and from which we're reading
4612 the data, and it means we have to spend time opening and
4613 reading the file, which could be a significant amount of
4614 time if the file is large.
4616 If the capture-file-writing code were to return the
4617 seek offset of each packet it writes, we could save that
4618 in the frame_data structure for the frame, and just open
4619 the file without reading it again...
4621 ...as long as, for gzipped files, the process of writing
4622 out the file *also* generates the information needed to
4623 support fast random access to the compressed file. */
4624 /* rescan_file will cause us to try all open_routines, so
4625 reset cfile's open_type */
4626 cf->open_type = WTAP_TYPE_AUTO;
4627 /* There are cases when SAVE_WITH_WTAP can result in new packets
4628 being written to the file, e.g ERF records
4629 In that case, we need to reload the whole file */
4631 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4632 if (cf_read(cf, TRUE) != CF_READ_OK) {
4633 /* The rescan failed; just close the file. Either
4634 a dialog was popped up for the failure, so the
4635 user knows what happened, or they stopped the
4636 rescan, in which case they know what happened. */
4637 /* XXX: This is inconsistent with normal open/reload behaviour. */
4643 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4644 /* The rescan failed; just close the file. Either
4645 a dialog was popped up for the failure, so the
4646 user knows what happened, or they stopped the
4647 rescan, in which case they know what happened. */
4654 /* If we were told to discard the comments, do so. */
4655 if (discard_comments) {
4656 /* Remove SHB comment, if any. */
4657 wtap_write_shb_comment(cf->provider.wth, NULL);
4659 /* remove all user comments */
4660 for (framenum = 1; framenum <= cf->count; framenum++) {
4661 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4663 fdata->flags.has_phdr_comment = FALSE;
4664 fdata->flags.has_user_comment = FALSE;
4667 if (cf->provider.frames_user_comments) {
4668 g_tree_destroy(cf->provider.frames_user_comments);
4669 cf->provider.frames_user_comments = NULL;
4672 cf->packet_comment_count = 0;
4678 if (fname_new != NULL) {
4679 /* We were trying to write to a temporary file; get rid of it if it
4680 exists. (We don't care whether this fails, as, if it fails,
4681 there's not much we can do about it. I guess if it failed for
4682 a reason other than "it doesn't exist", we could report an
4683 error, so the user knows there's a junk file that they might
4684 want to clean up.) */
4685 ws_unlink(fname_new);
4688 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4689 return CF_WRITE_ERROR;
4693 cf_export_specified_packets(capture_file *cf, const char *fname,
4694 packet_range_t *range, guint save_format,
4695 gboolean compressed)
4697 gchar *fname_new = NULL;
4700 save_callback_args_t callback_args;
4701 GArray *shb_hdrs = NULL;
4702 wtapng_iface_descriptions_t *idb_inf = NULL;
4703 GArray *nrb_hdrs = NULL;
4706 packet_range_process_init(range);
4708 /* We're writing out specified packets from the specified capture
4709 file to another file. Even if all captured packets are to be
4710 written, don't special-case the operation - read each packet
4711 and then write it out if it's one of the specified ones. */
4713 /* XXX: what free's this shb_hdr? */
4714 shb_hdrs = wtap_file_get_shb_for_new_file(cf->provider.wth);
4715 idb_inf = wtap_file_get_idb_info(cf->provider.wth);
4716 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->provider.wth);
4718 /* Determine what file encapsulation type we should use. */
4719 encap = wtap_dump_file_encap_type(cf->linktypes);
4721 if (file_exists(fname)) {
4722 /* We're overwriting an existing file; write out to a new file,
4723 and, if that succeeds, rename the new file on top of the
4724 old file. That makes this a "safe save", so that we don't
4725 lose the old file if we have a problem writing out the new
4726 file. (If the existing file is the current capture file,
4727 we *HAVE* to do that, otherwise we're overwriting the file
4728 from which we're reading the packets that we're writing!) */
4729 fname_new = g_strdup_printf("%s~", fname);
4730 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4731 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4733 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4734 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4740 cfile_dump_open_failure_alert_box(fname, err, save_format);
4744 /* Add address resolution */
4745 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4747 /* Iterate through the list of packets, processing the packets we were
4750 XXX - we've already called "packet_range_process_init(range)", but
4751 "process_specified_records()" will do it again. Fortunately,
4752 that's harmless in this case, as we haven't done anything to
4753 "range" since we initialized it. */
4754 callback_args.pdh = pdh;
4755 callback_args.fname = fname;
4756 callback_args.file_type = save_format;
4757 switch (process_specified_records(cf, range, "Writing", "specified records",
4758 TRUE, save_record, &callback_args, TRUE)) {
4761 /* Completed successfully. */
4765 /* The user decided to abort the saving.
4766 If we're writing to a temporary file, remove it.
4767 XXX - should we do so even if we're not writing to a
4769 wtap_dump_close(pdh, &err);
4770 if (fname_new != NULL)
4771 ws_unlink(fname_new);
4772 return CF_WRITE_ABORTED;
4776 /* Error while saving.
4777 If we're writing to a temporary file, remove it. */
4778 if (fname_new != NULL)
4779 ws_unlink(fname_new);
4780 wtap_dump_close(pdh, &err);
4784 if (!wtap_dump_close(pdh, &err)) {
4785 cfile_close_failure_alert_box(fname, err);
4789 if (fname_new != NULL) {
4790 /* We wrote out to fname_new, and should rename it on top of
4791 fname; fname is now closed, so that should be possible even
4792 on Windows. Do the rename. */
4793 if (ws_rename(fname_new, fname) == -1) {
4794 /* Well, the rename failed. */
4795 cf_rename_failure_alert_box(fname, errno);
4803 if (fname_new != NULL) {
4804 /* We were trying to write to a temporary file; get rid of it if it
4805 exists. (We don't care whether this fails, as, if it fails,
4806 there's not much we can do about it. I guess if it failed for
4807 a reason other than "it doesn't exist", we could report an
4808 error, so the user knows there's a junk file that they might
4809 want to clean up.) */
4810 ws_unlink(fname_new);
4813 return CF_WRITE_ERROR;
4817 * XXX - whether we mention the source pathname, the target pathname,
4818 * or both depends on the error and on what we find if we look for
4819 * one or both of them.
4822 cf_rename_failure_alert_box(const char *filename, int err)
4824 gchar *display_basename;
4826 display_basename = g_filename_display_basename(filename);
4830 /* XXX - should check whether the source exists and, if not,
4831 report it as the problem and, if so, report the destination
4833 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4838 /* XXX - if we're doing a rename after a safe save, we should
4839 probably say something else. */
4840 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4845 /* XXX - this should probably mention both the source and destination
4847 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4848 display_basename, wtap_strerror(err));
4851 g_free(display_basename);
4854 /* Reload the current capture file. */
4856 cf_reload(capture_file *cf) {
4858 gboolean is_tempfile;
4861 if (cf->read_lock) {
4862 g_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename);
4866 /* If the file could be opened, "cf_open()" calls "cf_close()"
4867 to get rid of state for the old capture file before filling in state
4868 for the new capture file. "cf_close()" will remove the file if
4869 it's a temporary file; we don't want that to happen (for one thing,
4870 it'd prevent subsequent reopens from working). Remember whether it's
4871 a temporary file, mark it as not being a temporary file, and then
4872 reopen it as the type of file it was.
4874 Also, "cf_close()" will free "cf->filename", so we must make
4875 a copy of it first. */
4876 filename = g_strdup(cf->filename);
4877 is_tempfile = cf->is_tempfile;
4878 cf->is_tempfile = FALSE;
4879 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4880 switch (cf_read(cf, TRUE)) {
4884 /* Just because we got an error, that doesn't mean we were unable
4885 to read any of the file; we handle what we could get from the
4889 case CF_READ_ABORTED:
4890 /* The user bailed out of re-reading the capture file; the
4891 capture file has been closed - just free the capture file name
4892 string and return (without changing the last containing
4898 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4899 Instead, the file was left open, so we should restore "cf->is_tempfile"
4902 XXX - change the menu? Presumably "cf_open()" will do that;
4903 make sure it does! */
4904 cf->is_tempfile = is_tempfile;
4906 /* "cf_open()" made a copy of the file name we handed it, so
4907 we should free up our copy. */
4917 * indent-tabs-mode: nil
4920 * ex: set shiftwidth=2 tabstop=8 expandtab:
4921 * :indentSize=2:tabSize=8:noTabs=true: