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 <wsutil/json_dumper.h>
25 #include <version_info.h>
27 #include <wiretap/merge.h>
29 #include <epan/exceptions.h>
30 #include <epan/epan.h>
31 #include <epan/column.h>
32 #include <epan/packet.h>
33 #include <epan/column-utils.h>
34 #include <epan/expert.h>
35 #include <epan/prefs.h>
36 #include <epan/dfilter/dfilter.h>
37 #include <epan/epan_dissect.h>
39 #include <epan/dissectors/packet-ber.h>
40 #include <epan/timestamp.h>
41 #include <epan/dfilter/dfilter-macro.h>
42 #include <epan/strutil.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/color_filters.h>
45 #include <epan/secrets.h>
50 #include "frame_tvbuff.h"
52 #include "ui/alert_box.h"
53 #include "ui/simple_dialog.h"
54 #include "ui/main_statusbar.h"
55 #include "ui/progress_dlg.h"
56 #include "ui/ws_ui_util.h"
58 /* Needed for addrinfo */
59 #include <sys/types.h>
61 #ifdef HAVE_SYS_SOCKET_H
62 #include <sys/socket.h>
65 #ifdef HAVE_NETINET_IN_H
66 # include <netinet/in.h>
70 # include <winsock2.h>
71 # include <ws2tcpip.h>
74 static gboolean read_record(capture_file *cf, dfilter_t *dfcode,
75 epan_dissect_t *edt, column_info *cinfo, gint64 offset);
77 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
84 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
86 static void match_subtree_text(proto_node *node, gpointer data);
87 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
89 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
91 static match_result match_narrow(capture_file *cf, frame_data *fdata,
93 static match_result match_wide(capture_file *cf, frame_data *fdata,
95 static match_result match_binary(capture_file *cf, frame_data *fdata,
97 static match_result match_regex(capture_file *cf, frame_data *fdata,
99 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
101 static match_result match_marked(capture_file *cf, frame_data *fdata,
103 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
105 static gboolean find_packet(capture_file *cf,
106 match_result (*match_function)(capture_file *, frame_data *, void *),
107 void *criterion, search_direction dir);
109 static void cf_rename_failure_alert_box(const char *filename, int err);
110 static void ref_time_packets(capture_file *cf);
112 /* Seconds spent processing packets between pushing UI updates. */
113 #define PROGBAR_UPDATE_INTERVAL 0.150
115 /* Show the progress bar after this many seconds. */
116 #define PROGBAR_SHOW_DELAY 0.5
119 * We could probably use g_signal_...() instead of the callbacks below but that
120 * would require linking our CLI programs to libgobject and creating an object
121 * instance for the signals.
124 cf_callback_t cb_fct;
126 } cf_callback_data_t;
128 static GList *cf_callbacks = NULL;
131 cf_callback_invoke(int event, gpointer data)
133 cf_callback_data_t *cb;
134 GList *cb_item = cf_callbacks;
136 /* there should be at least one interested */
137 g_assert(cb_item != NULL);
139 while (cb_item != NULL) {
140 cb = (cf_callback_data_t *)cb_item->data;
141 cb->cb_fct(event, data, cb->user_data);
142 cb_item = g_list_next(cb_item);
148 cf_callback_add(cf_callback_t func, gpointer user_data)
150 cf_callback_data_t *cb;
152 cb = g_new(cf_callback_data_t,1);
154 cb->user_data = user_data;
156 cf_callbacks = g_list_prepend(cf_callbacks, cb);
160 cf_callback_remove(cf_callback_t func, gpointer user_data)
162 cf_callback_data_t *cb;
163 GList *cb_item = cf_callbacks;
165 while (cb_item != NULL) {
166 cb = (cf_callback_data_t *)cb_item->data;
167 if (cb->cb_fct == func && cb->user_data == user_data) {
168 cf_callbacks = g_list_remove(cf_callbacks, cb);
172 cb_item = g_list_next(cb_item);
175 g_assert_not_reached();
179 cf_timestamp_auto_precision(capture_file *cf)
183 /* don't try to get the file's precision if none is opened */
184 if (cf->state == FILE_CLOSED) {
188 /* Set the column widths of those columns that show the time in
189 "command-line-specified" format. */
190 for (i = 0; i < cf->cinfo.num_cols; i++) {
191 if (col_has_time_fmt(&cf->cinfo, i)) {
192 packet_list_resize_column(i);
198 cf_get_computed_elapsed(capture_file *cf)
200 return cf->computed_elapsed;
204 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
207 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
212 g_get_current_time(&time_now);
214 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
215 time_now.tv_usec - start_time->tv_usec;
217 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
220 static const nstime_t *
221 ws_get_frame_ts(struct packet_provider_data *prov, guint32 frame_num)
223 if (prov->prev_dis && prov->prev_dis->num == frame_num)
224 return &prov->prev_dis->abs_ts;
226 if (prov->prev_cap && prov->prev_cap->num == frame_num)
227 return &prov->prev_cap->abs_ts;
230 frame_data *fd = frame_data_sequence_find(prov->frames, frame_num);
232 return (fd) ? &fd->abs_ts : NULL;
239 ws_epan_new(capture_file *cf)
241 static const struct packet_provider_funcs funcs = {
243 cap_file_provider_get_interface_name,
244 cap_file_provider_get_interface_description,
245 cap_file_provider_get_user_comment
248 return epan_new(&cf->provider, &funcs);
252 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
257 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
261 /* The open succeeded. Close whatever capture file we had open,
262 and fill in the information for this file. */
265 /* Initialize the record metadata. */
266 wtap_rec_init(&cf->rec);
268 /* XXX - we really want to initialize this after we've read all
269 the packets, so we know how much we'll ultimately need. */
270 ws_buffer_init(&cf->buf, 1500);
272 /* We're about to start reading the file. */
273 cf->state = FILE_READ_IN_PROGRESS;
275 cf->provider.wth = wth;
278 /* Set the file name because we need it to set the follow stream filter.
279 XXX - is that still true? We need it for other reasons, though,
281 cf->filename = g_strdup(fname);
283 /* Indicate whether it's a permanent or temporary file. */
284 cf->is_tempfile = is_tempfile;
286 /* No user changes yet. */
287 cf->unsaved_changes = FALSE;
289 cf->computed_elapsed = 0;
291 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
292 cf->open_type = type;
293 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
295 cf->packet_comment_count = 0;
296 cf->displayed_count = 0;
297 cf->marked_count = 0;
298 cf->ignored_count = 0;
299 cf->ref_time_count = 0;
300 cf->drops_known = FALSE;
302 cf->snap = wtap_snapshot_length(cf->provider.wth);
304 /* Allocate a frame_data_sequence for the frames in this file */
305 cf->provider.frames = new_frame_data_sequence();
307 nstime_set_zero(&cf->elapsed_time);
308 cf->provider.ref = NULL;
309 cf->provider.prev_dis = NULL;
310 cf->provider.prev_cap = NULL;
313 /* Create new epan session for dissection.
314 * (The old one was freed in cf_close().)
316 cf->epan = ws_epan_new(cf);
318 packet_list_queue_draw();
319 cf_callback_invoke(cf_cb_file_opened, cf);
321 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
322 /* tell the BER dissector the file name */
323 ber_set_filename(cf->filename);
326 wtap_set_cb_new_ipv4(cf->provider.wth, add_ipv4_name);
327 wtap_set_cb_new_ipv6(cf->provider.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
328 wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback);
333 cfile_open_failure_alert_box(fname, *err, err_info);
338 * Add an encapsulation type to cf->linktypes.
341 cf_add_encapsulation_type(capture_file *cf, int encap)
345 for (i = 0; i < cf->linktypes->len; i++) {
346 if (g_array_index(cf->linktypes, gint, i) == encap)
347 return; /* it's already there */
349 /* It's not already there - add it. */
350 g_array_append_val(cf->linktypes, encap);
353 /* Reset everything to a pristine state */
355 cf_close(capture_file *cf)
357 cf->stop_flag = FALSE;
358 if (cf->state == FILE_CLOSED)
359 return; /* Nothing to do */
361 /* Die if we're in the middle of reading a file. */
362 g_assert(cf->state != FILE_READ_IN_PROGRESS);
363 g_assert(!cf->read_lock);
365 cf_callback_invoke(cf_cb_file_closing, cf);
367 /* close things, if not already closed before */
368 color_filters_cleanup();
370 if (cf->provider.wth) {
371 wtap_close(cf->provider.wth);
372 cf->provider.wth = NULL;
374 /* We have no file open... */
375 if (cf->filename != NULL) {
376 /* If it's a temporary file, remove it. */
378 ws_unlink(cf->filename);
379 g_free(cf->filename);
382 /* ...which means we have no changes to that file to save. */
383 cf->unsaved_changes = FALSE;
385 /* no open_routine type */
386 cf->open_type = WTAP_TYPE_AUTO;
388 /* Clean up the record metadata. */
389 wtap_rec_cleanup(&cf->rec);
391 /* Free up the packet buffer. */
392 ws_buffer_free(&cf->buf);
394 dfilter_free(cf->rfcode);
396 if (cf->provider.frames != NULL) {
397 free_frame_data_sequence(cf->provider.frames);
398 cf->provider.frames = NULL;
400 if (cf->provider.frames_user_comments) {
401 g_tree_destroy(cf->provider.frames_user_comments);
402 cf->provider.frames_user_comments = NULL;
404 cf_unselect_packet(cf); /* nothing to select */
405 cf->first_displayed = 0;
406 cf->last_displayed = 0;
408 /* No frames, no frame selected, no field in that frame selected. */
410 cf->current_frame = 0;
412 cf->finfo_selected = NULL;
414 /* No frame link-layer types, either. */
415 if (cf->linktypes != NULL) {
416 g_array_free(cf->linktypes, TRUE);
417 cf->linktypes = NULL;
420 /* Clear the packet list. */
421 packet_list_freeze();
426 nstime_set_zero(&cf->elapsed_time);
428 reset_tap_listeners();
433 /* We have no file open. */
434 cf->state = FILE_CLOSED;
436 cf_callback_invoke(cf_cb_file_closed, cf);
440 * TRUE if the progress dialog doesn't exist and it looks like we'll
441 * take > 2s to load, FALSE otherwise.
443 static inline gboolean
444 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
448 if (progdlg) return FALSE;
449 elapsed = g_timer_elapsed(prog_timer, NULL);
450 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
451 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
458 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
462 progbar_val = (gfloat) file_pos / (gfloat) size;
463 if (progbar_val > 1.0) {
465 /* The file probably grew while we were reading it.
466 * Update file size, and try again.
468 size = wtap_file_size(cf->provider.wth, NULL);
471 progbar_val = (gfloat) file_pos / (gfloat) size;
473 /* If it's still > 1, either "wtap_file_size()" failed (in which
474 * case there's not much we can do about it), or the file
475 * *shrank* (in which case there's not much we can do about
476 * it); just clip the progress value at 1.0.
478 if (progbar_val > 1.0f)
482 g_snprintf(status_str, status_size,
483 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
484 file_pos / 1024, size / 1024);
490 cf_read(capture_file *cf, gboolean reloading)
493 gchar *err_info = NULL;
495 progdlg_t *volatile progbar = NULL;
496 GTimer *prog_timer = g_timer_new();
500 volatile gboolean create_proto_tree;
503 volatile gboolean is_read_aborted = FALSE;
505 /* The update_progress_dlg call below might end up accepting a user request to
506 * trigger redissection/rescans which can modify/destroy the dissection
507 * context ("cf->epan"). That condition should be prevented by callers, but in
508 * case it occurs let's fail gracefully.
511 g_warning("Failing due to recursive cf_read(\"%s\", %d) call!",
512 cf->filename, reloading);
513 return CF_READ_ERROR;
515 cf->read_lock = TRUE;
517 /* Compile the current display filter.
518 * We assume this will not fail since cf->dfilter is only set in
519 * cf_filter IFF the filter was valid.
521 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
522 g_assert(!cf->dfilter || (compiled && dfcode));
524 /* Get the union of the flags for all tap listeners. */
525 tap_flags = union_of_tap_listener_flags();
528 * Determine whether we need to create a protocol tree.
531 * we're going to apply a display filter;
533 * one of the tap listeners is going to apply a filter;
535 * one of the tap listeners requires a protocol tree;
537 * a postdissector wants field values or protocols on
541 (dfcode != NULL || have_filtering_tap_listeners() ||
542 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
544 reset_tap_listeners();
546 name_ptr = g_filename_display_basename(cf->filename);
549 cf_callback_invoke(cf_cb_file_reload_started, cf);
551 cf_callback_invoke(cf_cb_file_read_started, cf);
553 /* Record the file's compression type.
554 XXX - do we know this at open time? */
555 cf->compression_type = wtap_get_compression_type(cf->provider.wth);
557 /* The packet list window will be empty until the file is completly loaded */
558 packet_list_freeze();
560 cf->stop_flag = FALSE;
561 g_get_current_time(&start_time);
563 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
573 gchar status_str[100];
577 /* If any tap listeners require the columns, construct them. */
578 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
580 /* Find the size of the file. */
581 size = wtap_file_size(cf->provider.wth, NULL);
583 g_timer_start(prog_timer);
585 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
588 file_pos = wtap_read_so_far(cf->provider.wth);
590 /* Create the progress bar if necessary. */
591 if (progress_is_slow(progbar, prog_timer, size, file_pos)) {
592 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
594 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
595 TRUE, &cf->stop_flag, &start_time, progbar_val);
597 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
598 TRUE, &cf->stop_flag, &start_time, progbar_val);
602 * Update the progress bar, but do it only after
603 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
604 * and packets_bar_update will likely trigger UI paint events, which
605 * might take a while depending on the platform and display. Reset
606 * our timer *after* painting.
608 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
609 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
610 /* update the packet bar content on the first run or frequently on very large files */
611 update_progress_dlg(progbar, progbar_val, status_str);
612 compute_elapsed(cf, &start_time);
613 packets_bar_update();
614 g_timer_start(prog_timer);
617 * The previous GUI triggers should not have destroyed the running
618 * session. If that did happen, it could blow up when read_record tries
619 * to use the destroyed edt.session, so detect it right here.
621 g_assert(edt.session == cf->epan);
624 if (cf->state == FILE_READ_ABORTED) {
625 /* Well, the user decided to exit Wireshark. Break out of the
626 loop, and let the code below (which is called even if there
627 aren't any packets left to read) exit. */
628 is_read_aborted = TRUE;
632 /* Well, the user decided to abort the read. He/She will be warned and
633 it might be enough for him/her to work with the already loaded
635 This is especially true for very large capture files, where you don't
636 want to wait loading the whole file (which may last minutes or even
637 hours even on fast machines) just to see that it was the wrong file. */
640 read_record(cf, dfcode, &edt, cinfo, data_offset);
643 CATCH(OutOfMemoryError) {
644 simple_message_box(ESD_TYPE_ERROR, NULL,
645 "More information and workarounds can be found at\n"
646 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
647 "Sorry, but Wireshark has run out of memory and has to terminate now.");
649 /* Could we close the current capture and free up memory from that? */
651 /* we have to terminate, as we cannot recover from the memory error */
657 /* Free the display name */
660 /* Cleanup and release all dfilter resources */
661 dfilter_free(dfcode);
663 epan_dissect_cleanup(&edt);
665 /* We're done reading the file; destroy the progress bar if it was created. */
667 destroy_progress_dlg(progbar);
668 g_timer_destroy(prog_timer);
670 /* We're done reading sequentially through the file. */
671 cf->state = FILE_READ_DONE;
673 /* Close the sequential I/O side, to free up memory it requires. */
674 wtap_sequential_close(cf->provider.wth);
676 /* Allow the protocol dissectors to free up memory that they
677 * don't need after the sequential run-through of the packets. */
678 postseq_cleanup_all_protocols();
680 /* compute the time it took to load the file */
681 compute_elapsed(cf, &start_time);
683 /* Set the file encapsulation type now; we don't know what it is until
684 we've looked at all the packets, as we don't know until then whether
685 there's more than one type (and thus whether it's
686 WTAP_ENCAP_PER_PACKET). */
687 cf->lnk_t = wtap_file_encap(cf->provider.wth);
689 cf->current_frame = frame_data_sequence_find(cf->provider.frames, cf->first_displayed);
694 cf_callback_invoke(cf_cb_file_reload_finished, cf);
696 cf_callback_invoke(cf_cb_file_read_finished, cf);
698 /* If we have any displayed packets to select, select the first of those
699 packets by making the first row the selected row. */
700 if (cf->first_displayed != 0) {
701 packet_list_select_first_row();
704 /* It is safe again to execute redissections. */
705 g_assert(cf->read_lock);
706 cf->read_lock = FALSE;
708 if (is_read_aborted) {
710 * Well, the user decided to exit Wireshark while reading this *offline*
711 * capture file (Live captures are handled by something like
712 * cf_continue_tail). Clean up accordingly.
715 cf->redissection_queued = RESCAN_NONE;
716 return CF_READ_ABORTED;
719 if (cf->redissection_queued != RESCAN_NONE) {
720 /* Redissection was queued up. Clear the request and perform it now. */
721 gboolean redissect = cf->redissection_queued == RESCAN_REDISSECT;
722 rescan_packets(cf, "Reprocessing", "all packets", redissect);
726 simple_message_box(ESD_TYPE_WARN, NULL,
727 "The remaining packets in the file were discarded.\n"
729 "As a lot of packets from the original file will be missing,\n"
730 "remember to be careful when saving the current content to a file.\n",
731 "File loading was cancelled.");
732 return CF_READ_ERROR;
736 /* Put up a message box noting that the read failed somewhere along
737 the line. Don't throw out the stuff we managed to read, though,
739 cfile_read_failure_alert_box(NULL, err, err_info);
740 return CF_READ_ERROR;
747 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
750 volatile int newly_displayed_packets = 0;
753 gboolean create_proto_tree;
757 /* Compile the current display filter.
758 * We assume this will not fail since cf->dfilter is only set in
759 * cf_filter IFF the filter was valid.
761 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
762 g_assert(!cf->dfilter || (compiled && dfcode));
764 /* Get the union of the flags for all tap listeners. */
765 tap_flags = union_of_tap_listener_flags();
768 * Determine whether we need to create a protocol tree.
771 * we're going to apply a display filter;
773 * one of the tap listeners is going to apply a filter;
775 * one of the tap listeners requires a protocol tree;
777 * a postdissector wants field values or protocols on
781 (dfcode != NULL || have_filtering_tap_listeners() ||
782 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
786 /* Don't freeze/thaw the list when doing live capture */
787 /*packet_list_freeze();*/
789 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
791 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
794 gint64 data_offset = 0;
797 /* If any tap listeners require the columns, construct them. */
798 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
800 while (to_read != 0) {
801 wtap_cleareof(cf->provider.wth);
802 if (!wtap_read(cf->provider.wth, err, &err_info, &data_offset)) {
805 if (cf->state == FILE_READ_ABORTED) {
806 /* Well, the user decided to exit Wireshark. Break out of the
807 loop, and let the code below (which is called even if there
808 aren't any packets left to read) exit. */
811 if (read_record(cf, dfcode, &edt, cinfo, data_offset)) {
812 newly_displayed_packets++;
817 CATCH(OutOfMemoryError) {
818 simple_message_box(ESD_TYPE_ERROR, NULL,
819 "More information and workarounds can be found at\n"
820 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
821 "Sorry, but Wireshark has run out of memory and has to terminate now.");
823 /* Could we close the current capture and free up memory from that? */
824 return CF_READ_ABORTED;
826 /* we have to terminate, as we cannot recover from the memory error */
832 /* Update the file encapsulation; it might have changed based on the
833 packets we've read. */
834 cf->lnk_t = wtap_file_encap(cf->provider.wth);
836 /* Cleanup and release all dfilter resources */
837 dfilter_free(dfcode);
839 epan_dissect_cleanup(&edt);
841 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
842 cf->count, cf->state, *err);*/
844 /* Don't freeze/thaw the list when doing live capture */
845 /*packet_list_thaw();*/
846 /* With the new packet list the first packet
847 * isn't automatically selected.
849 if (!cf->current_frame)
850 packet_list_select_first_row();
852 /* moving to the end of the packet list - if the user requested so and
853 we have some new packets. */
854 if (newly_displayed_packets && cf->count != 0)
855 packet_list_moveto_end();
857 if (cf->state == FILE_READ_ABORTED) {
858 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
859 so that our caller can kill off the capture child process;
860 this will cause an EOF on the pipe from the child, so
861 "cf_finish_tail()" will be called, and it will clean up
863 return CF_READ_ABORTED;
864 } else if (*err != 0) {
865 /* We got an error reading the capture file.
866 XXX - pop up a dialog box instead? */
867 if (err_info != NULL) {
868 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
869 wtap_strerror(*err), cf->filename, err_info);
872 g_warning("Error \"%s\" while reading \"%s\"",
873 wtap_strerror(*err), cf->filename);
875 return CF_READ_ERROR;
881 cf_fake_continue_tail(capture_file *cf) {
882 cf->state = FILE_READ_DONE;
886 cf_finish_tail(capture_file *cf, int *err)
893 gboolean create_proto_tree;
897 /* Compile the current display filter.
898 * We assume this will not fail since cf->dfilter is only set in
899 * cf_filter IFF the filter was valid.
901 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
902 g_assert(!cf->dfilter || (compiled && dfcode));
904 /* Get the union of the flags for all tap listeners. */
905 tap_flags = union_of_tap_listener_flags();
907 /* If any tap listeners require the columns, construct them. */
908 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
911 * Determine whether we need to create a protocol tree.
914 * we're going to apply a display filter;
916 * one of the tap listeners is going to apply a filter;
918 * one of the tap listeners requires a protocol tree;
920 * a postdissector wants field values or protocols on
924 (dfcode != NULL || have_filtering_tap_listeners() ||
925 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
927 if (cf->provider.wth == NULL) {
929 return CF_READ_ERROR;
932 /* Don't freeze/thaw the list when doing live capture */
933 /*packet_list_freeze();*/
935 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
937 while ((wtap_read(cf->provider.wth, err, &err_info, &data_offset))) {
938 if (cf->state == FILE_READ_ABORTED) {
939 /* Well, the user decided to abort the read. Break out of the
940 loop, and let the code below (which is called even if there
941 aren't any packets left to read) exit. */
944 read_record(cf, dfcode, &edt, cinfo, data_offset);
947 /* Cleanup and release all dfilter resources */
948 dfilter_free(dfcode);
950 epan_dissect_cleanup(&edt);
952 /* Don't freeze/thaw the list when doing live capture */
953 /*packet_list_thaw();*/
955 if (cf->state == FILE_READ_ABORTED) {
956 /* Well, the user decided to abort the read. We're only called
957 when the child capture process closes the pipe to us (meaning
958 it's probably exited), so we can just close the capture
959 file; we return CF_READ_ABORTED so our caller can do whatever
960 is appropriate when that happens. */
962 return CF_READ_ABORTED;
965 /* We're done reading sequentially through the file. */
966 cf->state = FILE_READ_DONE;
968 /* We're done reading sequentially through the file; close the
969 sequential I/O side, to free up memory it requires. */
970 wtap_sequential_close(cf->provider.wth);
972 /* Allow the protocol dissectors to free up memory that they
973 * don't need after the sequential run-through of the packets. */
974 postseq_cleanup_all_protocols();
976 /* Update the file encapsulation; it might have changed based on the
977 packets we've read. */
978 cf->lnk_t = wtap_file_encap(cf->provider.wth);
980 /* Update the details in the file-set dialog, as the capture file
981 * has likely grown since we first stat-ed it */
982 fileset_update_file(cf->filename);
985 /* We got an error reading the capture file.
986 XXX - pop up a dialog box? */
987 if (err_info != NULL) {
988 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
989 wtap_strerror(*err), cf->filename, err_info);
992 g_warning("Error \"%s\" while reading \"%s\"",
993 wtap_strerror(*err), cf->filename);
995 return CF_READ_ERROR;
1000 #endif /* HAVE_LIBPCAP */
1003 cf_get_display_name(capture_file *cf)
1007 /* Return a name to use in displays */
1008 if (!cf->is_tempfile) {
1009 /* Get the last component of the file name, and use that. */
1011 displayname = g_filename_display_basename(cf->filename);
1013 displayname=g_strdup("(No file)");
1016 /* The file we read is a temporary file from a live capture or
1017 a merge operation; we don't mention its name, but, if it's
1018 from a capture, give the source of the capture. */
1020 displayname = g_strdup(cf->source);
1022 displayname = g_strdup("(Untitled)");
1029 cf_get_basename(capture_file *cf)
1033 /* Return a name to use in the GUI for the basename for files to
1034 which we save statistics */
1035 if (!cf->is_tempfile) {
1036 /* Get the last component of the file name, and use that. */
1038 displayname = g_filename_display_basename(cf->filename);
1040 /* If the file name ends with any extension that corresponds
1041 to a file type we support - including compressed versions
1042 of those files - strip it off. */
1043 size_t displayname_len = strlen(displayname);
1044 GSList *extensions = wtap_get_all_file_extensions_list();
1046 for (suffix = extensions; suffix != NULL; suffix = g_slist_next(suffix)) {
1047 /* Does the file name end with that extension? */
1048 const char *extension = (char *)suffix->data;
1049 size_t extension_len = strlen(extension);
1050 if (displayname_len > extension_len &&
1051 displayname[displayname_len - extension_len - 1] == '.' &&
1052 strcmp(&displayname[displayname_len - extension_len], extension) == 0) {
1053 /* Yes. Strip the extension off, and return the result. */
1054 displayname[displayname_len - extension_len - 1] = '\0';
1058 wtap_free_extensions_list(extensions);
1060 displayname=g_strdup("");
1063 /* The file we read is a temporary file from a live capture or
1064 a merge operation; we don't mention its name, but, if it's
1065 from a capture, give the source of the capture. */
1067 displayname = g_strdup(cf->source);
1069 displayname = g_strdup("");
1075 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1081 cf->source = g_strdup(source);
1083 cf->source = g_strdup("");
1087 const gchar *cf_get_tempfile_source(capture_file *cf) {
1095 /* XXX - use a macro instead? */
1097 cf_get_packet_count(capture_file *cf)
1102 /* XXX - use a macro instead? */
1104 cf_is_tempfile(capture_file *cf)
1106 return cf->is_tempfile;
1109 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1111 cf->is_tempfile = is_tempfile;
1115 /* XXX - use a macro instead? */
1116 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1118 cf->drops_known = drops_known;
1121 /* XXX - use a macro instead? */
1122 void cf_set_drops(capture_file *cf, guint32 drops)
1127 /* XXX - use a macro instead? */
1128 gboolean cf_get_drops_known(capture_file *cf)
1130 return cf->drops_known;
1133 /* XXX - use a macro instead? */
1134 guint32 cf_get_drops(capture_file *cf)
1139 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1141 cf->rfcode = rfcode;
1145 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1146 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1147 wtap_rec *rec, const guint8 *buf, gboolean add_to_packet_list)
1149 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1150 &cf->provider.ref, cf->provider.prev_dis);
1151 cf->provider.prev_cap = fdata;
1153 if (dfcode != NULL) {
1154 epan_dissect_prime_with_dfilter(edt, dfcode);
1157 /* Prepare coloring rules, this ensures that display filter rules containing
1158 * frame.color_rule references are still processed.
1159 * TODO: actually detect that situation or maybe apply other optimizations? */
1160 if (edt->tree && color_filters_used()) {
1161 color_filters_prime_edt(edt);
1162 fdata->need_colorize = 1;
1166 if (!fdata->visited) {
1167 /* This is the first pass, so prime the epan_dissect_t with the
1168 hfids postdissectors want on the first pass. */
1169 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1172 /* Dissect the frame. */
1173 epan_dissect_run_with_taps(edt, cf->cd_t, rec,
1174 frame_tvbuff_new(&cf->provider, fdata, buf),
1177 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1178 if (dfcode != NULL) {
1179 fdata->passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1181 if (fdata->passed_dfilter) {
1182 /* This frame passed the display filter but it may depend on other
1183 * (potentially not displayed) frames. Find those frames and mark them
1186 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->provider.frames);
1189 fdata->passed_dfilter = 1;
1191 if (fdata->passed_dfilter || fdata->ref_time)
1192 cf->displayed_count++;
1194 if (add_to_packet_list) {
1195 /* We fill the needed columns from new_packet_list */
1196 packet_list_append(cinfo, fdata);
1199 if (fdata->passed_dfilter || fdata->ref_time)
1201 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1202 cf->provider.prev_dis = fdata;
1204 /* If we haven't yet seen the first frame, this is it. */
1205 if (cf->first_displayed == 0)
1206 cf->first_displayed = fdata->num;
1208 /* This is the last frame we've seen so far. */
1209 cf->last_displayed = fdata->num;
1212 epan_dissect_reset(edt);
1216 * Read in a new record.
1217 * Returns TRUE if the packet was added to the packet (record) list,
1221 read_record(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1222 column_info *cinfo, gint64 offset)
1224 wtap_rec *rec = wtap_get_rec(cf->provider.wth);
1225 const guint8 *buf = wtap_get_buf_ptr(cf->provider.wth);
1228 gboolean passed = TRUE;
1229 gboolean added = FALSE;
1231 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1232 it's not already there.
1233 XXX - yes, this is O(N), so if every packet had a different
1234 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1235 there are probably going to be a small number of encapsulation types
1237 if (rec->rec_type == REC_TYPE_PACKET) {
1238 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
1241 /* The frame number of this packet, if we add it to the set of frames,
1242 would be one more than the count of frames in the file so far. */
1243 frame_data_init(&fdlocal, cf->count + 1, rec, offset, cf->cum_bytes);
1246 epan_dissect_t rf_edt;
1248 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1249 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1250 epan_dissect_run(&rf_edt, cf->cd_t, rec,
1251 frame_tvbuff_new(&cf->provider, &fdlocal, buf),
1253 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1254 epan_dissect_cleanup(&rf_edt);
1260 /* This does a shallow copy of fdlocal, which is good enough. */
1261 fdata = frame_data_sequence_add(cf->provider.frames, &fdlocal);
1264 if (rec->opt_comment != NULL)
1265 cf->packet_comment_count++;
1266 cf->f_datalen = offset + fdlocal.cap_len;
1268 /* When a redissection is in progress (or queued), do not process packets.
1269 * This will be done once all (new) packets have been scanned. */
1270 if (!cf->redissecting && cf->redissection_queued == RESCAN_NONE) {
1271 add_packet_to_packet_list(fdata, cf, edt, dfcode,
1272 cinfo, rec, buf, TRUE);
1280 typedef struct _callback_data_t {
1283 GTimeVal start_time;
1291 merge_callback(merge_event event, int num _U_,
1292 const merge_in_file_t in_files[], const guint in_file_count,
1296 callback_data_t *cb_data = (callback_data_t*) data;
1298 g_assert(cb_data != NULL);
1302 case MERGE_EVENT_INPUT_FILES_OPENED:
1306 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1310 case MERGE_EVENT_READY_TO_MERGE:
1311 /* Get the sum of the sizes of all the files. */
1312 for (i = 0; i < in_file_count; i++)
1313 cb_data->f_len += in_files[i].size;
1315 cb_data->prog_timer = g_timer_new();
1316 g_timer_start(cb_data->prog_timer);
1318 g_get_current_time(&cb_data->start_time);
1321 case MERGE_EVENT_RECORD_WAS_READ:
1323 /* Create the progress bar if necessary.
1324 We check on every iteration of the loop, so that it takes no
1325 longer than the standard time to create it (otherwise, for a
1326 large file, we might take considerably longer than that standard
1327 time in order to get to the next progress bar step). */
1328 if (cb_data->progbar == NULL) {
1329 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1330 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1334 * Update the progress bar, but do it only after
1335 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1336 * and packets_bar_update will likely trigger UI paint events, which
1337 * might take a while depending on the platform and display. Reset
1338 * our timer *after* painting.
1340 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1342 gint64 file_pos = 0;
1343 /* Get the sum of the seek positions in all of the files. */
1344 for (i = 0; i < in_file_count; i++)
1345 file_pos += wtap_read_so_far(in_files[i].wth);
1347 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1348 if (progbar_val > 1.0f) {
1349 /* Some file probably grew while we were reading it.
1350 That "shouldn't happen", so we'll just clip the progress
1355 if (cb_data->progbar != NULL) {
1356 gchar status_str[100];
1357 g_snprintf(status_str, sizeof(status_str),
1358 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1359 file_pos / 1024, cb_data->f_len / 1024);
1360 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1362 g_timer_start(cb_data->prog_timer);
1367 case MERGE_EVENT_DONE:
1368 /* We're done merging the files; destroy the progress bar if it was created. */
1369 if (cb_data->progbar != NULL)
1370 destroy_progress_dlg(cb_data->progbar);
1371 g_timer_destroy(cb_data->prog_timer);
1375 return cb_data->stop_flag;
1381 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1382 int in_file_count, char *const *in_filenames,
1383 int file_type, gboolean do_append)
1386 gchar *err_info = NULL;
1388 guint32 err_framenum;
1389 merge_result status;
1390 merge_progress_callback_t cb;
1391 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1393 /* prepare our callback routine */
1394 cb_data->pd_window = pd_window;
1395 cb.callback_func = merge_callback;
1398 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1400 /* merge the files */
1401 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1402 (const char *const *) in_filenames,
1403 in_file_count, do_append,
1404 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1405 "Wireshark", &cb, &err, &err_info,
1406 &err_fileno, &err_framenum);
1414 case MERGE_USER_ABORTED:
1415 /* this isn't really an error, though we will return CF_ERROR later */
1418 case MERGE_ERR_CANT_OPEN_INFILE:
1419 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1422 case MERGE_ERR_CANT_OPEN_OUTFILE:
1423 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1426 case MERGE_ERR_CANT_READ_INFILE:
1427 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1430 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1431 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1432 err_framenum, in_filenames[err_fileno]);
1435 case MERGE_ERR_CANT_WRITE_OUTFILE:
1436 cfile_write_failure_alert_box(in_filenames[err_fileno],
1437 *out_filenamep, err, err_info,
1438 err_framenum, file_type);
1441 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1442 cfile_close_failure_alert_box(*out_filenamep, err);
1446 simple_error_message_box("Unknown merge_files error %d", status);
1450 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1452 if (status != MERGE_OK) {
1453 /* Callers aren't expected to treat an error or an explicit abort
1454 differently - we put up error dialogs ourselves, so they don't
1462 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1464 const char *filter_new = dftext ? dftext : "";
1465 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1468 GTimeVal start_time;
1470 /* if new filter equals old one, do nothing unless told to do so */
1471 if (!force && strcmp(filter_new, filter_old) == 0) {
1477 if (dftext == NULL) {
1478 /* The new filter is an empty filter (i.e., display all packets).
1479 * so leave dfcode==NULL
1483 * We have a filter; make a copy of it (as we'll be saving it),
1484 * and try to compile it.
1486 dftext = g_strdup(dftext);
1487 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1488 /* The attempt failed; report an error. */
1489 simple_message_box(ESD_TYPE_ERROR, NULL,
1490 "See the help for a description of the display filter syntax.",
1491 "\"%s\" isn't a valid display filter: %s",
1499 if (dfcode == NULL) {
1500 /* Yes - free the filter text, and set it to null. */
1506 /* We have a valid filter. Replace the current filter. */
1507 g_free(cf->dfilter);
1508 cf->dfilter = dftext;
1509 g_get_current_time(&start_time);
1512 /* Now rescan the packet list, applying the new filter, but not
1513 * throwing away information constructed on a previous pass.
1514 * If a dissection is already in progress, queue it.
1516 if (cf->redissection_queued == RESCAN_NONE) {
1517 if (cf->read_lock) {
1518 cf->redissection_queued = RESCAN_SCAN;
1519 } else if (cf->state != FILE_CLOSED) {
1520 if (dftext == NULL) {
1521 rescan_packets(cf, "Resetting", "Filter", FALSE);
1523 rescan_packets(cf, "Filtering", dftext, FALSE);
1528 /* Cleanup and release all dfilter resources */
1529 dfilter_free(dfcode);
1535 cf_reftime_packets(capture_file *cf)
1537 ref_time_packets(cf);
1541 cf_redissect_packets(capture_file *cf)
1543 if (cf->read_lock || cf->redissection_queued == RESCAN_SCAN) {
1544 /* Dissection in progress, signal redissection rather than rescanning. That
1545 * would destroy the current (in-progress) dissection in "cf_read" which
1546 * will cause issues when "cf_read" tries to add packets to the list.
1547 * If a previous rescan was requested, "upgrade" it to a full redissection.
1549 cf->redissection_queued = RESCAN_REDISSECT;
1551 if (cf->redissection_queued != RESCAN_NONE) {
1552 /* Redissection is (already) queued, wait for "cf_read" to finish. */
1556 if (cf->state != FILE_CLOSED) {
1557 /* Restart dissection in case no cf_read is pending. */
1558 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1563 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1564 wtap_rec *rec, Buffer *buf)
1569 if (!wtap_seek_read(cf->provider.wth, fdata->file_off, rec, buf, &err, &err_info)) {
1570 cfile_read_failure_alert_box(cf->filename, err, err_info);
1577 cf_read_record(capture_file *cf, frame_data *fdata)
1579 return cf_read_record_r(cf, fdata, &cf->rec, &cf->buf);
1582 /* Rescan the list of packets, reconstructing the CList.
1584 "action" describes why we're doing this; it's used in the progress
1587 "action_item" describes what we're doing; it's used in the progress
1590 "redissect" is TRUE if we need to make the dissectors reconstruct
1591 any state information they have (because a preference that affects
1592 some dissector has changed, meaning some dissector might construct
1593 its state differently from the way it was constructed the last time). */
1595 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1597 /* Rescan packets new packet list */
1600 progdlg_t *progbar = NULL;
1601 GTimer *prog_timer = g_timer_new();
1603 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1604 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1605 gboolean selected_frame_seen;
1607 GTimeVal start_time;
1608 gchar status_str[100];
1612 gboolean create_proto_tree;
1614 gboolean add_to_packet_list = FALSE;
1616 guint32 frames_count;
1617 gboolean queued_rescan_type = RESCAN_NONE;
1619 /* Rescan in progress, clear pending actions. */
1620 cf->redissection_queued = RESCAN_NONE;
1621 g_assert(!cf->read_lock);
1622 cf->read_lock = TRUE;
1624 /* Compile the current display filter.
1625 * We assume this will not fail since cf->dfilter is only set in
1626 * cf_filter IFF the filter was valid.
1628 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1629 g_assert(!cf->dfilter || (compiled && dfcode));
1631 /* Get the union of the flags for all tap listeners. */
1632 tap_flags = union_of_tap_listener_flags();
1634 /* If any tap listeners require the columns, construct them. */
1635 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1638 * Determine whether we need to create a protocol tree.
1641 * we're going to apply a display filter;
1643 * one of the tap listeners is going to apply a filter;
1645 * one of the tap listeners requires a protocol tree;
1647 * we're redissecting and a postdissector wants field
1648 * values or protocols on the first pass.
1651 (dfcode != NULL || have_filtering_tap_listeners() ||
1652 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1653 (redissect && postdissectors_want_hfids()));
1655 reset_tap_listeners();
1656 /* Which frame, if any, is the currently selected frame?
1657 XXX - should the selected frame or the focus frame be the "current"
1658 frame, that frame being the one from which "Find Frame" searches
1660 selected_frame = cf->current_frame;
1662 /* Mark frame num as not found */
1663 selected_frame_num = -1;
1665 /* Freeze the packet list while we redo it, so we don't get any
1666 screen updates while it happens. */
1667 packet_list_freeze();
1670 /* We need to re-initialize all the state information that protocols
1671 keep, because some preference that controls a dissector has changed,
1672 which might cause the state information to be constructed differently
1673 by that dissector. */
1675 /* We might receive new packets while redissecting, and we don't
1676 want to dissect those before their time. */
1677 cf->redissecting = TRUE;
1679 /* 'reset' dissection session */
1680 epan_free(cf->epan);
1681 if (cf->edt && cf->edt->pi.fd) {
1682 /* All pointers in "per frame proto data" for the currently selected
1683 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1684 Free them here to avoid unintended usage in packet_list_clear(). */
1685 frame_data_destroy(cf->edt->pi.fd);
1687 cf->epan = ws_epan_new(cf);
1688 cf->cinfo.epan = cf->epan;
1690 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1691 called via epan_new() / init_dissection() when reloading Lua plugins. */
1692 if (!create_proto_tree && have_filtering_tap_listeners()) {
1693 create_proto_tree = TRUE;
1696 /* We need to redissect the packets so we have to discard our old
1697 * packet list store. */
1698 packet_list_clear();
1699 add_to_packet_list = TRUE;
1702 /* We don't yet know which will be the first and last frames displayed. */
1703 cf->first_displayed = 0;
1704 cf->last_displayed = 0;
1706 /* We currently don't display any packets */
1707 cf->displayed_count = 0;
1709 /* Iterate through the list of frames. Call a routine for each frame
1710 to check whether it should be displayed and, if so, add it to
1711 the display list. */
1712 cf->provider.ref = NULL;
1713 cf->provider.prev_dis = NULL;
1714 cf->provider.prev_cap = NULL;
1717 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1719 g_timer_start(prog_timer);
1720 /* Count of packets at which we've looked. */
1722 /* Progress so far. */
1725 cf->stop_flag = FALSE;
1726 g_get_current_time(&start_time);
1728 /* no previous row yet */
1729 prev_frame_num = -1;
1732 preceding_frame_num = -1;
1733 preceding_frame = NULL;
1734 following_frame_num = -1;
1735 following_frame = NULL;
1737 selected_frame_seen = FALSE;
1739 frames_count = cf->count;
1741 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1745 * Decryption secrets are read while sequentially processing records and
1746 * then passed to the dissector. During redissection, the previous secrets
1747 * are lost (see epan_free above), but they are not read again from the
1748 * file as only packet records are re-read. Therefore reset the wtap secrets
1749 * callback such that wtap resupplies the secrets callback with previously
1752 wtap_set_cb_new_secrets(cf->provider.wth, secrets_wtap_callback);
1755 for (framenum = 1; framenum <= frames_count; framenum++) {
1756 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1758 /* Create the progress bar if necessary.
1759 We check on every iteration of the loop, so that it takes no
1760 longer than the standard time to create it (otherwise, for a
1761 large file, we might take considerably longer than that standard
1762 time in order to get to the next progress bar step). */
1763 if (progbar == NULL)
1764 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1770 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1771 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1772 * likely trigger UI paint events, which might take a while depending on
1773 * the platform and display. Reset our timer *after* painting.
1775 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1776 /* let's not divide by zero. I should never be started
1777 * with count == 0, so let's assert that
1779 g_assert(cf->count > 0);
1780 progbar_val = (gfloat) count / frames_count;
1782 if (progbar != NULL) {
1783 g_snprintf(status_str, sizeof(status_str),
1784 "%4u of %u frames", count, frames_count);
1785 update_progress_dlg(progbar, progbar_val, status_str);
1788 g_timer_start(prog_timer);
1791 queued_rescan_type = cf->redissection_queued;
1792 if (queued_rescan_type != RESCAN_NONE) {
1793 /* A redissection was requested while an existing redissection was
1798 if (cf->stop_flag) {
1799 /* Well, the user decided to abort the filtering. Just stop.
1801 XXX - go back to the previous filter? Users probably just
1802 want not to wait for a filtering operation to finish;
1803 unless we cancel by having no filter, reverting to the
1804 previous filter will probably be even more expensive than
1805 continuing the filtering, as it involves going back to the
1806 beginning and filtering, and even with no filter we currently
1807 have to re-generate the entire clist, which is also expensive.
1809 I'm not sure what Network Monitor does, but it doesn't appear
1810 to give you an unfiltered display if you cancel. */
1817 /* Since all state for the frame was destroyed, mark the frame
1818 * as not visited, free the GSList referring to the state
1819 * data (the per-frame data itself was freed by
1820 * "init_dissection()"), and null out the GSList pointer. */
1821 frame_data_reset(fdata);
1822 frames_count = cf->count;
1825 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1826 fdata->dependent_of_displayed = 0;
1828 if (!cf_read_record(cf, fdata))
1829 break; /* error reading the frame */
1831 /* If the previous frame is displayed, and we haven't yet seen the
1832 selected frame, remember that frame - it's the closest one we've
1833 yet seen before the selected frame. */
1834 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->passed_dfilter) {
1835 preceding_frame_num = prev_frame_num;
1836 preceding_frame = prev_frame;
1839 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1841 ws_buffer_start_ptr(&cf->buf),
1842 add_to_packet_list);
1844 /* If this frame is displayed, and this is the first frame we've
1845 seen displayed after the selected frame, remember this frame -
1846 it's the closest one we've yet seen at or after the selected
1848 if (fdata->passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1849 following_frame_num = fdata->num;
1850 following_frame = fdata;
1852 if (fdata == selected_frame) {
1853 selected_frame_seen = TRUE;
1854 if (fdata->passed_dfilter)
1855 selected_frame_num = fdata->num;
1858 /* Remember this frame - it'll be the previous frame
1859 on the next pass through the loop. */
1860 prev_frame_num = fdata->num;
1864 epan_dissect_cleanup(&edt);
1866 /* We are done redissecting the packet list. */
1867 cf->redissecting = FALSE;
1870 frames_count = cf->count;
1871 /* Clear out what remains of the visited flags and per-frame data
1874 XXX - that may cause various forms of bogosity when dissecting
1875 these frames, as they won't have been seen by this sequential
1876 pass, but the only alternative I see is to keep scanning them
1877 even though the user requested that the scan stop, and that
1878 would leave the user stuck with an Wireshark grinding on
1879 until it finishes. Should we just stick them with that? */
1880 for (; framenum <= frames_count; framenum++) {
1881 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1882 frame_data_reset(fdata);
1886 /* We're done filtering the packets; destroy the progress bar if it
1888 if (progbar != NULL)
1889 destroy_progress_dlg(progbar);
1890 g_timer_destroy(prog_timer);
1892 /* Unfreeze the packet list. */
1893 if (!add_to_packet_list)
1894 packet_list_recreate_visible_rows();
1896 /* Compute the time it took to filter the file */
1897 compute_elapsed(cf, &start_time);
1901 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1903 if (selected_frame_num == -1) {
1904 /* The selected frame didn't pass the filter. */
1905 if (selected_frame == NULL) {
1906 /* That's because there *was* no selected frame. Make the first
1907 displayed frame the current frame. */
1908 selected_frame_num = 0;
1910 /* Find the nearest displayed frame to the selected frame (whether
1911 it's before or after that frame) and make that the current frame.
1912 If the next and previous displayed frames are equidistant from the
1913 selected frame, choose the next one. */
1914 g_assert(following_frame == NULL ||
1915 following_frame->num >= selected_frame->num);
1916 g_assert(preceding_frame == NULL ||
1917 preceding_frame->num <= selected_frame->num);
1918 if (following_frame == NULL) {
1919 /* No frame after the selected frame passed the filter, so we
1920 have to select the last displayed frame before the selected
1922 selected_frame_num = preceding_frame_num;
1923 selected_frame = preceding_frame;
1924 } else if (preceding_frame == NULL) {
1925 /* No frame before the selected frame passed the filter, so we
1926 have to select the first displayed frame after the selected
1928 selected_frame_num = following_frame_num;
1929 selected_frame = following_frame;
1931 /* Frames before and after the selected frame passed the filter, so
1932 we'll select the previous frame */
1933 selected_frame_num = preceding_frame_num;
1934 selected_frame = preceding_frame;
1939 if (selected_frame_num == -1) {
1940 /* There are no frames displayed at all. */
1941 cf_unselect_packet(cf);
1943 /* Either the frame that was selected passed the filter, or we've
1944 found the nearest displayed frame to that frame. Select it, make
1945 it the focus row, and make it visible. */
1946 /* Set to invalid to force update of packet list and packet details */
1947 cf->current_row = -1;
1948 if (selected_frame_num == 0) {
1949 packet_list_select_first_row();
1951 if (!packet_list_select_row_from_data(selected_frame)) {
1952 /* We didn't find a row corresponding to this frame.
1953 This means that the frame isn't being displayed currently,
1954 so we can't select it. */
1955 simple_message_box(ESD_TYPE_INFO, NULL,
1956 "The capture file is probably not fully dissected.",
1957 "End of capture exceeded.");
1962 /* Cleanup and release all dfilter resources */
1963 dfilter_free(dfcode);
1965 /* It is safe again to execute redissections. */
1966 g_assert(cf->read_lock);
1967 cf->read_lock = FALSE;
1969 /* If another rescan (due to dfilter change) or redissection (due to profile
1970 * change) was requested, the rescan above is aborted and restarted here. */
1971 if (queued_rescan_type != RESCAN_NONE) {
1972 redissect = redissect || queued_rescan_type == RESCAN_REDISSECT;
1973 rescan_packets(cf, "Reprocessing", "all packets", redissect);
1979 * Scan through all frame data and recalculate the ref time
1980 * without rereading the file.
1981 * XXX - do we need a progres bar or is this fast enough?
1984 ref_time_packets(capture_file *cf)
1990 cf->provider.ref = NULL;
1991 cf->provider.prev_dis = NULL;
1994 for (framenum = 1; framenum <= cf->count; framenum++) {
1995 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1997 /* just add some value here until we know if it is being displayed or not */
1998 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
2004 /* If we don't have the time stamp of the first packet in the
2005 capture, it's because this is the first packet. Save the time
2006 stamp of this packet as the time stamp of the first packet. */
2007 if (cf->provider.ref == NULL)
2008 cf->provider.ref = fdata;
2009 /* if this frames is marked as a reference time frame, reset
2010 firstsec and firstusec to this frame */
2011 if (fdata->ref_time)
2012 cf->provider.ref = fdata;
2014 /* If we don't have the time stamp of the previous displayed packet,
2015 it's because this is the first displayed packet. Save the time
2016 stamp of this packet as the time stamp of the previous displayed
2018 if (cf->provider.prev_dis == NULL) {
2019 cf->provider.prev_dis = fdata;
2022 /* Get the time elapsed between the first packet and this packet. */
2023 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
2024 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
2026 /* If it's greater than the current elapsed time, set the elapsed time
2027 to it (we check for "greater than" so as not to be confused by
2028 time moving backwards). */
2029 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2030 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2031 cf->elapsed_time = rel_ts;
2034 /* If this frame is displayed, get the time elapsed between the
2035 previous displayed packet and this packet. */
2036 if ( fdata->passed_dfilter ) {
2037 fdata->prev_dis_num = cf->provider.prev_dis->num;
2038 cf->provider.prev_dis = fdata;
2044 if ( (fdata->passed_dfilter) || (fdata->ref_time) ) {
2045 /* This frame either passed the display filter list or is marked as
2046 a time reference frame. All time reference frames are displayed
2047 even if they don't pass the display filter */
2048 if (fdata->ref_time) {
2049 /* if this was a TIME REF frame we should reset the cum_bytes field */
2050 cf->cum_bytes = fdata->pkt_len;
2051 fdata->cum_bytes = cf->cum_bytes;
2053 /* increase cum_bytes with this packets length */
2054 cf->cum_bytes += fdata->pkt_len;
2067 process_specified_records(capture_file *cf, packet_range_t *range,
2068 const char *string1, const char *string2, gboolean terminate_is_stop,
2069 gboolean (*callback)(capture_file *, frame_data *,
2070 wtap_rec *, const guint8 *, void *),
2071 void *callback_args,
2072 gboolean show_progress_bar)
2078 psp_return_t ret = PSP_FINISHED;
2080 progdlg_t *progbar = NULL;
2081 GTimer *prog_timer = g_timer_new();
2084 GTimeVal progbar_start_time;
2085 gchar progbar_status_str[100];
2086 range_process_e process_this;
2088 wtap_rec_init(&rec);
2089 ws_buffer_init(&buf, 1500);
2091 g_timer_start(prog_timer);
2092 /* Count of packets at which we've looked. */
2094 /* Progress so far. */
2097 if (cf->read_lock) {
2098 g_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename);
2101 cf->read_lock = TRUE;
2103 cf->stop_flag = FALSE;
2104 g_get_current_time(&progbar_start_time);
2107 packet_range_process_init(range);
2109 /* Iterate through all the packets, printing the packets that
2110 were selected by the current display filter. */
2111 for (framenum = 1; framenum <= cf->count; framenum++) {
2112 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
2114 /* Create the progress bar if necessary.
2115 We check on every iteration of the loop, so that it takes no
2116 longer than the standard time to create it (otherwise, for a
2117 large file, we might take considerably longer than that standard
2118 time in order to get to the next progress bar step). */
2119 if (show_progress_bar && progbar == NULL)
2120 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2123 &progbar_start_time,
2127 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2128 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2129 * likely trigger UI paint events, which might take a while depending on
2130 * the platform and display. Reset our timer *after* painting.
2132 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2133 /* let's not divide by zero. I should never be started
2134 * with count == 0, so let's assert that
2136 g_assert(cf->count > 0);
2137 progbar_val = (gfloat) progbar_count / cf->count;
2139 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2140 "%4u of %u packets", progbar_count, cf->count);
2141 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2143 g_timer_start(prog_timer);
2146 if (cf->stop_flag) {
2147 /* Well, the user decided to abort the operation. Just stop,
2148 and arrange to return PSP_STOPPED to our caller, so they know
2149 it was stopped explicitly. */
2156 if (range != NULL) {
2157 /* do we have to process this packet? */
2158 process_this = packet_range_process_packet(range, fdata);
2159 if (process_this == range_process_next) {
2160 /* this packet uninteresting, continue with next one */
2162 } else if (process_this == range_processing_finished) {
2163 /* all interesting packets processed, stop the loop */
2168 /* Get the packet */
2169 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2170 /* Attempt to get the packet failed. */
2174 /* Process the packet */
2175 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2176 /* Callback failed. We assume it reported the error appropriately. */
2182 /* We're done printing the packets; destroy the progress bar if
2184 if (progbar != NULL)
2185 destroy_progress_dlg(progbar);
2186 g_timer_destroy(prog_timer);
2188 g_assert(cf->read_lock);
2189 cf->read_lock = FALSE;
2191 wtap_rec_cleanup(&rec);
2192 ws_buffer_free(&buf);
2200 } retap_callback_args_t;
2203 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2204 const guint8 *pd, void *argsp)
2206 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2208 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2209 frame_tvbuff_new(&cf->provider, fdata, pd),
2210 fdata, args->cinfo);
2211 epan_dissect_reset(&args->edt);
2217 cf_retap_packets(capture_file *cf)
2219 packet_range_t range;
2220 retap_callback_args_t callback_args;
2221 gboolean create_proto_tree;
2225 /* Presumably the user closed the capture file. */
2227 return CF_READ_ABORTED;
2230 cf_callback_invoke(cf_cb_file_retap_started, cf);
2232 /* Get the union of the flags for all tap listeners. */
2233 tap_flags = union_of_tap_listener_flags();
2235 /* If any tap listeners require the columns, construct them. */
2236 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2239 * Determine whether we need to create a protocol tree.
2242 * one of the tap listeners is going to apply a filter;
2244 * one of the tap listeners requires a protocol tree.
2247 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2249 /* Reset the tap listeners. */
2250 reset_tap_listeners();
2252 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2254 /* Iterate through the list of packets, dissecting all packets and
2255 re-running the taps. */
2256 packet_range_init(&range, cf);
2257 packet_range_process_init(&range);
2259 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2260 "all packets", TRUE, retap_packet,
2261 &callback_args, TRUE);
2263 packet_range_cleanup(&range);
2264 epan_dissect_cleanup(&callback_args.edt);
2266 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2270 /* Completed successfully. */
2274 /* Well, the user decided to abort the refiltering.
2275 Return CF_READ_ABORTED so our caller knows they did that. */
2276 return CF_READ_ABORTED;
2279 /* Error while retapping. */
2280 return CF_READ_ERROR;
2283 g_assert_not_reached();
2288 print_args_t *print_args;
2289 gboolean print_header_line;
2290 char *header_line_buf;
2291 int header_line_buf_len;
2292 gboolean print_formfeed;
2293 gboolean print_separator;
2297 int num_visible_cols;
2300 } print_callback_args_t;
2303 print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2304 const guint8 *pd, void *argsp)
2306 print_callback_args_t *args = (print_callback_args_t *)argsp;
2312 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2313 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2314 col_item_t* col_item;
2316 /* Fill in the column information if we're printing the summary
2318 if (args->print_args->print_summary) {
2319 col_custom_prime_edt(&args->edt, &cf->cinfo);
2320 epan_dissect_run(&args->edt, cf->cd_t, rec,
2321 frame_tvbuff_new(&cf->provider, fdata, pd),
2323 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2325 epan_dissect_run(&args->edt, cf->cd_t, rec,
2326 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2328 if (args->print_formfeed) {
2329 if (!new_page(args->print_args->stream))
2333 * Print another header line if we print a packet summary on the
2336 if (args->print_args->print_col_headings)
2337 args->print_header_line = TRUE;
2339 if (args->print_separator) {
2340 if (!print_line(args->print_args->stream, 0, ""))
2346 * We generate bookmarks, if the output format supports them.
2347 * The name is "__frameN__".
2349 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2351 if (args->print_args->print_summary) {
2352 if (!args->print_args->print_col_headings)
2353 args->print_header_line = FALSE;
2354 if (args->print_header_line) {
2355 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2357 args->print_header_line = FALSE; /* we might not need to print any more */
2359 cp = &args->line_buf[0];
2361 for (i = 0; i < args->num_visible_cols; i++) {
2362 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2363 /* Find the length of the string for this column. */
2364 column_len = (int) strlen(col_item->col_data);
2365 if (args->col_widths[i] > column_len)
2366 column_len = args->col_widths[i];
2368 /* Make sure there's room in the line buffer for the column; if not,
2369 double its length. */
2370 line_len += column_len + 1; /* "+1" for space */
2371 if (line_len > args->line_buf_len) {
2372 cp_off = (int) (cp - args->line_buf);
2373 args->line_buf_len = 2 * line_len;
2374 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2375 cp = args->line_buf + cp_off;
2378 /* Right-justify the packet number column. */
2379 if (col_item->col_fmt == COL_NUMBER)
2380 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2382 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2384 if (i != args->num_visible_cols - 1)
2390 * Generate a bookmark, using the summary line as the title.
2392 if (!print_bookmark(args->print_args->stream, bookmark_name,
2396 if (!print_line(args->print_args->stream, 0, args->line_buf))
2400 * Generate a bookmark, using "Frame N" as the title, as we're not
2401 * printing the summary line.
2403 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2404 if (!print_bookmark(args->print_args->stream, bookmark_name,
2407 } /* if (print_summary) */
2409 if (args->print_args->print_dissections != print_dissections_none) {
2410 if (args->print_args->print_summary) {
2411 /* Separate the summary line from the tree with a blank line. */
2412 if (!print_line(args->print_args->stream, 0, ""))
2416 /* Print the information in that tree. */
2417 if (!proto_tree_print(args->print_args->print_dissections,
2418 args->print_args->print_hex, &args->edt, NULL,
2419 args->print_args->stream))
2422 /* Print a blank line if we print anything after this (aka more than one packet). */
2423 args->print_separator = TRUE;
2425 /* Print a header line if we print any more packet summaries */
2426 if (args->print_args->print_col_headings)
2427 args->print_header_line = TRUE;
2430 if (args->print_args->print_hex) {
2431 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2432 if (!print_line(args->print_args->stream, 0, ""))
2435 /* Print the full packet data as hex. */
2436 if (!print_hex_data(args->print_args->stream, &args->edt))
2439 /* Print a blank line if we print anything after this (aka more than one packet). */
2440 args->print_separator = TRUE;
2442 /* Print a header line if we print any more packet summaries */
2443 if (args->print_args->print_col_headings)
2444 args->print_header_line = TRUE;
2445 } /* if (args->print_args->print_dissections != print_dissections_none) */
2447 epan_dissect_reset(&args->edt);
2449 /* do we want to have a formfeed between each packet from now on? */
2450 if (args->print_args->print_formfeed) {
2451 args->print_formfeed = TRUE;
2457 epan_dissect_reset(&args->edt);
2462 cf_print_packets(capture_file *cf, print_args_t *print_args,
2463 gboolean show_progress_bar)
2465 print_callback_args_t callback_args;
2468 int i, cp_off, column_len, line_len;
2469 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2473 gboolean proto_tree_needed;
2475 callback_args.print_args = print_args;
2476 callback_args.print_header_line = print_args->print_col_headings;
2477 callback_args.header_line_buf = NULL;
2478 callback_args.header_line_buf_len = 256;
2479 callback_args.print_formfeed = FALSE;
2480 callback_args.print_separator = FALSE;
2481 callback_args.line_buf = NULL;
2482 callback_args.line_buf_len = 256;
2483 callback_args.col_widths = NULL;
2484 callback_args.num_visible_cols = 0;
2485 callback_args.visible_cols = NULL;
2487 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2488 destroy_print_stream(print_args->stream);
2489 return CF_PRINT_WRITE_ERROR;
2492 if (print_args->print_summary) {
2493 /* We're printing packet summaries. Allocate the header line buffer
2494 and get the column widths. */
2495 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2497 /* Find the number of visible columns and the last visible column */
2498 for (i = 0; i < prefs.num_cols; i++) {
2500 clp = g_list_nth(prefs.col_list, i);
2501 if (clp == NULL) /* Sanity check, Invalid column requested */
2504 cfmt = (fmt_data *) clp->data;
2505 if (cfmt->visible) {
2507 last_visible_col = i;
2511 /* if num_visible_col is 0, we are done */
2512 if (num_visible_col == 0) {
2513 g_free(callback_args.header_line_buf);
2517 /* Find the widths for each of the columns - maximum of the
2518 width of the title and the width of the data - and construct
2519 a buffer with a line containing the column titles. */
2520 callback_args.num_visible_cols = num_visible_col;
2521 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2522 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2523 cp = &callback_args.header_line_buf[0];
2525 visible_col_count = 0;
2526 for (i = 0; i < cf->cinfo.num_cols; i++) {
2528 clp = g_list_nth(prefs.col_list, i);
2529 if (clp == NULL) /* Sanity check, Invalid column requested */
2532 cfmt = (fmt_data *) clp->data;
2533 if (cfmt->visible == FALSE)
2536 /* Save the order of visible columns */
2537 callback_args.visible_cols[visible_col_count] = i;
2539 /* Don't pad the last column. */
2540 if (i == last_visible_col)
2541 callback_args.col_widths[visible_col_count] = 0;
2543 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2544 data_width = get_column_char_width(get_column_format(i));
2545 if (data_width > callback_args.col_widths[visible_col_count])
2546 callback_args.col_widths[visible_col_count] = data_width;
2549 /* Find the length of the string for this column. */
2550 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2551 if (callback_args.col_widths[visible_col_count] > column_len)
2552 column_len = callback_args.col_widths[visible_col_count];
2554 /* Make sure there's room in the line buffer for the column; if not,
2555 double its length. */
2556 line_len += column_len + 1; /* "+1" for space */
2557 if (line_len > callback_args.header_line_buf_len) {
2558 cp_off = (int) (cp - callback_args.header_line_buf);
2559 callback_args.header_line_buf_len = 2 * line_len;
2560 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2561 callback_args.header_line_buf_len + 1);
2562 cp = callback_args.header_line_buf + cp_off;
2565 /* Right-justify the packet number column. */
2566 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2567 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2569 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2571 if (i != cf->cinfo.num_cols - 1)
2574 visible_col_count++;
2578 /* Now start out the main line buffer with the same length as the
2579 header line buffer. */
2580 callback_args.line_buf_len = callback_args.header_line_buf_len;
2581 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2582 } /* if (print_summary) */
2584 /* Create the protocol tree, and make it visible, if we're printing
2585 the dissection or the hex data.
2586 XXX - do we need it if we're just printing the hex data? */
2588 callback_args.print_args->print_dissections != print_dissections_none ||
2589 callback_args.print_args->print_hex ||
2590 have_custom_cols(&cf->cinfo) || have_field_extractors();
2591 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2593 /* Iterate through the list of packets, printing the packets we were
2595 ret = process_specified_records(cf, &print_args->range, "Printing",
2596 "selected packets", TRUE, print_packet,
2597 &callback_args, show_progress_bar);
2598 epan_dissect_cleanup(&callback_args.edt);
2599 g_free(callback_args.header_line_buf);
2600 g_free(callback_args.line_buf);
2601 g_free(callback_args.col_widths);
2602 g_free(callback_args.visible_cols);
2607 /* Completed successfully. */
2611 /* Well, the user decided to abort the printing.
2613 XXX - note that what got generated before they did that
2614 will get printed if we're piping to a print program; we'd
2615 have to write to a file and then hand that to the print
2616 program to make it actually not print anything. */
2620 /* Error while printing.
2622 XXX - note that what got generated before they did that
2623 will get printed if we're piping to a print program; we'd
2624 have to write to a file and then hand that to the print
2625 program to make it actually not print anything. */
2626 destroy_print_stream(print_args->stream);
2627 return CF_PRINT_WRITE_ERROR;
2630 if (!print_finale(print_args->stream)) {
2631 destroy_print_stream(print_args->stream);
2632 return CF_PRINT_WRITE_ERROR;
2635 if (!destroy_print_stream(print_args->stream))
2636 return CF_PRINT_WRITE_ERROR;
2644 print_args_t *print_args;
2645 json_dumper jdumper;
2646 } write_packet_callback_args_t;
2649 write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2650 const guint8 *pd, void *argsp)
2652 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2654 /* Create the protocol tree, but don't fill in the column information. */
2655 epan_dissect_run(&args->edt, cf->cd_t, rec,
2656 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2658 /* Write out the information in that tree. */
2659 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE);
2661 epan_dissect_reset(&args->edt);
2663 return !ferror(args->fh);
2667 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2669 write_packet_callback_args_t callback_args;
2673 fh = ws_fopen(print_args->file, "w");
2675 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2677 write_pdml_preamble(fh, cf->filename);
2680 return CF_PRINT_WRITE_ERROR;
2683 callback_args.fh = fh;
2684 callback_args.print_args = print_args;
2685 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2687 /* Iterate through the list of packets, printing the packets we were
2689 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2690 "selected packets", TRUE,
2691 write_pdml_packet, &callback_args, TRUE);
2693 epan_dissect_cleanup(&callback_args.edt);
2698 /* Completed successfully. */
2702 /* Well, the user decided to abort the printing. */
2706 /* Error while printing. */
2708 return CF_PRINT_WRITE_ERROR;
2711 write_pdml_finale(fh);
2714 return CF_PRINT_WRITE_ERROR;
2717 /* XXX - check for an error */
2724 write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2725 const guint8 *pd, void *argsp)
2727 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2729 /* Fill in the column information */
2730 col_custom_prime_edt(&args->edt, &cf->cinfo);
2731 epan_dissect_run(&args->edt, cf->cd_t, rec,
2732 frame_tvbuff_new(&cf->provider, fdata, pd),
2734 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2736 /* Write out the column information. */
2737 write_psml_columns(&args->edt, args->fh, FALSE);
2739 epan_dissect_reset(&args->edt);
2741 return !ferror(args->fh);
2745 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2747 write_packet_callback_args_t callback_args;
2751 gboolean proto_tree_needed;
2753 fh = ws_fopen(print_args->file, "w");
2755 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2757 write_psml_preamble(&cf->cinfo, fh);
2760 return CF_PRINT_WRITE_ERROR;
2763 callback_args.fh = fh;
2764 callback_args.print_args = print_args;
2766 /* Fill in the column information, only create the protocol tree
2767 if having custom columns or field extractors. */
2768 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2769 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2771 /* Iterate through the list of packets, printing the packets we were
2773 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2774 "selected packets", TRUE,
2775 write_psml_packet, &callback_args, TRUE);
2777 epan_dissect_cleanup(&callback_args.edt);
2782 /* Completed successfully. */
2786 /* Well, the user decided to abort the printing. */
2790 /* Error while printing. */
2792 return CF_PRINT_WRITE_ERROR;
2795 write_psml_finale(fh);
2798 return CF_PRINT_WRITE_ERROR;
2801 /* XXX - check for an error */
2808 write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2809 const guint8 *pd, void *argsp)
2811 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2813 /* Fill in the column information */
2814 col_custom_prime_edt(&args->edt, &cf->cinfo);
2815 epan_dissect_run(&args->edt, cf->cd_t, rec,
2816 frame_tvbuff_new(&cf->provider, fdata, pd),
2818 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2820 /* Write out the column information. */
2821 write_csv_columns(&args->edt, args->fh);
2823 epan_dissect_reset(&args->edt);
2825 return !ferror(args->fh);
2829 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2831 write_packet_callback_args_t callback_args;
2832 gboolean proto_tree_needed;
2836 fh = ws_fopen(print_args->file, "w");
2838 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2840 write_csv_column_titles(&cf->cinfo, fh);
2843 return CF_PRINT_WRITE_ERROR;
2846 callback_args.fh = fh;
2847 callback_args.print_args = print_args;
2849 /* only create the protocol tree if having custom columns or field extractors. */
2850 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2851 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2853 /* Iterate through the list of packets, printing the packets we were
2855 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2856 "selected packets", TRUE,
2857 write_csv_packet, &callback_args, TRUE);
2859 epan_dissect_cleanup(&callback_args.edt);
2864 /* Completed successfully. */
2868 /* Well, the user decided to abort the printing. */
2872 /* Error while printing. */
2874 return CF_PRINT_WRITE_ERROR;
2877 /* XXX - check for an error */
2884 carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2885 const guint8 *pd, void *argsp)
2887 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2889 epan_dissect_run(&args->edt, cf->cd_t, rec,
2890 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2891 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2892 epan_dissect_reset(&args->edt);
2894 return !ferror(args->fh);
2898 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2900 write_packet_callback_args_t callback_args;
2904 fh = ws_fopen(print_args->file, "w");
2907 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2911 return CF_PRINT_WRITE_ERROR;
2914 callback_args.fh = fh;
2915 callback_args.print_args = print_args;
2916 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2918 /* Iterate through the list of packets, printing the packets we were
2920 ret = process_specified_records(cf, &print_args->range,
2922 "selected packets", TRUE,
2923 carrays_write_packet, &callback_args, TRUE);
2925 epan_dissect_cleanup(&callback_args.edt);
2929 /* Completed successfully. */
2932 /* Well, the user decided to abort the printing. */
2935 /* Error while printing. */
2937 return CF_PRINT_WRITE_ERROR;
2945 write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2946 const guint8 *pd, void *argsp)
2948 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2950 /* Create the protocol tree, but don't fill in the column information. */
2951 epan_dissect_run(&args->edt, cf->cd_t, rec,
2952 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2954 /* Write out the information in that tree. */
2955 write_json_proto_tree(NULL, args->print_args->print_dissections,
2956 args->print_args->print_hex, NULL, PF_NONE,
2957 &args->edt, &cf->cinfo, proto_node_group_children_by_unique,
2960 epan_dissect_reset(&args->edt);
2962 return !ferror(args->fh);
2966 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2968 write_packet_callback_args_t callback_args;
2972 fh = ws_fopen(print_args->file, "w");
2974 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2976 callback_args.jdumper = write_json_preamble(fh);
2979 return CF_PRINT_WRITE_ERROR;
2982 callback_args.fh = fh;
2983 callback_args.print_args = print_args;
2984 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2986 /* Iterate through the list of packets, printing the packets we were
2988 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2989 "selected packets", TRUE,
2990 write_json_packet, &callback_args, TRUE);
2992 epan_dissect_cleanup(&callback_args.edt);
2997 /* Completed successfully. */
3001 /* Well, the user decided to abort the printing. */
3005 /* Error while printing. */
3007 return CF_PRINT_WRITE_ERROR;
3010 write_json_finale(&callback_args.jdumper);
3013 return CF_PRINT_WRITE_ERROR;
3016 /* XXX - check for an error */
3023 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3024 search_direction dir)
3028 mdata.string = string;
3029 mdata.string_len = strlen(string);
3030 return find_packet(cf, match_protocol_tree, &mdata, dir);
3034 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3036 mdata->frame_matched = FALSE;
3037 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3038 mdata->string_len = strlen(mdata->string);
3040 /* Iterate through all the nodes looking for matching text */
3041 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3042 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3046 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3048 match_data *mdata = (match_data *)criterion;
3051 /* Load the frame's data. */
3052 if (!cf_read_record(cf, fdata)) {
3053 /* Attempt to get the packet failed. */
3057 /* Construct the protocol tree, including the displayed text */
3058 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3059 /* We don't need the column information */
3060 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3061 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3064 /* Iterate through all the nodes, seeing if they have text that matches. */
3066 mdata->frame_matched = FALSE;
3067 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3068 epan_dissect_cleanup(&edt);
3069 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3073 match_subtree_text(proto_node *node, gpointer data)
3075 match_data *mdata = (match_data *) data;
3076 const gchar *string = mdata->string;
3077 size_t string_len = mdata->string_len;
3078 capture_file *cf = mdata->cf;
3079 field_info *fi = PNODE_FINFO(node);
3080 gchar label_str[ITEM_LABEL_LENGTH];
3087 /* dissection with an invisible proto tree? */
3090 if (mdata->frame_matched) {
3091 /* We already had a match; don't bother doing any more work. */
3095 /* Don't match invisible entries. */
3096 if (PROTO_ITEM_IS_HIDDEN(node))
3099 /* was a free format label produced? */
3101 label_ptr = fi->rep->representation;
3103 /* no, make a generic label */
3104 label_ptr = label_str;
3105 proto_item_fill_label(fi, label_str);
3109 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3110 mdata->frame_matched = TRUE;
3115 /* Does that label match? */
3116 label_len = strlen(label_ptr);
3117 for (i = 0; i < label_len; i++) {
3118 c_char = label_ptr[i];
3120 c_char = g_ascii_toupper(c_char);
3121 if (c_char == string[c_match]) {
3123 if (c_match == string_len) {
3124 /* No need to look further; we have a match */
3125 mdata->frame_matched = TRUE;
3134 /* Recurse into the subtree, if it exists */
3135 if (node->first_child != NULL)
3136 proto_tree_children_foreach(node, match_subtree_text, mdata);
3140 cf_find_packet_summary_line(capture_file *cf, const char *string,
3141 search_direction dir)
3145 mdata.string = string;
3146 mdata.string_len = strlen(string);
3147 return find_packet(cf, match_summary_line, &mdata, dir);
3151 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3153 match_data *mdata = (match_data *)criterion;
3154 const gchar *string = mdata->string;
3155 size_t string_len = mdata->string_len;
3157 const char *info_column;
3158 size_t info_column_len;
3159 match_result result = MR_NOTMATCHED;
3165 /* Load the frame's data. */
3166 if (!cf_read_record(cf, fdata)) {
3167 /* Attempt to get the packet failed. */
3171 /* Don't bother constructing the protocol tree */
3172 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3173 /* Get the column information */
3174 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3175 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3178 /* Find the Info column */
3179 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3180 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3181 /* Found it. See if we match. */
3182 info_column = edt.pi.cinfo->columns[colx].col_data;
3183 info_column_len = strlen(info_column);
3185 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3186 result = MR_MATCHED;
3190 for (i = 0; i < info_column_len; i++) {
3191 c_char = info_column[i];
3193 c_char = g_ascii_toupper(c_char);
3194 if (c_char == string[c_match]) {
3196 if (c_match == string_len) {
3197 result = MR_MATCHED;
3207 epan_dissect_cleanup(&edt);
3214 } cbs_t; /* "Counted byte string" */
3218 * The current match_* routines only support ASCII case insensitivity and don't
3219 * convert UTF-8 inputs to UTF-16 for matching.
3221 * We could modify them to use the GLib Unicode routines or the International
3222 * Components for Unicode library but it's not apparent that we could do so
3223 * without consuming a lot more CPU and memory or that searching would be
3224 * significantly better.
3228 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3229 search_direction dir)
3234 info.data_len = string_size;
3236 /* Regex, String or hex search? */
3238 /* Regular Expression search */
3239 return find_packet(cf, match_regex, NULL, dir);
3240 } else if (cf->string) {
3241 /* String search - what type of string? */
3242 switch (cf->scs_type) {
3244 case SCS_NARROW_AND_WIDE:
3245 return find_packet(cf, match_narrow_and_wide, &info, dir);
3248 return find_packet(cf, match_narrow, &info, dir);
3251 return find_packet(cf, match_wide, &info, dir);
3254 g_assert_not_reached();
3258 return find_packet(cf, match_binary, &info, dir);
3262 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3264 cbs_t *info = (cbs_t *)criterion;
3265 const guint8 *ascii_text = info->data;
3266 size_t textlen = info->data_len;
3267 match_result result;
3274 /* Load the frame's data. */
3275 if (!cf_read_record(cf, fdata)) {
3276 /* Attempt to get the packet failed. */
3280 result = MR_NOTMATCHED;
3281 buf_len = fdata->cap_len;
3282 pd = ws_buffer_start_ptr(&cf->buf);
3284 while (i < buf_len) {
3287 c_char = g_ascii_toupper(c_char);
3288 if (c_char != '\0') {
3289 if (c_char == ascii_text[c_match]) {
3291 if (c_match == textlen) {
3292 result = MR_MATCHED;
3293 cf->search_pos = i; /* Save the position of the last character
3294 for highlighting the field. */
3295 cf->search_len = (guint32)textlen;
3300 g_assert(i>=c_match);
3301 i -= (guint32)c_match;
3311 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3314 cbs_t *info = (cbs_t *)criterion;
3315 const guint8 *ascii_text = info->data;
3316 size_t textlen = info->data_len;
3317 match_result result;
3323 /* Load the frame's data. */
3324 if (!cf_read_record(cf, fdata)) {
3325 /* Attempt to get the packet failed. */
3329 result = MR_NOTMATCHED;
3330 buf_len = fdata->cap_len;
3331 pd = ws_buffer_start_ptr(&cf->buf);
3333 while (i < buf_len) {
3336 c_char = g_ascii_toupper(c_char);
3337 if (c_char == ascii_text[c_match]) {
3339 if (c_match == textlen) {
3340 result = MR_MATCHED;
3341 cf->search_pos = i; /* Save the position of the last character
3342 for highlighting the field. */
3343 cf->search_len = (guint32)textlen;
3348 g_assert(i>=c_match);
3349 i -= (guint32)c_match;
3359 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3361 cbs_t *info = (cbs_t *)criterion;
3362 const guint8 *ascii_text = info->data;
3363 size_t textlen = info->data_len;
3364 match_result result;
3371 /* Load the frame's data. */
3372 if (!cf_read_record(cf, fdata)) {
3373 /* Attempt to get the packet failed. */
3377 result = MR_NOTMATCHED;
3378 buf_len = fdata->cap_len;
3379 pd = ws_buffer_start_ptr(&cf->buf);
3381 while (i < buf_len) {
3384 c_char = g_ascii_toupper(c_char);
3385 if (c_char == ascii_text[c_match]) {
3387 if (c_match == textlen) {
3388 result = MR_MATCHED;
3389 cf->search_pos = i; /* Save the position of the last character
3390 for highlighting the field. */
3391 cf->search_len = (guint32)textlen;
3397 g_assert(i>=(c_match*2));
3398 i -= (guint32)c_match*2;
3407 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3409 cbs_t *info = (cbs_t *)criterion;
3410 const guint8 *binary_data = info->data;
3411 size_t datalen = info->data_len;
3412 match_result result;
3418 /* Load the frame's data. */
3419 if (!cf_read_record(cf, fdata)) {
3420 /* Attempt to get the packet failed. */
3424 result = MR_NOTMATCHED;
3425 buf_len = fdata->cap_len;
3426 pd = ws_buffer_start_ptr(&cf->buf);
3428 while (i < buf_len) {
3429 if (pd[i] == binary_data[c_match]) {
3431 if (c_match == datalen) {
3432 result = MR_MATCHED;
3433 cf->search_pos = i; /* Save the position of the last character
3434 for highlighting the field. */
3435 cf->search_len = (guint32)datalen;
3440 g_assert(i>=c_match);
3441 i -= (guint32)c_match;
3450 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3452 match_result result = MR_NOTMATCHED;
3453 GMatchInfo *match_info = NULL;
3455 /* Load the frame's data. */
3456 if (!cf_read_record(cf, fdata)) {
3457 /* Attempt to get the packet failed. */
3461 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3462 0, (GRegexMatchFlags) 0, &match_info, NULL))
3464 gint start_pos = 0, end_pos = 0;
3465 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3466 cf->search_pos = end_pos - 1;
3467 cf->search_len = end_pos - start_pos;
3468 result = MR_MATCHED;
3474 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3475 search_direction dir)
3477 return find_packet(cf, match_dfilter, sfcode, dir);
3481 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3482 search_direction dir)
3487 if (!dfilter_compile(filter, &sfcode, NULL)) {
3489 * XXX - this shouldn't happen, as the filter string is machine
3494 if (sfcode == NULL) {
3496 * XXX - this shouldn't happen, as the filter string is machine
3501 result = find_packet(cf, match_dfilter, sfcode, dir);
3502 dfilter_free(sfcode);
3507 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3509 dfilter_t *sfcode = (dfilter_t *)criterion;
3511 match_result result;
3513 /* Load the frame's data. */
3514 if (!cf_read_record(cf, fdata)) {
3515 /* Attempt to get the packet failed. */
3519 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3520 epan_dissect_prime_with_dfilter(&edt, sfcode);
3521 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3522 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3524 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3525 epan_dissect_cleanup(&edt);
3530 cf_find_packet_marked(capture_file *cf, search_direction dir)
3532 return find_packet(cf, match_marked, NULL, dir);
3536 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3538 return fdata->marked ? MR_MATCHED : MR_NOTMATCHED;
3542 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3544 return find_packet(cf, match_time_reference, NULL, dir);
3548 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3550 return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED;
3554 find_packet(capture_file *cf,
3555 match_result (*match_function)(capture_file *, frame_data *, void *),
3556 void *criterion, search_direction dir)
3558 frame_data *start_fd;
3560 guint32 prev_framenum;
3562 frame_data *new_fd = NULL;
3563 progdlg_t *progbar = NULL;
3564 GTimer *prog_timer = g_timer_new();
3568 GTimeVal start_time;
3569 gchar status_str[100];
3571 match_result result;
3573 start_fd = cf->current_frame;
3574 if (start_fd != NULL) {
3575 prev_framenum = start_fd->num;
3577 prev_framenum = 0; /* No start packet selected. */
3580 /* Iterate through the list of packets, starting at the packet we've
3581 picked, calling a routine to run the filter on the packet, see if
3582 it matches, and stop if so. */
3584 framenum = prev_framenum;
3586 g_timer_start(prog_timer);
3587 /* Progress so far. */
3590 cf->stop_flag = FALSE;
3591 g_get_current_time(&start_time);
3593 title = cf->sfilter?cf->sfilter:"";
3595 /* Create the progress bar if necessary.
3596 We check on every iteration of the loop, so that it takes no
3597 longer than the standard time to create it (otherwise, for a
3598 large file, we might take considerably longer than that standard
3599 time in order to get to the next progress bar step). */
3600 if (progbar == NULL)
3601 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3602 FALSE, &cf->stop_flag, &start_time, progbar_val);
3605 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3606 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3607 * likely trigger UI paint events, which might take a while depending on
3608 * the platform and display. Reset our timer *after* painting.
3610 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3611 /* let's not divide by zero. I should never be started
3612 * with count == 0, so let's assert that
3614 g_assert(cf->count > 0);
3616 progbar_val = (gfloat) count / cf->count;
3618 g_snprintf(status_str, sizeof(status_str),
3619 "%4u of %u packets", count, cf->count);
3620 update_progress_dlg(progbar, progbar_val, status_str);
3622 g_timer_start(prog_timer);
3625 if (cf->stop_flag) {
3626 /* Well, the user decided to abort the search. Go back to the
3627 frame where we started. */
3632 /* Go past the current frame. */
3633 if (dir == SD_BACKWARD) {
3634 /* Go on to the previous frame. */
3635 if (framenum <= 1) {
3637 * XXX - other apps have a bit more of a detailed message
3638 * for this, and instead of offering "OK" and "Cancel",
3639 * they offer things such as "Continue" and "Cancel";
3640 * we need an API for popping up alert boxes with
3641 * {Verb} and "Cancel".
3644 if (prefs.gui_find_wrap) {
3645 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3646 framenum = cf->count; /* wrap around */
3648 statusbar_push_temporary_msg("Search reached the beginning.");
3649 framenum = prev_framenum; /* stay on previous packet */
3654 /* Go on to the next frame. */
3655 if (framenum == cf->count) {
3656 if (prefs.gui_find_wrap) {
3657 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3658 framenum = 1; /* wrap around */
3660 statusbar_push_temporary_msg("Search reached the end.");
3661 framenum = prev_framenum; /* stay on previous packet */
3667 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3670 /* Is this packet in the display? */
3671 if (fdata && fdata->passed_dfilter) {
3672 /* Yes. Does it match the search criterion? */
3673 result = (*match_function)(cf, fdata, criterion);
3674 if (result == MR_ERROR) {
3675 /* Error; our caller has reported the error. Go back to the frame
3676 where we started. */
3679 } else if (result == MR_MATCHED) {
3680 /* Yes. Go to the new frame. */
3686 if (fdata == start_fd) {
3687 /* We're back to the frame we were on originally, and that frame
3688 doesn't match the search filter. The search failed. */
3693 /* We're done scanning the packets; destroy the progress bar if it
3695 if (progbar != NULL)
3696 destroy_progress_dlg(progbar);
3697 g_timer_destroy(prog_timer);
3699 if (new_fd != NULL) {
3700 /* Find and select */
3701 cf->search_in_progress = TRUE;
3702 found = packet_list_select_row_from_data(new_fd);
3703 cf->search_in_progress = FALSE;
3704 cf->search_pos = 0; /* Reset the position */
3705 cf->search_len = 0; /* Reset length */
3707 /* We didn't find a row corresponding to this frame.
3708 This means that the frame isn't being displayed currently,
3709 so we can't select it. */
3710 simple_message_box(ESD_TYPE_INFO, NULL,
3711 "The capture file is probably not fully dissected.",
3712 "End of capture exceeded.");
3715 return TRUE; /* success */
3717 return FALSE; /* failure */
3721 cf_goto_frame(capture_file *cf, guint fnumber)
3725 if (cf == NULL || cf->provider.frames == NULL) {
3726 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3727 statusbar_push_temporary_msg("There is no file loaded");
3728 return FALSE; /* we failed to go to that packet */
3731 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3733 if (fdata == NULL) {
3734 /* we didn't find a packet with that packet number */
3735 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3736 return FALSE; /* we failed to go to that packet */
3738 if (!fdata->passed_dfilter) {
3739 /* that packet currently isn't displayed */
3740 /* XXX - add it to the set of displayed packets? */
3741 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3742 return FALSE; /* we failed to go to that packet */
3745 if (!packet_list_select_row_from_data(fdata)) {
3746 /* We didn't find a row corresponding to this frame.
3747 This means that the frame isn't being displayed currently,
3748 so we can't select it. */
3749 simple_message_box(ESD_TYPE_INFO, NULL,
3750 "The capture file is probably not fully dissected.",
3751 "End of capture exceeded.");
3754 return TRUE; /* we got to that packet */
3758 * Go to frame specified by currently selected protocol tree item.
3761 cf_goto_framenum(capture_file *cf)
3763 header_field_info *hfinfo;
3766 if (cf->finfo_selected) {
3767 hfinfo = cf->finfo_selected->hfinfo;
3769 if (hfinfo->type == FT_FRAMENUM) {
3770 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3772 return cf_goto_frame(cf, framenum);
3779 /* Select the packet on a given row. */
3781 cf_select_packet(capture_file *cf, int row)
3783 epan_dissect_t *old_edt;
3786 /* Get the frame data struct pointer for this frame */
3787 fdata = packet_list_get_row_data(row);
3789 if (fdata == NULL) {
3793 /* Get the data in that frame. */
3794 if (!cf_read_record (cf, fdata)) {
3798 /* Record that this frame is the current frame. */
3799 cf->current_frame = fdata;
3800 cf->current_row = row;
3803 /* Create the logical protocol tree. */
3804 /* We don't need the columns here. */
3805 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3807 tap_build_interesting(cf->edt);
3808 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3809 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3810 cf->current_frame, NULL);
3812 dfilter_macro_build_ftv_cache(cf->edt->tree);
3814 if (old_edt != NULL)
3815 epan_dissect_free(old_edt);
3819 /* Unselect the selected packet, if any. */
3821 cf_unselect_packet(capture_file *cf)
3823 epan_dissect_t *old_edt = cf->edt;
3827 /* No packet is selected. */
3828 cf->current_frame = NULL;
3829 cf->current_row = 0;
3831 /* Destroy the epan_dissect_t for the unselected packet. */
3832 if (old_edt != NULL)
3833 epan_dissect_free(old_edt);
3837 * Mark a particular frame.
3840 cf_mark_frame(capture_file *cf, frame_data *frame)
3842 if (! frame->marked) {
3843 frame->marked = TRUE;
3844 if (cf->count > cf->marked_count)
3850 * Unmark a particular frame.
3853 cf_unmark_frame(capture_file *cf, frame_data *frame)
3855 if (frame->marked) {
3856 frame->marked = FALSE;
3857 if (cf->marked_count > 0)
3863 * Ignore a particular frame.
3866 cf_ignore_frame(capture_file *cf, frame_data *frame)
3868 if (! frame->ignored) {
3869 frame->ignored = TRUE;
3870 if (cf->count > cf->ignored_count)
3871 cf->ignored_count++;
3876 * Un-ignore a particular frame.
3879 cf_unignore_frame(capture_file *cf, frame_data *frame)
3881 if (frame->ignored) {
3882 frame->ignored = FALSE;
3883 if (cf->ignored_count > 0)
3884 cf->ignored_count--;
3889 * Read the section comment.
3892 cf_read_section_comment(capture_file *cf)
3894 wtap_block_t shb_inf;
3898 /* XXX - support multiple SHBs */
3899 shb_inf = wtap_file_get_shb(cf->provider.wth);
3901 /* Get the first comment from the SHB. */
3902 /* XXX - support multiple comments */
3903 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3909 * Modify the section comment.
3912 cf_update_section_comment(capture_file *cf, gchar *comment)
3914 wtap_block_t shb_inf;
3918 /* XXX - support multiple SHBs */
3919 shb_inf = wtap_file_get_shb(cf->provider.wth);
3921 /* Get the first comment from the SHB. */
3922 /* XXX - support multiple comments */
3923 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3924 /* There's no comment - add one. */
3925 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3927 /* See if the comment has changed or not */
3928 if (strcmp(shb_comment, comment) == 0) {
3933 /* The comment has changed, let's update it */
3934 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3936 /* Mark the file as having unsaved changes */
3937 cf->unsaved_changes = TRUE;
3941 * Get the comment on a packet (record).
3942 * If the comment has been edited, it returns the result of the edit,
3943 * otherwise it returns the comment from the file.
3946 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3950 /* fetch user comment */
3951 if (fd->has_user_comment)
3952 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3954 /* fetch phdr comment */
3955 if (fd->has_phdr_comment) {
3956 wtap_rec rec; /* Record metadata */
3957 Buffer buf; /* Record data */
3959 wtap_rec_init(&rec);
3960 ws_buffer_init(&buf, 1500);
3962 if (!cf_read_record_r(cf, fd, &rec, &buf))
3963 { /* XXX, what we can do here? */ }
3965 comment = rec.opt_comment;
3966 wtap_rec_cleanup(&rec);
3967 ws_buffer_free(&buf);
3974 * Update(replace) the comment on a capture from a frame
3977 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3979 char *pkt_comment = cf_get_packet_comment(cf, fd);
3981 /* Check if the comment has changed */
3982 if (!g_strcmp0(pkt_comment, new_comment)) {
3983 g_free(pkt_comment);
3986 g_free(pkt_comment);
3989 cf->packet_comment_count--;
3992 cf->packet_comment_count++;
3994 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3996 expert_update_comment_count(cf->packet_comment_count);
3998 /* OK, we have unsaved changes. */
3999 cf->unsaved_changes = TRUE;
4004 * What types of comments does this capture file have?
4007 cf_comment_types(capture_file *cf)
4009 guint32 comment_types = 0;
4011 if (cf_read_section_comment(cf) != NULL)
4012 comment_types |= WTAP_COMMENT_PER_SECTION;
4013 if (cf->packet_comment_count != 0)
4014 comment_types |= WTAP_COMMENT_PER_PACKET;
4015 return comment_types;
4019 * Add a resolved address to this file's list of resolved addresses.
4022 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
4025 * XXX - support multiple resolved address lists, and add to the one
4026 * attached to this file?
4028 if (!add_ip_name_from_string(addr, name))
4031 /* OK, we have unsaved changes. */
4032 cf->unsaved_changes = TRUE;
4040 } save_callback_args_t;
4043 * Save a capture to a file, in a particular format, saving either
4044 * all packets, all currently-displayed packets, or all marked packets.
4046 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4047 * up a message box for the failure.
4050 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
4051 const guint8 *pd, void *argsp)
4053 save_callback_args_t *args = (save_callback_args_t *)argsp;
4057 const char *pkt_comment;
4059 /* Copy the record information from what was read in from the file. */
4062 /* Make changes based on anything that the user has done but that
4063 hasn't been saved yet. */
4064 if (fdata->has_user_comment)
4065 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
4067 pkt_comment = rec->opt_comment;
4068 new_rec.opt_comment = g_strdup(pkt_comment);
4069 new_rec.has_comment_changed = fdata->has_user_comment ? TRUE : FALSE;
4070 /* XXX - what if times have been shifted? */
4072 /* and save the packet */
4073 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
4074 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4079 g_free(new_rec.opt_comment);
4084 * Can this capture file be written out in any format using Wiretap
4085 * rather than by copying the raw data?
4088 cf_can_write_with_wiretap(capture_file *cf)
4090 /* We don't care whether we support the comments in this file or not;
4091 if we can't, we'll offer the user the option of discarding the
4093 return wtap_dump_can_write(cf->linktypes, 0);
4097 * Should we let the user do a save?
4101 * the file has unsaved changes, and we can save it in some
4102 * format through Wiretap
4106 * the file is a temporary file and has no unsaved changes (so
4107 * that "saving" it just means copying it).
4109 * XXX - we shouldn't allow files to be edited if they can't be saved,
4110 * so cf->unsaved_changes should be true only if the file can be saved.
4112 * We don't care whether we support the comments in this file or not;
4113 * if we can't, we'll offer the user the option of discarding the
4117 cf_can_save(capture_file *cf)
4119 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4120 /* Saved changes, and we can write it out with Wiretap. */
4124 if (cf->is_tempfile && !cf->unsaved_changes) {
4126 * Temporary file with no unsaved changes, so we can just do a
4132 /* Nothing to save. */
4137 * Should we let the user do a "save as"?
4141 * we can save it in some format through Wiretap
4145 * the file is a temporary file and has no unsaved changes (so
4146 * that "saving" it just means copying it).
4148 * XXX - we shouldn't allow files to be edited if they can't be saved,
4149 * so cf->unsaved_changes should be true only if the file can be saved.
4151 * We don't care whether we support the comments in this file or not;
4152 * if we can't, we'll offer the user the option of discarding the
4156 cf_can_save_as(capture_file *cf)
4158 if (wtap_dump_can_write(cf->linktypes, 0)) {
4159 /* We can write it out with Wiretap. */
4163 if (cf->is_tempfile && !cf->unsaved_changes) {
4165 * Temporary file with no unsaved changes, so we can just do a
4171 /* Nothing to save. */
4176 * Does this file have unsaved data?
4179 cf_has_unsaved_data(capture_file *cf)
4182 * If this is a temporary file, or a file with unsaved changes, it
4185 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4189 * Quick scan to find packet offsets.
4191 static cf_read_status_t
4192 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4194 const wtap_rec *rec;
4199 progdlg_t *progbar = NULL;
4200 GTimer *prog_timer = g_timer_new();
4203 GTimeVal start_time;
4204 gchar status_str[100];
4209 /* Close the old handle. */
4210 wtap_close(cf->provider.wth);
4212 /* Open the new file. */
4213 /* XXX: this will go through all open_routines for a matching one. But right
4214 now rescan_file() is only used when a file is being saved to a different
4215 format than the original, and the user is not given a choice of which
4216 reader to use (only which format to save it in), so doing this makes
4218 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4219 if (cf->provider.wth == NULL) {
4220 cfile_open_failure_alert_box(fname, err, err_info);
4221 return CF_READ_ERROR;
4224 /* We're scanning a file whose contents should be the same as what
4225 we had before, so we don't discard dissection state etc.. */
4228 /* Set the file name because we need it to set the follow stream filter.
4229 XXX - is that still true? We need it for other reasons, though,
4231 cf->filename = g_strdup(fname);
4233 /* Indicate whether it's a permanent or temporary file. */
4234 cf->is_tempfile = is_tempfile;
4236 /* No user changes yet. */
4237 cf->unsaved_changes = FALSE;
4239 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4240 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4242 cf->snap = wtap_snapshot_length(cf->provider.wth);
4244 name_ptr = g_filename_display_basename(cf->filename);
4246 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4248 /* Record the file's compression type.
4249 XXX - do we know this at open time? */
4250 cf->compression_type = wtap_get_compression_type(cf->provider.wth);
4252 /* Find the size of the file. */
4253 size = wtap_file_size(cf->provider.wth, NULL);
4255 g_timer_start(prog_timer);
4257 cf->stop_flag = FALSE;
4258 g_get_current_time(&start_time);
4261 rec = wtap_get_rec(cf->provider.wth);
4262 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4264 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4265 fdata->file_off = data_offset;
4268 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4270 /* Create the progress bar if necessary. */
4271 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4272 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4273 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4274 TRUE, &cf->stop_flag, &start_time, progbar_val);
4278 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4279 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4280 * likely trigger UI paint events, which might take a while depending on
4281 * the platform and display. Reset our timer *after* painting.
4283 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4284 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4285 /* update the packet bar content on the first run or frequently on very large files */
4286 update_progress_dlg(progbar, progbar_val, status_str);
4287 compute_elapsed(cf, &start_time);
4288 packets_bar_update();
4289 g_timer_start(prog_timer);
4293 if (cf->stop_flag) {
4294 /* Well, the user decided to abort the rescan. Sadly, as this
4295 isn't a reread, recovering is difficult, so we'll just
4296 close the current capture. */
4300 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4301 it's not already there.
4302 XXX - yes, this is O(N), so if every packet had a different
4303 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4304 there are probably going to be a small number of encapsulation types
4306 if (rec->rec_type == REC_TYPE_PACKET) {
4307 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4311 /* Free the display name */
4314 /* We're done reading the file; destroy the progress bar if it was created. */
4315 if (progbar != NULL)
4316 destroy_progress_dlg(progbar);
4317 g_timer_destroy(prog_timer);
4319 /* We're done reading sequentially through the file. */
4320 cf->state = FILE_READ_DONE;
4322 /* Close the sequential I/O side, to free up memory it requires. */
4323 wtap_sequential_close(cf->provider.wth);
4325 /* compute the time it took to load the file */
4326 compute_elapsed(cf, &start_time);
4328 /* Set the file encapsulation type now; we don't know what it is until
4329 we've looked at all the packets, as we don't know until then whether
4330 there's more than one type (and thus whether it's
4331 WTAP_ENCAP_PER_PACKET). */
4332 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4334 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4336 if (cf->stop_flag) {
4337 /* Our caller will give up at this point. */
4338 return CF_READ_ABORTED;
4342 /* Put up a message box noting that the read failed somewhere along
4343 the line. Don't throw out the stuff we managed to read, though,
4345 cfile_read_failure_alert_box(NULL, err, err_info);
4346 return CF_READ_ERROR;
4352 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4353 wtap_compression_type compression_type,
4354 gboolean discard_comments, gboolean dont_reopen)
4357 gchar *fname_new = NULL;
4360 addrinfo_lists_t *addr_lists;
4364 gchar *display_basename;
4371 save_callback_args_t callback_args;
4372 gboolean needs_reload = FALSE;
4374 /* XXX caller should avoid saving the file while a read is pending
4375 * (e.g. by delaying the save action) */
4376 if (cf->read_lock) {
4377 g_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname);
4380 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4382 addr_lists = get_addrinfo_list();
4384 if (save_format == cf->cd_t && compression_type == cf->compression_type
4385 && !discard_comments && !cf->unsaved_changes
4386 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4387 /* We're saving in the format it's already in, and we're not discarding
4388 comments, and there are no changes we have in memory that aren't saved
4389 to the file, and we have no name resolution information to write or
4390 the file format we're saving in doesn't support writing name
4391 resolution information, so we can just move or copy the raw data. */
4393 if (cf->is_tempfile) {
4394 /* The file being saved is a temporary file from a live
4395 capture, so it doesn't need to stay around under that name;
4396 first, try renaming the capture buffer file to the new name.
4397 This acts as a "safe save", in that, if the file already
4398 exists, the existing file will be removed only if the rename
4401 Sadly, on Windows, as we have the current capture file
4402 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4403 (to cause the rename to remove an existing target), as
4404 done by ws_stdio_rename() (ws_rename() is #defined to
4405 be ws_stdio_rename() on Windows) will fail.
4407 According to the MSDN documentation for CreateFile(), if,
4408 when we open a capture file, we were to directly do a CreateFile(),
4409 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4410 convert it to a file descriptor with _open_osfhandle(),
4411 that would allow the file to be renamed out from under us.
4413 However, that doesn't work in practice. Perhaps the problem
4414 is that the process doing the rename is the process that
4415 has the file open. */
4417 if (ws_rename(cf->filename, fname) == 0) {
4418 /* That succeeded - there's no need to copy the source file. */
4419 how_to_save = SAVE_WITH_MOVE;
4421 if (errno == EXDEV) {
4422 /* They're on different file systems, so we have to copy the
4424 how_to_save = SAVE_WITH_COPY;
4426 /* The rename failed, but not because they're on different
4427 file systems - put up an error message. (Or should we
4428 just punt and try to copy? The only reason why I'd
4429 expect the rename to fail and the copy to succeed would
4430 be if we didn't have permission to remove the file from
4431 the temporary directory, and that might be fixable - but
4432 is it worth requiring the user to go off and fix it?) */
4433 cf_rename_failure_alert_box(fname, errno);
4438 /* Windows - copy the file to its new location. */
4439 how_to_save = SAVE_WITH_COPY;
4442 /* It's a permanent file, so we should copy it, and not remove the
4444 how_to_save = SAVE_WITH_COPY;
4447 if (how_to_save == SAVE_WITH_COPY) {
4448 /* Copy the file, if we haven't moved it. If we're overwriting
4449 an existing file, we do it with a "safe save", by writing
4450 to a new file and, if the write succeeds, renaming the
4451 new file on top of the old file. */
4452 if (file_exists(fname)) {
4453 fname_new = g_strdup_printf("%s~", fname);
4454 if (!copy_file_binary_mode(cf->filename, fname_new))
4457 if (!copy_file_binary_mode(cf->filename, fname))
4462 /* Either we're saving in a different format or we're saving changes,
4463 such as added, modified, or removed comments, that haven't yet
4464 been written to the underlying file; we can't do that by copying
4465 or moving the capture file, we have to do it by writing the packets
4468 wtap_dump_params params;
4471 /* XXX: what free's params.shb_hdr? */
4472 wtap_dump_params_init(¶ms, cf->provider.wth);
4474 /* Determine what file encapsulation type we should use. */
4475 encap = wtap_dump_file_encap_type(cf->linktypes);
4476 params.encap = encap;
4478 /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */
4479 params.snaplen = cf->snap;
4481 if (file_exists(fname)) {
4482 /* We're overwriting an existing file; write out to a new file,
4483 and, if that succeeds, rename the new file on top of the
4484 old file. That makes this a "safe save", so that we don't
4485 lose the old file if we have a problem writing out the new
4486 file. (If the existing file is the current capture file,
4487 we *HAVE* to do that, otherwise we're overwriting the file
4488 from which we're reading the packets that we're writing!) */
4489 fname_new = g_strdup_printf("%s~", fname);
4490 pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms,
4493 pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, &err);
4495 /* XXX idb_inf is documented to be used until wtap_dump_close. */
4496 g_free(params.idb_inf);
4497 params.idb_inf = NULL;
4500 cfile_dump_open_failure_alert_box(fname, err, save_format);
4504 /* Add address resolution */
4505 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4507 /* Iterate through the list of packets, processing all the packets. */
4508 callback_args.pdh = pdh;
4509 callback_args.fname = fname;
4510 callback_args.file_type = save_format;
4511 switch (process_specified_records(cf, NULL, "Saving", "packets",
4512 TRUE, save_record, &callback_args, TRUE)) {
4515 /* Completed successfully. */
4519 /* The user decided to abort the saving.
4520 If we're writing to a temporary file, remove it.
4521 XXX - should we do so even if we're not writing to a
4523 wtap_dump_close(pdh, &err);
4524 if (fname_new != NULL)
4525 ws_unlink(fname_new);
4526 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4527 return CF_WRITE_ABORTED;
4530 /* Error while saving.
4531 If we're writing to a temporary file, remove it. */
4532 if (fname_new != NULL)
4533 ws_unlink(fname_new);
4534 wtap_dump_close(pdh, &err);
4538 needs_reload = wtap_dump_get_needs_reload(pdh);
4540 if (!wtap_dump_close(pdh, &err)) {
4541 cfile_close_failure_alert_box(fname, err);
4545 how_to_save = SAVE_WITH_WTAP;
4548 if (fname_new != NULL) {
4549 /* We wrote out to fname_new, and should rename it on top of
4550 fname. fname_new is now closed, so that should be possible even
4551 on Windows. However, on Windows, we first need to close whatever
4552 file descriptors we have open for fname. */
4554 wtap_fdclose(cf->provider.wth);
4556 /* Now do the rename. */
4557 if (ws_rename(fname_new, fname) == -1) {
4558 /* Well, the rename failed. */
4559 cf_rename_failure_alert_box(fname, errno);
4561 /* Attempt to reopen the random file descriptor using the
4562 current file's filename. (At this point, the sequential
4563 file descriptor is closed.) */
4564 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4565 /* Oh, well, we're screwed. */
4566 display_basename = g_filename_display_basename(cf->filename);
4567 simple_error_message_box(
4568 file_open_error_message(err, FALSE), display_basename);
4569 g_free(display_basename);
4576 /* If this was a temporary file, and we didn't do the save by doing
4577 a move, so the tempoary file is still around under its old name,
4579 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4580 /* If this fails, there's not much we can do, so just ignore errors. */
4581 ws_unlink(cf->filename);
4584 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4585 cf->unsaved_changes = FALSE;
4588 switch (how_to_save) {
4590 case SAVE_WITH_MOVE:
4591 /* We just moved the file, so the wtap structure refers to the
4592 new file, and all the information other than the filename
4593 and the "is temporary" status applies to the new file; just
4595 g_free(cf->filename);
4596 cf->filename = g_strdup(fname);
4597 cf->is_tempfile = FALSE;
4598 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4601 case SAVE_WITH_COPY:
4602 /* We just copied the file, so all the information other than
4603 the wtap structure, the filename, and the "is temporary"
4604 status applies to the new file; just update that. */
4605 wtap_close(cf->provider.wth);
4606 /* Although we're just "copying" and then opening the copy, it will
4607 try all open_routine readers to open the copy, so we need to
4608 reset the cfile's open_type. */
4609 cf->open_type = WTAP_TYPE_AUTO;
4610 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4611 if (cf->provider.wth == NULL) {
4612 cfile_open_failure_alert_box(fname, err, err_info);
4615 g_free(cf->filename);
4616 cf->filename = g_strdup(fname);
4617 cf->is_tempfile = FALSE;
4619 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4622 case SAVE_WITH_WTAP:
4623 /* Open and read the file we saved to.
4625 XXX - this is somewhat of a waste; we already have the
4626 packets, all this gets us is updated file type information
4627 (which we could just stuff into "cf"), and having the new
4628 file be the one we have opened and from which we're reading
4629 the data, and it means we have to spend time opening and
4630 reading the file, which could be a significant amount of
4631 time if the file is large.
4633 If the capture-file-writing code were to return the
4634 seek offset of each packet it writes, we could save that
4635 in the frame_data structure for the frame, and just open
4636 the file without reading it again...
4638 ...as long as, for gzipped files, the process of writing
4639 out the file *also* generates the information needed to
4640 support fast random access to the compressed file. */
4641 /* rescan_file will cause us to try all open_routines, so
4642 reset cfile's open_type */
4643 cf->open_type = WTAP_TYPE_AUTO;
4644 /* There are cases when SAVE_WITH_WTAP can result in new packets
4645 being written to the file, e.g ERF records
4646 In that case, we need to reload the whole file */
4648 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4649 if (cf_read(cf, TRUE) != CF_READ_OK) {
4650 /* The rescan failed; just close the file. Either
4651 a dialog was popped up for the failure, so the
4652 user knows what happened, or they stopped the
4653 rescan, in which case they know what happened. */
4654 /* XXX: This is inconsistent with normal open/reload behaviour. */
4660 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4661 /* The rescan failed; just close the file. Either
4662 a dialog was popped up for the failure, so the
4663 user knows what happened, or they stopped the
4664 rescan, in which case they know what happened. */
4671 /* If we were told to discard the comments, do so. */
4672 if (discard_comments) {
4673 /* Remove SHB comment, if any. */
4674 wtap_write_shb_comment(cf->provider.wth, NULL);
4676 /* remove all user comments */
4677 for (framenum = 1; framenum <= cf->count; framenum++) {
4678 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4680 fdata->has_phdr_comment = FALSE;
4681 fdata->has_user_comment = FALSE;
4684 if (cf->provider.frames_user_comments) {
4685 g_tree_destroy(cf->provider.frames_user_comments);
4686 cf->provider.frames_user_comments = NULL;
4689 cf->packet_comment_count = 0;
4695 if (fname_new != NULL) {
4696 /* We were trying to write to a temporary file; get rid of it if it
4697 exists. (We don't care whether this fails, as, if it fails,
4698 there's not much we can do about it. I guess if it failed for
4699 a reason other than "it doesn't exist", we could report an
4700 error, so the user knows there's a junk file that they might
4701 want to clean up.) */
4702 ws_unlink(fname_new);
4705 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4706 return CF_WRITE_ERROR;
4710 cf_export_specified_packets(capture_file *cf, const char *fname,
4711 packet_range_t *range, guint save_format,
4712 wtap_compression_type compression_type)
4714 gchar *fname_new = NULL;
4717 save_callback_args_t callback_args;
4718 wtap_dump_params params;
4721 packet_range_process_init(range);
4723 /* We're writing out specified packets from the specified capture
4724 file to another file. Even if all captured packets are to be
4725 written, don't special-case the operation - read each packet
4726 and then write it out if it's one of the specified ones. */
4728 /* XXX: what free's params.shb_hdr? */
4729 wtap_dump_params_init(¶ms, cf->provider.wth);
4731 /* Determine what file encapsulation type we should use. */
4732 encap = wtap_dump_file_encap_type(cf->linktypes);
4733 params.encap = encap;
4735 /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */
4736 params.snaplen = cf->snap;
4738 if (file_exists(fname)) {
4739 /* We're overwriting an existing file; write out to a new file,
4740 and, if that succeeds, rename the new file on top of the
4741 old file. That makes this a "safe save", so that we don't
4742 lose the old file if we have a problem writing out the new
4743 file. (If the existing file is the current capture file,
4744 we *HAVE* to do that, otherwise we're overwriting the file
4745 from which we're reading the packets that we're writing!) */
4746 fname_new = g_strdup_printf("%s~", fname);
4747 pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms,
4750 pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, &err);
4752 /* XXX idb_inf is documented to be used until wtap_dump_close. */
4753 g_free(params.idb_inf);
4754 params.idb_inf = NULL;
4757 cfile_dump_open_failure_alert_box(fname, err, save_format);
4761 /* Add address resolution */
4762 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4764 /* Iterate through the list of packets, processing the packets we were
4767 XXX - we've already called "packet_range_process_init(range)", but
4768 "process_specified_records()" will do it again. Fortunately,
4769 that's harmless in this case, as we haven't done anything to
4770 "range" since we initialized it. */
4771 callback_args.pdh = pdh;
4772 callback_args.fname = fname;
4773 callback_args.file_type = save_format;
4774 switch (process_specified_records(cf, range, "Writing", "specified records",
4775 TRUE, save_record, &callback_args, TRUE)) {
4778 /* Completed successfully. */
4782 /* The user decided to abort the saving.
4783 If we're writing to a temporary file, remove it.
4784 XXX - should we do so even if we're not writing to a
4786 wtap_dump_close(pdh, &err);
4787 if (fname_new != NULL)
4788 ws_unlink(fname_new);
4789 return CF_WRITE_ABORTED;
4793 /* Error while saving.
4794 If we're writing to a temporary file, remove it. */
4795 if (fname_new != NULL)
4796 ws_unlink(fname_new);
4797 wtap_dump_close(pdh, &err);
4801 if (!wtap_dump_close(pdh, &err)) {
4802 cfile_close_failure_alert_box(fname, err);
4806 if (fname_new != NULL) {
4807 /* We wrote out to fname_new, and should rename it on top of
4808 fname; fname is now closed, so that should be possible even
4809 on Windows. Do the rename. */
4810 if (ws_rename(fname_new, fname) == -1) {
4811 /* Well, the rename failed. */
4812 cf_rename_failure_alert_box(fname, errno);
4820 if (fname_new != NULL) {
4821 /* We were trying to write to a temporary file; get rid of it if it
4822 exists. (We don't care whether this fails, as, if it fails,
4823 there's not much we can do about it. I guess if it failed for
4824 a reason other than "it doesn't exist", we could report an
4825 error, so the user knows there's a junk file that they might
4826 want to clean up.) */
4827 ws_unlink(fname_new);
4830 return CF_WRITE_ERROR;
4834 * XXX - whether we mention the source pathname, the target pathname,
4835 * or both depends on the error and on what we find if we look for
4836 * one or both of them.
4839 cf_rename_failure_alert_box(const char *filename, int err)
4841 gchar *display_basename;
4843 display_basename = g_filename_display_basename(filename);
4847 /* XXX - should check whether the source exists and, if not,
4848 report it as the problem and, if so, report the destination
4850 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4855 /* XXX - if we're doing a rename after a safe save, we should
4856 probably say something else. */
4857 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4862 /* XXX - this should probably mention both the source and destination
4864 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4865 display_basename, wtap_strerror(err));
4868 g_free(display_basename);
4871 /* Reload the current capture file. */
4873 cf_reload(capture_file *cf) {
4875 gboolean is_tempfile;
4878 if (cf->read_lock) {
4879 g_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename);
4883 /* If the file could be opened, "cf_open()" calls "cf_close()"
4884 to get rid of state for the old capture file before filling in state
4885 for the new capture file. "cf_close()" will remove the file if
4886 it's a temporary file; we don't want that to happen (for one thing,
4887 it'd prevent subsequent reopens from working). Remember whether it's
4888 a temporary file, mark it as not being a temporary file, and then
4889 reopen it as the type of file it was.
4891 Also, "cf_close()" will free "cf->filename", so we must make
4892 a copy of it first. */
4893 filename = g_strdup(cf->filename);
4894 is_tempfile = cf->is_tempfile;
4895 cf->is_tempfile = FALSE;
4896 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4897 switch (cf_read(cf, TRUE)) {
4901 /* Just because we got an error, that doesn't mean we were unable
4902 to read any of the file; we handle what we could get from the
4906 case CF_READ_ABORTED:
4907 /* The user bailed out of re-reading the capture file; the
4908 capture file has been closed - just free the capture file name
4909 string and return (without changing the last containing
4915 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4916 Instead, the file was left open, so we should restore "cf->is_tempfile"
4919 XXX - change the menu? Presumably "cf_open()" will do that;
4920 make sure it does! */
4921 cf->is_tempfile = is_tempfile;
4923 /* "cf_open()" made a copy of the file name we handed it, so
4924 we should free up our copy. */
4934 * indent-tabs-mode: nil
4937 * ex: set shiftwidth=2 tabstop=8 expandtab:
4938 * :indentSize=2:tabSize=8:noTabs=true: