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);
1743 for (framenum = 1; framenum <= frames_count; framenum++) {
1744 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1746 /* Create the progress bar if necessary.
1747 We check on every iteration of the loop, so that it takes no
1748 longer than the standard time to create it (otherwise, for a
1749 large file, we might take considerably longer than that standard
1750 time in order to get to the next progress bar step). */
1751 if (progbar == NULL)
1752 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1758 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1759 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1760 * likely trigger UI paint events, which might take a while depending on
1761 * the platform and display. Reset our timer *after* painting.
1763 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1764 /* let's not divide by zero. I should never be started
1765 * with count == 0, so let's assert that
1767 g_assert(cf->count > 0);
1768 progbar_val = (gfloat) count / frames_count;
1770 if (progbar != NULL) {
1771 g_snprintf(status_str, sizeof(status_str),
1772 "%4u of %u frames", count, frames_count);
1773 update_progress_dlg(progbar, progbar_val, status_str);
1776 g_timer_start(prog_timer);
1779 queued_rescan_type = cf->redissection_queued;
1780 if (queued_rescan_type != RESCAN_NONE) {
1781 /* A redissection was requested while an existing redissection was
1786 if (cf->stop_flag) {
1787 /* Well, the user decided to abort the filtering. Just stop.
1789 XXX - go back to the previous filter? Users probably just
1790 want not to wait for a filtering operation to finish;
1791 unless we cancel by having no filter, reverting to the
1792 previous filter will probably be even more expensive than
1793 continuing the filtering, as it involves going back to the
1794 beginning and filtering, and even with no filter we currently
1795 have to re-generate the entire clist, which is also expensive.
1797 I'm not sure what Network Monitor does, but it doesn't appear
1798 to give you an unfiltered display if you cancel. */
1805 /* Since all state for the frame was destroyed, mark the frame
1806 * as not visited, free the GSList referring to the state
1807 * data (the per-frame data itself was freed by
1808 * "init_dissection()"), and null out the GSList pointer. */
1809 frame_data_reset(fdata);
1810 frames_count = cf->count;
1813 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1814 fdata->dependent_of_displayed = 0;
1816 if (!cf_read_record(cf, fdata))
1817 break; /* error reading the frame */
1819 /* If the previous frame is displayed, and we haven't yet seen the
1820 selected frame, remember that frame - it's the closest one we've
1821 yet seen before the selected frame. */
1822 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->passed_dfilter) {
1823 preceding_frame_num = prev_frame_num;
1824 preceding_frame = prev_frame;
1827 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1829 ws_buffer_start_ptr(&cf->buf),
1830 add_to_packet_list);
1832 /* If this frame is displayed, and this is the first frame we've
1833 seen displayed after the selected frame, remember this frame -
1834 it's the closest one we've yet seen at or after the selected
1836 if (fdata->passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1837 following_frame_num = fdata->num;
1838 following_frame = fdata;
1840 if (fdata == selected_frame) {
1841 selected_frame_seen = TRUE;
1842 if (fdata->passed_dfilter)
1843 selected_frame_num = fdata->num;
1846 /* Remember this frame - it'll be the previous frame
1847 on the next pass through the loop. */
1848 prev_frame_num = fdata->num;
1852 epan_dissect_cleanup(&edt);
1854 /* We are done redissecting the packet list. */
1855 cf->redissecting = FALSE;
1858 frames_count = cf->count;
1859 /* Clear out what remains of the visited flags and per-frame data
1862 XXX - that may cause various forms of bogosity when dissecting
1863 these frames, as they won't have been seen by this sequential
1864 pass, but the only alternative I see is to keep scanning them
1865 even though the user requested that the scan stop, and that
1866 would leave the user stuck with an Wireshark grinding on
1867 until it finishes. Should we just stick them with that? */
1868 for (; framenum <= frames_count; framenum++) {
1869 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1870 frame_data_reset(fdata);
1874 /* We're done filtering the packets; destroy the progress bar if it
1876 if (progbar != NULL)
1877 destroy_progress_dlg(progbar);
1878 g_timer_destroy(prog_timer);
1880 /* Unfreeze the packet list. */
1881 if (!add_to_packet_list)
1882 packet_list_recreate_visible_rows();
1884 /* Compute the time it took to filter the file */
1885 compute_elapsed(cf, &start_time);
1889 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1891 if (selected_frame_num == -1) {
1892 /* The selected frame didn't pass the filter. */
1893 if (selected_frame == NULL) {
1894 /* That's because there *was* no selected frame. Make the first
1895 displayed frame the current frame. */
1896 selected_frame_num = 0;
1898 /* Find the nearest displayed frame to the selected frame (whether
1899 it's before or after that frame) and make that the current frame.
1900 If the next and previous displayed frames are equidistant from the
1901 selected frame, choose the next one. */
1902 g_assert(following_frame == NULL ||
1903 following_frame->num >= selected_frame->num);
1904 g_assert(preceding_frame == NULL ||
1905 preceding_frame->num <= selected_frame->num);
1906 if (following_frame == NULL) {
1907 /* No frame after the selected frame passed the filter, so we
1908 have to select the last displayed frame before the selected
1910 selected_frame_num = preceding_frame_num;
1911 selected_frame = preceding_frame;
1912 } else if (preceding_frame == NULL) {
1913 /* No frame before the selected frame passed the filter, so we
1914 have to select the first displayed frame after the selected
1916 selected_frame_num = following_frame_num;
1917 selected_frame = following_frame;
1919 /* Frames before and after the selected frame passed the filter, so
1920 we'll select the previous frame */
1921 selected_frame_num = preceding_frame_num;
1922 selected_frame = preceding_frame;
1927 if (selected_frame_num == -1) {
1928 /* There are no frames displayed at all. */
1929 cf_unselect_packet(cf);
1931 /* Either the frame that was selected passed the filter, or we've
1932 found the nearest displayed frame to that frame. Select it, make
1933 it the focus row, and make it visible. */
1934 /* Set to invalid to force update of packet list and packet details */
1935 cf->current_row = -1;
1936 if (selected_frame_num == 0) {
1937 packet_list_select_first_row();
1939 if (!packet_list_select_row_from_data(selected_frame)) {
1940 /* We didn't find a row corresponding to this frame.
1941 This means that the frame isn't being displayed currently,
1942 so we can't select it. */
1943 simple_message_box(ESD_TYPE_INFO, NULL,
1944 "The capture file is probably not fully dissected.",
1945 "End of capture exceeded.");
1950 /* Cleanup and release all dfilter resources */
1951 dfilter_free(dfcode);
1953 /* It is safe again to execute redissections. */
1954 g_assert(cf->read_lock);
1955 cf->read_lock = FALSE;
1957 /* If another rescan (due to dfilter change) or redissection (due to profile
1958 * change) was requested, the rescan above is aborted and restarted here. */
1959 if (queued_rescan_type != RESCAN_NONE) {
1960 redissect = redissect || queued_rescan_type == RESCAN_REDISSECT;
1961 rescan_packets(cf, "Reprocessing", "all packets", redissect);
1967 * Scan through all frame data and recalculate the ref time
1968 * without rereading the file.
1969 * XXX - do we need a progres bar or is this fast enough?
1972 ref_time_packets(capture_file *cf)
1978 cf->provider.ref = NULL;
1979 cf->provider.prev_dis = NULL;
1982 for (framenum = 1; framenum <= cf->count; framenum++) {
1983 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
1985 /* just add some value here until we know if it is being displayed or not */
1986 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1992 /* If we don't have the time stamp of the first packet in the
1993 capture, it's because this is the first packet. Save the time
1994 stamp of this packet as the time stamp of the first packet. */
1995 if (cf->provider.ref == NULL)
1996 cf->provider.ref = fdata;
1997 /* if this frames is marked as a reference time frame, reset
1998 firstsec and firstusec to this frame */
1999 if (fdata->ref_time)
2000 cf->provider.ref = fdata;
2002 /* If we don't have the time stamp of the previous displayed packet,
2003 it's because this is the first displayed packet. Save the time
2004 stamp of this packet as the time stamp of the previous displayed
2006 if (cf->provider.prev_dis == NULL) {
2007 cf->provider.prev_dis = fdata;
2010 /* Get the time elapsed between the first packet and this packet. */
2011 fdata->frame_ref_num = (fdata != cf->provider.ref) ? cf->provider.ref->num : 0;
2012 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->provider.ref->abs_ts);
2014 /* If it's greater than the current elapsed time, set the elapsed time
2015 to it (we check for "greater than" so as not to be confused by
2016 time moving backwards). */
2017 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2018 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2019 cf->elapsed_time = rel_ts;
2022 /* If this frame is displayed, get the time elapsed between the
2023 previous displayed packet and this packet. */
2024 if ( fdata->passed_dfilter ) {
2025 fdata->prev_dis_num = cf->provider.prev_dis->num;
2026 cf->provider.prev_dis = fdata;
2032 if ( (fdata->passed_dfilter) || (fdata->ref_time) ) {
2033 /* This frame either passed the display filter list or is marked as
2034 a time reference frame. All time reference frames are displayed
2035 even if they don't pass the display filter */
2036 if (fdata->ref_time) {
2037 /* if this was a TIME REF frame we should reset the cum_bytes field */
2038 cf->cum_bytes = fdata->pkt_len;
2039 fdata->cum_bytes = cf->cum_bytes;
2041 /* increase cum_bytes with this packets length */
2042 cf->cum_bytes += fdata->pkt_len;
2055 process_specified_records(capture_file *cf, packet_range_t *range,
2056 const char *string1, const char *string2, gboolean terminate_is_stop,
2057 gboolean (*callback)(capture_file *, frame_data *,
2058 wtap_rec *, const guint8 *, void *),
2059 void *callback_args,
2060 gboolean show_progress_bar)
2066 psp_return_t ret = PSP_FINISHED;
2068 progdlg_t *progbar = NULL;
2069 GTimer *prog_timer = g_timer_new();
2072 GTimeVal progbar_start_time;
2073 gchar progbar_status_str[100];
2074 range_process_e process_this;
2076 wtap_rec_init(&rec);
2077 ws_buffer_init(&buf, 1500);
2079 g_timer_start(prog_timer);
2080 /* Count of packets at which we've looked. */
2082 /* Progress so far. */
2085 if (cf->read_lock) {
2086 g_warning("Failing due to nested process_specified_records(\"%s\") call!", cf->filename);
2089 cf->read_lock = TRUE;
2091 cf->stop_flag = FALSE;
2092 g_get_current_time(&progbar_start_time);
2095 packet_range_process_init(range);
2097 /* Iterate through all the packets, printing the packets that
2098 were selected by the current display filter. */
2099 for (framenum = 1; framenum <= cf->count; framenum++) {
2100 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
2102 /* Create the progress bar if necessary.
2103 We check on every iteration of the loop, so that it takes no
2104 longer than the standard time to create it (otherwise, for a
2105 large file, we might take considerably longer than that standard
2106 time in order to get to the next progress bar step). */
2107 if (show_progress_bar && progbar == NULL)
2108 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2111 &progbar_start_time,
2115 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2116 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2117 * likely trigger UI paint events, which might take a while depending on
2118 * the platform and display. Reset our timer *after* painting.
2120 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2121 /* let's not divide by zero. I should never be started
2122 * with count == 0, so let's assert that
2124 g_assert(cf->count > 0);
2125 progbar_val = (gfloat) progbar_count / cf->count;
2127 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2128 "%4u of %u packets", progbar_count, cf->count);
2129 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2131 g_timer_start(prog_timer);
2134 if (cf->stop_flag) {
2135 /* Well, the user decided to abort the operation. Just stop,
2136 and arrange to return PSP_STOPPED to our caller, so they know
2137 it was stopped explicitly. */
2144 if (range != NULL) {
2145 /* do we have to process this packet? */
2146 process_this = packet_range_process_packet(range, fdata);
2147 if (process_this == range_process_next) {
2148 /* this packet uninteresting, continue with next one */
2150 } else if (process_this == range_processing_finished) {
2151 /* all interesting packets processed, stop the loop */
2156 /* Get the packet */
2157 if (!cf_read_record_r(cf, fdata, &rec, &buf)) {
2158 /* Attempt to get the packet failed. */
2162 /* Process the packet */
2163 if (!callback(cf, fdata, &rec, ws_buffer_start_ptr(&buf), callback_args)) {
2164 /* Callback failed. We assume it reported the error appropriately. */
2170 /* We're done printing the packets; destroy the progress bar if
2172 if (progbar != NULL)
2173 destroy_progress_dlg(progbar);
2174 g_timer_destroy(prog_timer);
2176 g_assert(cf->read_lock);
2177 cf->read_lock = FALSE;
2179 wtap_rec_cleanup(&rec);
2180 ws_buffer_free(&buf);
2188 } retap_callback_args_t;
2191 retap_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2192 const guint8 *pd, void *argsp)
2194 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2196 epan_dissect_run_with_taps(&args->edt, cf->cd_t, rec,
2197 frame_tvbuff_new(&cf->provider, fdata, pd),
2198 fdata, args->cinfo);
2199 epan_dissect_reset(&args->edt);
2205 cf_retap_packets(capture_file *cf)
2207 packet_range_t range;
2208 retap_callback_args_t callback_args;
2209 gboolean create_proto_tree;
2213 /* Presumably the user closed the capture file. */
2215 return CF_READ_ABORTED;
2218 cf_callback_invoke(cf_cb_file_retap_started, cf);
2220 /* Get the union of the flags for all tap listeners. */
2221 tap_flags = union_of_tap_listener_flags();
2223 /* If any tap listeners require the columns, construct them. */
2224 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2227 * Determine whether we need to create a protocol tree.
2230 * one of the tap listeners is going to apply a filter;
2232 * one of the tap listeners requires a protocol tree.
2235 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2237 /* Reset the tap listeners. */
2238 reset_tap_listeners();
2240 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2242 /* Iterate through the list of packets, dissecting all packets and
2243 re-running the taps. */
2244 packet_range_init(&range, cf);
2245 packet_range_process_init(&range);
2247 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2248 "all packets", TRUE, retap_packet,
2249 &callback_args, TRUE);
2251 packet_range_cleanup(&range);
2252 epan_dissect_cleanup(&callback_args.edt);
2254 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2258 /* Completed successfully. */
2262 /* Well, the user decided to abort the refiltering.
2263 Return CF_READ_ABORTED so our caller knows they did that. */
2264 return CF_READ_ABORTED;
2267 /* Error while retapping. */
2268 return CF_READ_ERROR;
2271 g_assert_not_reached();
2276 print_args_t *print_args;
2277 gboolean print_header_line;
2278 char *header_line_buf;
2279 int header_line_buf_len;
2280 gboolean print_formfeed;
2281 gboolean print_separator;
2285 int num_visible_cols;
2288 } print_callback_args_t;
2291 print_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2292 const guint8 *pd, void *argsp)
2294 print_callback_args_t *args = (print_callback_args_t *)argsp;
2300 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2301 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2302 col_item_t* col_item;
2304 /* Fill in the column information if we're printing the summary
2306 if (args->print_args->print_summary) {
2307 col_custom_prime_edt(&args->edt, &cf->cinfo);
2308 epan_dissect_run(&args->edt, cf->cd_t, rec,
2309 frame_tvbuff_new(&cf->provider, fdata, pd),
2311 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2313 epan_dissect_run(&args->edt, cf->cd_t, rec,
2314 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2316 if (args->print_formfeed) {
2317 if (!new_page(args->print_args->stream))
2321 * Print another header line if we print a packet summary on the
2324 if (args->print_args->print_col_headings)
2325 args->print_header_line = TRUE;
2327 if (args->print_separator) {
2328 if (!print_line(args->print_args->stream, 0, ""))
2334 * We generate bookmarks, if the output format supports them.
2335 * The name is "__frameN__".
2337 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2339 if (args->print_args->print_summary) {
2340 if (!args->print_args->print_col_headings)
2341 args->print_header_line = FALSE;
2342 if (args->print_header_line) {
2343 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2345 args->print_header_line = FALSE; /* we might not need to print any more */
2347 cp = &args->line_buf[0];
2349 for (i = 0; i < args->num_visible_cols; i++) {
2350 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2351 /* Find the length of the string for this column. */
2352 column_len = (int) strlen(col_item->col_data);
2353 if (args->col_widths[i] > column_len)
2354 column_len = args->col_widths[i];
2356 /* Make sure there's room in the line buffer for the column; if not,
2357 double its length. */
2358 line_len += column_len + 1; /* "+1" for space */
2359 if (line_len > args->line_buf_len) {
2360 cp_off = (int) (cp - args->line_buf);
2361 args->line_buf_len = 2 * line_len;
2362 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2363 cp = args->line_buf + cp_off;
2366 /* Right-justify the packet number column. */
2367 if (col_item->col_fmt == COL_NUMBER)
2368 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2370 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2372 if (i != args->num_visible_cols - 1)
2378 * Generate a bookmark, using the summary line as the title.
2380 if (!print_bookmark(args->print_args->stream, bookmark_name,
2384 if (!print_line(args->print_args->stream, 0, args->line_buf))
2388 * Generate a bookmark, using "Frame N" as the title, as we're not
2389 * printing the summary line.
2391 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2392 if (!print_bookmark(args->print_args->stream, bookmark_name,
2395 } /* if (print_summary) */
2397 if (args->print_args->print_dissections != print_dissections_none) {
2398 if (args->print_args->print_summary) {
2399 /* Separate the summary line from the tree with a blank line. */
2400 if (!print_line(args->print_args->stream, 0, ""))
2404 /* Print the information in that tree. */
2405 if (!proto_tree_print(args->print_args->print_dissections,
2406 args->print_args->print_hex, &args->edt, NULL,
2407 args->print_args->stream))
2410 /* Print a blank line if we print anything after this (aka more than one packet). */
2411 args->print_separator = TRUE;
2413 /* Print a header line if we print any more packet summaries */
2414 if (args->print_args->print_col_headings)
2415 args->print_header_line = TRUE;
2418 if (args->print_args->print_hex) {
2419 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2420 if (!print_line(args->print_args->stream, 0, ""))
2423 /* Print the full packet data as hex. */
2424 if (!print_hex_data(args->print_args->stream, &args->edt))
2427 /* Print a blank line if we print anything after this (aka more than one packet). */
2428 args->print_separator = TRUE;
2430 /* Print a header line if we print any more packet summaries */
2431 if (args->print_args->print_col_headings)
2432 args->print_header_line = TRUE;
2433 } /* if (args->print_args->print_dissections != print_dissections_none) */
2435 epan_dissect_reset(&args->edt);
2437 /* do we want to have a formfeed between each packet from now on? */
2438 if (args->print_args->print_formfeed) {
2439 args->print_formfeed = TRUE;
2445 epan_dissect_reset(&args->edt);
2450 cf_print_packets(capture_file *cf, print_args_t *print_args,
2451 gboolean show_progress_bar)
2453 print_callback_args_t callback_args;
2456 int i, cp_off, column_len, line_len;
2457 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2461 gboolean proto_tree_needed;
2463 callback_args.print_args = print_args;
2464 callback_args.print_header_line = print_args->print_col_headings;
2465 callback_args.header_line_buf = NULL;
2466 callback_args.header_line_buf_len = 256;
2467 callback_args.print_formfeed = FALSE;
2468 callback_args.print_separator = FALSE;
2469 callback_args.line_buf = NULL;
2470 callback_args.line_buf_len = 256;
2471 callback_args.col_widths = NULL;
2472 callback_args.num_visible_cols = 0;
2473 callback_args.visible_cols = NULL;
2475 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2476 destroy_print_stream(print_args->stream);
2477 return CF_PRINT_WRITE_ERROR;
2480 if (print_args->print_summary) {
2481 /* We're printing packet summaries. Allocate the header line buffer
2482 and get the column widths. */
2483 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2485 /* Find the number of visible columns and the last visible column */
2486 for (i = 0; i < prefs.num_cols; i++) {
2488 clp = g_list_nth(prefs.col_list, i);
2489 if (clp == NULL) /* Sanity check, Invalid column requested */
2492 cfmt = (fmt_data *) clp->data;
2493 if (cfmt->visible) {
2495 last_visible_col = i;
2499 /* if num_visible_col is 0, we are done */
2500 if (num_visible_col == 0) {
2501 g_free(callback_args.header_line_buf);
2505 /* Find the widths for each of the columns - maximum of the
2506 width of the title and the width of the data - and construct
2507 a buffer with a line containing the column titles. */
2508 callback_args.num_visible_cols = num_visible_col;
2509 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2510 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2511 cp = &callback_args.header_line_buf[0];
2513 visible_col_count = 0;
2514 for (i = 0; i < cf->cinfo.num_cols; i++) {
2516 clp = g_list_nth(prefs.col_list, i);
2517 if (clp == NULL) /* Sanity check, Invalid column requested */
2520 cfmt = (fmt_data *) clp->data;
2521 if (cfmt->visible == FALSE)
2524 /* Save the order of visible columns */
2525 callback_args.visible_cols[visible_col_count] = i;
2527 /* Don't pad the last column. */
2528 if (i == last_visible_col)
2529 callback_args.col_widths[visible_col_count] = 0;
2531 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2532 data_width = get_column_char_width(get_column_format(i));
2533 if (data_width > callback_args.col_widths[visible_col_count])
2534 callback_args.col_widths[visible_col_count] = data_width;
2537 /* Find the length of the string for this column. */
2538 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2539 if (callback_args.col_widths[visible_col_count] > column_len)
2540 column_len = callback_args.col_widths[visible_col_count];
2542 /* Make sure there's room in the line buffer for the column; if not,
2543 double its length. */
2544 line_len += column_len + 1; /* "+1" for space */
2545 if (line_len > callback_args.header_line_buf_len) {
2546 cp_off = (int) (cp - callback_args.header_line_buf);
2547 callback_args.header_line_buf_len = 2 * line_len;
2548 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2549 callback_args.header_line_buf_len + 1);
2550 cp = callback_args.header_line_buf + cp_off;
2553 /* Right-justify the packet number column. */
2554 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2555 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2557 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2559 if (i != cf->cinfo.num_cols - 1)
2562 visible_col_count++;
2566 /* Now start out the main line buffer with the same length as the
2567 header line buffer. */
2568 callback_args.line_buf_len = callback_args.header_line_buf_len;
2569 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2570 } /* if (print_summary) */
2572 /* Create the protocol tree, and make it visible, if we're printing
2573 the dissection or the hex data.
2574 XXX - do we need it if we're just printing the hex data? */
2576 callback_args.print_args->print_dissections != print_dissections_none ||
2577 callback_args.print_args->print_hex ||
2578 have_custom_cols(&cf->cinfo) || have_field_extractors();
2579 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2581 /* Iterate through the list of packets, printing the packets we were
2583 ret = process_specified_records(cf, &print_args->range, "Printing",
2584 "selected packets", TRUE, print_packet,
2585 &callback_args, show_progress_bar);
2586 epan_dissect_cleanup(&callback_args.edt);
2587 g_free(callback_args.header_line_buf);
2588 g_free(callback_args.line_buf);
2589 g_free(callback_args.col_widths);
2590 g_free(callback_args.visible_cols);
2595 /* Completed successfully. */
2599 /* Well, the user decided to abort the printing.
2601 XXX - note that what got generated before they did that
2602 will get printed if we're piping to a print program; we'd
2603 have to write to a file and then hand that to the print
2604 program to make it actually not print anything. */
2608 /* Error while printing.
2610 XXX - note that what got generated before they did that
2611 will get printed if we're piping to a print program; we'd
2612 have to write to a file and then hand that to the print
2613 program to make it actually not print anything. */
2614 destroy_print_stream(print_args->stream);
2615 return CF_PRINT_WRITE_ERROR;
2618 if (!print_finale(print_args->stream)) {
2619 destroy_print_stream(print_args->stream);
2620 return CF_PRINT_WRITE_ERROR;
2623 if (!destroy_print_stream(print_args->stream))
2624 return CF_PRINT_WRITE_ERROR;
2632 print_args_t *print_args;
2633 json_dumper jdumper;
2634 } write_packet_callback_args_t;
2637 write_pdml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2638 const guint8 *pd, void *argsp)
2640 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2642 /* Create the protocol tree, but don't fill in the column information. */
2643 epan_dissect_run(&args->edt, cf->cd_t, rec,
2644 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2646 /* Write out the information in that tree. */
2647 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, &cf->cinfo, args->fh, FALSE);
2649 epan_dissect_reset(&args->edt);
2651 return !ferror(args->fh);
2655 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2657 write_packet_callback_args_t callback_args;
2661 fh = ws_fopen(print_args->file, "w");
2663 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2665 write_pdml_preamble(fh, cf->filename);
2668 return CF_PRINT_WRITE_ERROR;
2671 callback_args.fh = fh;
2672 callback_args.print_args = print_args;
2673 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2675 /* Iterate through the list of packets, printing the packets we were
2677 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2678 "selected packets", TRUE,
2679 write_pdml_packet, &callback_args, TRUE);
2681 epan_dissect_cleanup(&callback_args.edt);
2686 /* Completed successfully. */
2690 /* Well, the user decided to abort the printing. */
2694 /* Error while printing. */
2696 return CF_PRINT_WRITE_ERROR;
2699 write_pdml_finale(fh);
2702 return CF_PRINT_WRITE_ERROR;
2705 /* XXX - check for an error */
2712 write_psml_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2713 const guint8 *pd, void *argsp)
2715 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2717 /* Fill in the column information */
2718 col_custom_prime_edt(&args->edt, &cf->cinfo);
2719 epan_dissect_run(&args->edt, cf->cd_t, rec,
2720 frame_tvbuff_new(&cf->provider, fdata, pd),
2722 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2724 /* Write out the column information. */
2725 write_psml_columns(&args->edt, args->fh, FALSE);
2727 epan_dissect_reset(&args->edt);
2729 return !ferror(args->fh);
2733 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2735 write_packet_callback_args_t callback_args;
2739 gboolean proto_tree_needed;
2741 fh = ws_fopen(print_args->file, "w");
2743 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2745 write_psml_preamble(&cf->cinfo, fh);
2748 return CF_PRINT_WRITE_ERROR;
2751 callback_args.fh = fh;
2752 callback_args.print_args = print_args;
2754 /* Fill in the column information, only create the protocol tree
2755 if having custom columns or field extractors. */
2756 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2757 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2759 /* Iterate through the list of packets, printing the packets we were
2761 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2762 "selected packets", TRUE,
2763 write_psml_packet, &callback_args, TRUE);
2765 epan_dissect_cleanup(&callback_args.edt);
2770 /* Completed successfully. */
2774 /* Well, the user decided to abort the printing. */
2778 /* Error while printing. */
2780 return CF_PRINT_WRITE_ERROR;
2783 write_psml_finale(fh);
2786 return CF_PRINT_WRITE_ERROR;
2789 /* XXX - check for an error */
2796 write_csv_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2797 const guint8 *pd, void *argsp)
2799 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2801 /* Fill in the column information */
2802 col_custom_prime_edt(&args->edt, &cf->cinfo);
2803 epan_dissect_run(&args->edt, cf->cd_t, rec,
2804 frame_tvbuff_new(&cf->provider, fdata, pd),
2806 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2808 /* Write out the column information. */
2809 write_csv_columns(&args->edt, args->fh);
2811 epan_dissect_reset(&args->edt);
2813 return !ferror(args->fh);
2817 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2819 write_packet_callback_args_t callback_args;
2820 gboolean proto_tree_needed;
2824 fh = ws_fopen(print_args->file, "w");
2826 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2828 write_csv_column_titles(&cf->cinfo, fh);
2831 return CF_PRINT_WRITE_ERROR;
2834 callback_args.fh = fh;
2835 callback_args.print_args = print_args;
2837 /* only create the protocol tree if having custom columns or field extractors. */
2838 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2839 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2841 /* Iterate through the list of packets, printing the packets we were
2843 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2844 "selected packets", TRUE,
2845 write_csv_packet, &callback_args, TRUE);
2847 epan_dissect_cleanup(&callback_args.edt);
2852 /* Completed successfully. */
2856 /* Well, the user decided to abort the printing. */
2860 /* Error while printing. */
2862 return CF_PRINT_WRITE_ERROR;
2865 /* XXX - check for an error */
2872 carrays_write_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2873 const guint8 *pd, void *argsp)
2875 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2877 epan_dissect_run(&args->edt, cf->cd_t, rec,
2878 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2879 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2880 epan_dissect_reset(&args->edt);
2882 return !ferror(args->fh);
2886 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2888 write_packet_callback_args_t callback_args;
2892 fh = ws_fopen(print_args->file, "w");
2895 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2899 return CF_PRINT_WRITE_ERROR;
2902 callback_args.fh = fh;
2903 callback_args.print_args = print_args;
2904 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2906 /* Iterate through the list of packets, printing the packets we were
2908 ret = process_specified_records(cf, &print_args->range,
2910 "selected packets", TRUE,
2911 carrays_write_packet, &callback_args, TRUE);
2913 epan_dissect_cleanup(&callback_args.edt);
2917 /* Completed successfully. */
2920 /* Well, the user decided to abort the printing. */
2923 /* Error while printing. */
2925 return CF_PRINT_WRITE_ERROR;
2933 write_json_packet(capture_file *cf, frame_data *fdata, wtap_rec *rec,
2934 const guint8 *pd, void *argsp)
2936 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2938 /* Create the protocol tree, but don't fill in the column information. */
2939 epan_dissect_run(&args->edt, cf->cd_t, rec,
2940 frame_tvbuff_new(&cf->provider, fdata, pd), fdata, NULL);
2942 /* Write out the information in that tree. */
2943 write_json_proto_tree(NULL, args->print_args->print_dissections,
2944 args->print_args->print_hex, NULL, PF_NONE,
2945 &args->edt, &cf->cinfo, proto_node_group_children_by_unique,
2948 epan_dissect_reset(&args->edt);
2950 return !ferror(args->fh);
2954 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2956 write_packet_callback_args_t callback_args;
2960 fh = ws_fopen(print_args->file, "w");
2962 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2964 callback_args.jdumper = write_json_preamble(fh);
2967 return CF_PRINT_WRITE_ERROR;
2970 callback_args.fh = fh;
2971 callback_args.print_args = print_args;
2972 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2974 /* Iterate through the list of packets, printing the packets we were
2976 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2977 "selected packets", TRUE,
2978 write_json_packet, &callback_args, TRUE);
2980 epan_dissect_cleanup(&callback_args.edt);
2985 /* Completed successfully. */
2989 /* Well, the user decided to abort the printing. */
2993 /* Error while printing. */
2995 return CF_PRINT_WRITE_ERROR;
2998 write_json_finale(&callback_args.jdumper);
3001 return CF_PRINT_WRITE_ERROR;
3004 /* XXX - check for an error */
3011 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3012 search_direction dir)
3016 mdata.string = string;
3017 mdata.string_len = strlen(string);
3018 return find_packet(cf, match_protocol_tree, &mdata, dir);
3022 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3024 mdata->frame_matched = FALSE;
3025 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3026 mdata->string_len = strlen(mdata->string);
3028 /* Iterate through all the nodes looking for matching text */
3029 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3030 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3034 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3036 match_data *mdata = (match_data *)criterion;
3039 /* Load the frame's data. */
3040 if (!cf_read_record(cf, fdata)) {
3041 /* Attempt to get the packet failed. */
3045 /* Construct the protocol tree, including the displayed text */
3046 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3047 /* We don't need the column information */
3048 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3049 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3052 /* Iterate through all the nodes, seeing if they have text that matches. */
3054 mdata->frame_matched = FALSE;
3055 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3056 epan_dissect_cleanup(&edt);
3057 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3061 match_subtree_text(proto_node *node, gpointer data)
3063 match_data *mdata = (match_data *) data;
3064 const gchar *string = mdata->string;
3065 size_t string_len = mdata->string_len;
3066 capture_file *cf = mdata->cf;
3067 field_info *fi = PNODE_FINFO(node);
3068 gchar label_str[ITEM_LABEL_LENGTH];
3075 /* dissection with an invisible proto tree? */
3078 if (mdata->frame_matched) {
3079 /* We already had a match; don't bother doing any more work. */
3083 /* Don't match invisible entries. */
3084 if (PROTO_ITEM_IS_HIDDEN(node))
3087 /* was a free format label produced? */
3089 label_ptr = fi->rep->representation;
3091 /* no, make a generic label */
3092 label_ptr = label_str;
3093 proto_item_fill_label(fi, label_str);
3097 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
3098 mdata->frame_matched = TRUE;
3103 /* Does that label match? */
3104 label_len = strlen(label_ptr);
3105 for (i = 0; i < label_len; i++) {
3106 c_char = label_ptr[i];
3108 c_char = g_ascii_toupper(c_char);
3109 if (c_char == string[c_match]) {
3111 if (c_match == string_len) {
3112 /* No need to look further; we have a match */
3113 mdata->frame_matched = TRUE;
3122 /* Recurse into the subtree, if it exists */
3123 if (node->first_child != NULL)
3124 proto_tree_children_foreach(node, match_subtree_text, mdata);
3128 cf_find_packet_summary_line(capture_file *cf, const char *string,
3129 search_direction dir)
3133 mdata.string = string;
3134 mdata.string_len = strlen(string);
3135 return find_packet(cf, match_summary_line, &mdata, dir);
3139 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3141 match_data *mdata = (match_data *)criterion;
3142 const gchar *string = mdata->string;
3143 size_t string_len = mdata->string_len;
3145 const char *info_column;
3146 size_t info_column_len;
3147 match_result result = MR_NOTMATCHED;
3153 /* Load the frame's data. */
3154 if (!cf_read_record(cf, fdata)) {
3155 /* Attempt to get the packet failed. */
3159 /* Don't bother constructing the protocol tree */
3160 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3161 /* Get the column information */
3162 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3163 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3166 /* Find the Info column */
3167 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3168 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3169 /* Found it. See if we match. */
3170 info_column = edt.pi.cinfo->columns[colx].col_data;
3171 info_column_len = strlen(info_column);
3173 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3174 result = MR_MATCHED;
3178 for (i = 0; i < info_column_len; i++) {
3179 c_char = info_column[i];
3181 c_char = g_ascii_toupper(c_char);
3182 if (c_char == string[c_match]) {
3184 if (c_match == string_len) {
3185 result = MR_MATCHED;
3195 epan_dissect_cleanup(&edt);
3202 } cbs_t; /* "Counted byte string" */
3206 * The current match_* routines only support ASCII case insensitivity and don't
3207 * convert UTF-8 inputs to UTF-16 for matching.
3209 * We could modify them to use the GLib Unicode routines or the International
3210 * Components for Unicode library but it's not apparent that we could do so
3211 * without consuming a lot more CPU and memory or that searching would be
3212 * significantly better.
3216 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3217 search_direction dir)
3222 info.data_len = string_size;
3224 /* Regex, String or hex search? */
3226 /* Regular Expression search */
3227 return find_packet(cf, match_regex, NULL, dir);
3228 } else if (cf->string) {
3229 /* String search - what type of string? */
3230 switch (cf->scs_type) {
3232 case SCS_NARROW_AND_WIDE:
3233 return find_packet(cf, match_narrow_and_wide, &info, dir);
3236 return find_packet(cf, match_narrow, &info, dir);
3239 return find_packet(cf, match_wide, &info, dir);
3242 g_assert_not_reached();
3246 return find_packet(cf, match_binary, &info, dir);
3250 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3252 cbs_t *info = (cbs_t *)criterion;
3253 const guint8 *ascii_text = info->data;
3254 size_t textlen = info->data_len;
3255 match_result result;
3262 /* Load the frame's data. */
3263 if (!cf_read_record(cf, fdata)) {
3264 /* Attempt to get the packet failed. */
3268 result = MR_NOTMATCHED;
3269 buf_len = fdata->cap_len;
3270 pd = ws_buffer_start_ptr(&cf->buf);
3272 while (i < buf_len) {
3275 c_char = g_ascii_toupper(c_char);
3276 if (c_char != '\0') {
3277 if (c_char == ascii_text[c_match]) {
3279 if (c_match == textlen) {
3280 result = MR_MATCHED;
3281 cf->search_pos = i; /* Save the position of the last character
3282 for highlighting the field. */
3283 cf->search_len = (guint32)textlen;
3288 g_assert(i>=c_match);
3289 i -= (guint32)c_match;
3299 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3302 cbs_t *info = (cbs_t *)criterion;
3303 const guint8 *ascii_text = info->data;
3304 size_t textlen = info->data_len;
3305 match_result result;
3311 /* Load the frame's data. */
3312 if (!cf_read_record(cf, fdata)) {
3313 /* Attempt to get the packet failed. */
3317 result = MR_NOTMATCHED;
3318 buf_len = fdata->cap_len;
3319 pd = ws_buffer_start_ptr(&cf->buf);
3321 while (i < buf_len) {
3324 c_char = g_ascii_toupper(c_char);
3325 if (c_char == ascii_text[c_match]) {
3327 if (c_match == textlen) {
3328 result = MR_MATCHED;
3329 cf->search_pos = i; /* Save the position of the last character
3330 for highlighting the field. */
3331 cf->search_len = (guint32)textlen;
3336 g_assert(i>=c_match);
3337 i -= (guint32)c_match;
3347 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3349 cbs_t *info = (cbs_t *)criterion;
3350 const guint8 *ascii_text = info->data;
3351 size_t textlen = info->data_len;
3352 match_result result;
3359 /* Load the frame's data. */
3360 if (!cf_read_record(cf, fdata)) {
3361 /* Attempt to get the packet failed. */
3365 result = MR_NOTMATCHED;
3366 buf_len = fdata->cap_len;
3367 pd = ws_buffer_start_ptr(&cf->buf);
3369 while (i < buf_len) {
3372 c_char = g_ascii_toupper(c_char);
3373 if (c_char == ascii_text[c_match]) {
3375 if (c_match == textlen) {
3376 result = MR_MATCHED;
3377 cf->search_pos = i; /* Save the position of the last character
3378 for highlighting the field. */
3379 cf->search_len = (guint32)textlen;
3385 g_assert(i>=(c_match*2));
3386 i -= (guint32)c_match*2;
3395 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3397 cbs_t *info = (cbs_t *)criterion;
3398 const guint8 *binary_data = info->data;
3399 size_t datalen = info->data_len;
3400 match_result result;
3406 /* Load the frame's data. */
3407 if (!cf_read_record(cf, fdata)) {
3408 /* Attempt to get the packet failed. */
3412 result = MR_NOTMATCHED;
3413 buf_len = fdata->cap_len;
3414 pd = ws_buffer_start_ptr(&cf->buf);
3416 while (i < buf_len) {
3417 if (pd[i] == binary_data[c_match]) {
3419 if (c_match == datalen) {
3420 result = MR_MATCHED;
3421 cf->search_pos = i; /* Save the position of the last character
3422 for highlighting the field. */
3423 cf->search_len = (guint32)datalen;
3428 g_assert(i>=c_match);
3429 i -= (guint32)c_match;
3438 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3440 match_result result = MR_NOTMATCHED;
3441 GMatchInfo *match_info = NULL;
3443 /* Load the frame's data. */
3444 if (!cf_read_record(cf, fdata)) {
3445 /* Attempt to get the packet failed. */
3449 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3450 0, (GRegexMatchFlags) 0, &match_info, NULL))
3452 gint start_pos = 0, end_pos = 0;
3453 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3454 cf->search_pos = end_pos - 1;
3455 cf->search_len = end_pos - start_pos;
3456 result = MR_MATCHED;
3462 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3463 search_direction dir)
3465 return find_packet(cf, match_dfilter, sfcode, dir);
3469 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3470 search_direction dir)
3475 if (!dfilter_compile(filter, &sfcode, NULL)) {
3477 * XXX - this shouldn't happen, as the filter string is machine
3482 if (sfcode == NULL) {
3484 * XXX - this shouldn't happen, as the filter string is machine
3489 result = find_packet(cf, match_dfilter, sfcode, dir);
3490 dfilter_free(sfcode);
3495 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3497 dfilter_t *sfcode = (dfilter_t *)criterion;
3499 match_result result;
3501 /* Load the frame's data. */
3502 if (!cf_read_record(cf, fdata)) {
3503 /* Attempt to get the packet failed. */
3507 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3508 epan_dissect_prime_with_dfilter(&edt, sfcode);
3509 epan_dissect_run(&edt, cf->cd_t, &cf->rec,
3510 frame_tvbuff_new_buffer(&cf->provider, fdata, &cf->buf),
3512 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3513 epan_dissect_cleanup(&edt);
3518 cf_find_packet_marked(capture_file *cf, search_direction dir)
3520 return find_packet(cf, match_marked, NULL, dir);
3524 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3526 return fdata->marked ? MR_MATCHED : MR_NOTMATCHED;
3530 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3532 return find_packet(cf, match_time_reference, NULL, dir);
3536 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3538 return fdata->ref_time ? MR_MATCHED : MR_NOTMATCHED;
3542 find_packet(capture_file *cf,
3543 match_result (*match_function)(capture_file *, frame_data *, void *),
3544 void *criterion, search_direction dir)
3546 frame_data *start_fd;
3548 guint32 prev_framenum;
3550 frame_data *new_fd = NULL;
3551 progdlg_t *progbar = NULL;
3552 GTimer *prog_timer = g_timer_new();
3556 GTimeVal start_time;
3557 gchar status_str[100];
3559 match_result result;
3561 start_fd = cf->current_frame;
3562 if (start_fd != NULL) {
3563 prev_framenum = start_fd->num;
3565 prev_framenum = 0; /* No start packet selected. */
3568 /* Iterate through the list of packets, starting at the packet we've
3569 picked, calling a routine to run the filter on the packet, see if
3570 it matches, and stop if so. */
3572 framenum = prev_framenum;
3574 g_timer_start(prog_timer);
3575 /* Progress so far. */
3578 cf->stop_flag = FALSE;
3579 g_get_current_time(&start_time);
3581 title = cf->sfilter?cf->sfilter:"";
3583 /* Create the progress bar if necessary.
3584 We check on every iteration of the loop, so that it takes no
3585 longer than the standard time to create it (otherwise, for a
3586 large file, we might take considerably longer than that standard
3587 time in order to get to the next progress bar step). */
3588 if (progbar == NULL)
3589 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3590 FALSE, &cf->stop_flag, &start_time, progbar_val);
3593 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3594 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3595 * likely trigger UI paint events, which might take a while depending on
3596 * the platform and display. Reset our timer *after* painting.
3598 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3599 /* let's not divide by zero. I should never be started
3600 * with count == 0, so let's assert that
3602 g_assert(cf->count > 0);
3604 progbar_val = (gfloat) count / cf->count;
3606 g_snprintf(status_str, sizeof(status_str),
3607 "%4u of %u packets", count, cf->count);
3608 update_progress_dlg(progbar, progbar_val, status_str);
3610 g_timer_start(prog_timer);
3613 if (cf->stop_flag) {
3614 /* Well, the user decided to abort the search. Go back to the
3615 frame where we started. */
3620 /* Go past the current frame. */
3621 if (dir == SD_BACKWARD) {
3622 /* Go on to the previous frame. */
3623 if (framenum <= 1) {
3625 * XXX - other apps have a bit more of a detailed message
3626 * for this, and instead of offering "OK" and "Cancel",
3627 * they offer things such as "Continue" and "Cancel";
3628 * we need an API for popping up alert boxes with
3629 * {Verb} and "Cancel".
3632 if (prefs.gui_find_wrap) {
3633 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3634 framenum = cf->count; /* wrap around */
3636 statusbar_push_temporary_msg("Search reached the beginning.");
3637 framenum = prev_framenum; /* stay on previous packet */
3642 /* Go on to the next frame. */
3643 if (framenum == cf->count) {
3644 if (prefs.gui_find_wrap) {
3645 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3646 framenum = 1; /* wrap around */
3648 statusbar_push_temporary_msg("Search reached the end.");
3649 framenum = prev_framenum; /* stay on previous packet */
3655 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
3658 /* Is this packet in the display? */
3659 if (fdata && fdata->passed_dfilter) {
3660 /* Yes. Does it match the search criterion? */
3661 result = (*match_function)(cf, fdata, criterion);
3662 if (result == MR_ERROR) {
3663 /* Error; our caller has reported the error. Go back to the frame
3664 where we started. */
3667 } else if (result == MR_MATCHED) {
3668 /* Yes. Go to the new frame. */
3674 if (fdata == start_fd) {
3675 /* We're back to the frame we were on originally, and that frame
3676 doesn't match the search filter. The search failed. */
3681 /* We're done scanning the packets; destroy the progress bar if it
3683 if (progbar != NULL)
3684 destroy_progress_dlg(progbar);
3685 g_timer_destroy(prog_timer);
3687 if (new_fd != NULL) {
3688 /* Find and select */
3689 cf->search_in_progress = TRUE;
3690 found = packet_list_select_row_from_data(new_fd);
3691 cf->search_in_progress = FALSE;
3692 cf->search_pos = 0; /* Reset the position */
3693 cf->search_len = 0; /* Reset length */
3695 /* We didn't find a row corresponding to this frame.
3696 This means that the frame isn't being displayed currently,
3697 so we can't select it. */
3698 simple_message_box(ESD_TYPE_INFO, NULL,
3699 "The capture file is probably not fully dissected.",
3700 "End of capture exceeded.");
3703 return TRUE; /* success */
3705 return FALSE; /* failure */
3709 cf_goto_frame(capture_file *cf, guint fnumber)
3713 if (cf == NULL || cf->provider.frames == NULL) {
3714 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3715 statusbar_push_temporary_msg("There is no file loaded");
3716 return FALSE; /* we failed to go to that packet */
3719 fdata = frame_data_sequence_find(cf->provider.frames, fnumber);
3721 if (fdata == NULL) {
3722 /* we didn't find a packet with that packet number */
3723 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3724 return FALSE; /* we failed to go to that packet */
3726 if (!fdata->passed_dfilter) {
3727 /* that packet currently isn't displayed */
3728 /* XXX - add it to the set of displayed packets? */
3729 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3730 return FALSE; /* we failed to go to that packet */
3733 if (!packet_list_select_row_from_data(fdata)) {
3734 /* We didn't find a row corresponding to this frame.
3735 This means that the frame isn't being displayed currently,
3736 so we can't select it. */
3737 simple_message_box(ESD_TYPE_INFO, NULL,
3738 "The capture file is probably not fully dissected.",
3739 "End of capture exceeded.");
3742 return TRUE; /* we got to that packet */
3746 * Go to frame specified by currently selected protocol tree item.
3749 cf_goto_framenum(capture_file *cf)
3751 header_field_info *hfinfo;
3754 if (cf->finfo_selected) {
3755 hfinfo = cf->finfo_selected->hfinfo;
3757 if (hfinfo->type == FT_FRAMENUM) {
3758 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3760 return cf_goto_frame(cf, framenum);
3767 /* Select the packet on a given row. */
3769 cf_select_packet(capture_file *cf, int row)
3771 epan_dissect_t *old_edt;
3774 /* Get the frame data struct pointer for this frame */
3775 fdata = packet_list_get_row_data(row);
3777 if (fdata == NULL) {
3781 /* Get the data in that frame. */
3782 if (!cf_read_record (cf, fdata)) {
3786 /* Record that this frame is the current frame. */
3787 cf->current_frame = fdata;
3788 cf->current_row = row;
3791 /* Create the logical protocol tree. */
3792 /* We don't need the columns here. */
3793 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3795 tap_build_interesting(cf->edt);
3796 epan_dissect_run(cf->edt, cf->cd_t, &cf->rec,
3797 frame_tvbuff_new_buffer(&cf->provider, cf->current_frame, &cf->buf),
3798 cf->current_frame, NULL);
3800 dfilter_macro_build_ftv_cache(cf->edt->tree);
3802 if (old_edt != NULL)
3803 epan_dissect_free(old_edt);
3807 /* Unselect the selected packet, if any. */
3809 cf_unselect_packet(capture_file *cf)
3811 epan_dissect_t *old_edt = cf->edt;
3815 /* No packet is selected. */
3816 cf->current_frame = NULL;
3817 cf->current_row = 0;
3819 /* Destroy the epan_dissect_t for the unselected packet. */
3820 if (old_edt != NULL)
3821 epan_dissect_free(old_edt);
3825 * Mark a particular frame.
3828 cf_mark_frame(capture_file *cf, frame_data *frame)
3830 if (! frame->marked) {
3831 frame->marked = TRUE;
3832 if (cf->count > cf->marked_count)
3838 * Unmark a particular frame.
3841 cf_unmark_frame(capture_file *cf, frame_data *frame)
3843 if (frame->marked) {
3844 frame->marked = FALSE;
3845 if (cf->marked_count > 0)
3851 * Ignore a particular frame.
3854 cf_ignore_frame(capture_file *cf, frame_data *frame)
3856 if (! frame->ignored) {
3857 frame->ignored = TRUE;
3858 if (cf->count > cf->ignored_count)
3859 cf->ignored_count++;
3864 * Un-ignore a particular frame.
3867 cf_unignore_frame(capture_file *cf, frame_data *frame)
3869 if (frame->ignored) {
3870 frame->ignored = FALSE;
3871 if (cf->ignored_count > 0)
3872 cf->ignored_count--;
3877 * Read the section comment.
3880 cf_read_section_comment(capture_file *cf)
3882 wtap_block_t shb_inf;
3886 /* XXX - support multiple SHBs */
3887 shb_inf = wtap_file_get_shb(cf->provider.wth);
3889 /* Get the first comment from the SHB. */
3890 /* XXX - support multiple comments */
3891 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3897 * Modify the section comment.
3900 cf_update_section_comment(capture_file *cf, gchar *comment)
3902 wtap_block_t shb_inf;
3906 /* XXX - support multiple SHBs */
3907 shb_inf = wtap_file_get_shb(cf->provider.wth);
3909 /* Get the first comment from the SHB. */
3910 /* XXX - support multiple comments */
3911 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3912 /* There's no comment - add one. */
3913 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3915 /* See if the comment has changed or not */
3916 if (strcmp(shb_comment, comment) == 0) {
3921 /* The comment has changed, let's update it */
3922 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3924 /* Mark the file as having unsaved changes */
3925 cf->unsaved_changes = TRUE;
3929 * Get the comment on a packet (record).
3930 * If the comment has been edited, it returns the result of the edit,
3931 * otherwise it returns the comment from the file.
3934 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3938 /* fetch user comment */
3939 if (fd->has_user_comment)
3940 return g_strdup(cap_file_provider_get_user_comment(&cf->provider, fd));
3942 /* fetch phdr comment */
3943 if (fd->has_phdr_comment) {
3944 wtap_rec rec; /* Record metadata */
3945 Buffer buf; /* Record data */
3947 wtap_rec_init(&rec);
3948 ws_buffer_init(&buf, 1500);
3950 if (!cf_read_record_r(cf, fd, &rec, &buf))
3951 { /* XXX, what we can do here? */ }
3953 comment = rec.opt_comment;
3954 wtap_rec_cleanup(&rec);
3955 ws_buffer_free(&buf);
3962 * Update(replace) the comment on a capture from a frame
3965 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3967 char *pkt_comment = cf_get_packet_comment(cf, fd);
3969 /* Check if the comment has changed */
3970 if (!g_strcmp0(pkt_comment, new_comment)) {
3971 g_free(pkt_comment);
3974 g_free(pkt_comment);
3977 cf->packet_comment_count--;
3980 cf->packet_comment_count++;
3982 cap_file_provider_set_user_comment(&cf->provider, fd, new_comment);
3984 expert_update_comment_count(cf->packet_comment_count);
3986 /* OK, we have unsaved changes. */
3987 cf->unsaved_changes = TRUE;
3992 * What types of comments does this capture file have?
3995 cf_comment_types(capture_file *cf)
3997 guint32 comment_types = 0;
3999 if (cf_read_section_comment(cf) != NULL)
4000 comment_types |= WTAP_COMMENT_PER_SECTION;
4001 if (cf->packet_comment_count != 0)
4002 comment_types |= WTAP_COMMENT_PER_PACKET;
4003 return comment_types;
4007 * Add a resolved address to this file's list of resolved addresses.
4010 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
4013 * XXX - support multiple resolved address lists, and add to the one
4014 * attached to this file?
4016 if (!add_ip_name_from_string(addr, name))
4019 /* OK, we have unsaved changes. */
4020 cf->unsaved_changes = TRUE;
4028 } save_callback_args_t;
4031 * Save a capture to a file, in a particular format, saving either
4032 * all packets, all currently-displayed packets, or all marked packets.
4034 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4035 * up a message box for the failure.
4038 save_record(capture_file *cf, frame_data *fdata, wtap_rec *rec,
4039 const guint8 *pd, void *argsp)
4041 save_callback_args_t *args = (save_callback_args_t *)argsp;
4045 const char *pkt_comment;
4047 /* Copy the record information from what was read in from the file. */
4050 /* Make changes based on anything that the user has done but that
4051 hasn't been saved yet. */
4052 if (fdata->has_user_comment)
4053 pkt_comment = cap_file_provider_get_user_comment(&cf->provider, fdata);
4055 pkt_comment = rec->opt_comment;
4056 new_rec.opt_comment = g_strdup(pkt_comment);
4057 new_rec.has_comment_changed = fdata->has_user_comment ? TRUE : FALSE;
4058 /* XXX - what if times have been shifted? */
4060 /* and save the packet */
4061 if (!wtap_dump(args->pdh, &new_rec, pd, &err, &err_info)) {
4062 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4067 g_free(new_rec.opt_comment);
4072 * Can this capture file be written out in any format using Wiretap
4073 * rather than by copying the raw data?
4076 cf_can_write_with_wiretap(capture_file *cf)
4078 /* We don't care whether we support the comments in this file or not;
4079 if we can't, we'll offer the user the option of discarding the
4081 return wtap_dump_can_write(cf->linktypes, 0);
4085 * Should we let the user do a save?
4089 * the file has unsaved changes, and we can save it in some
4090 * format through Wiretap
4094 * the file is a temporary file and has no unsaved changes (so
4095 * that "saving" it just means copying it).
4097 * XXX - we shouldn't allow files to be edited if they can't be saved,
4098 * so cf->unsaved_changes should be true only if the file can be saved.
4100 * We don't care whether we support the comments in this file or not;
4101 * if we can't, we'll offer the user the option of discarding the
4105 cf_can_save(capture_file *cf)
4107 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4108 /* Saved changes, and we can write it out with Wiretap. */
4112 if (cf->is_tempfile && !cf->unsaved_changes) {
4114 * Temporary file with no unsaved changes, so we can just do a
4120 /* Nothing to save. */
4125 * Should we let the user do a "save as"?
4129 * we can save it in some format through Wiretap
4133 * the file is a temporary file and has no unsaved changes (so
4134 * that "saving" it just means copying it).
4136 * XXX - we shouldn't allow files to be edited if they can't be saved,
4137 * so cf->unsaved_changes should be true only if the file can be saved.
4139 * We don't care whether we support the comments in this file or not;
4140 * if we can't, we'll offer the user the option of discarding the
4144 cf_can_save_as(capture_file *cf)
4146 if (wtap_dump_can_write(cf->linktypes, 0)) {
4147 /* We can write it out with Wiretap. */
4151 if (cf->is_tempfile && !cf->unsaved_changes) {
4153 * Temporary file with no unsaved changes, so we can just do a
4159 /* Nothing to save. */
4164 * Does this file have unsaved data?
4167 cf_has_unsaved_data(capture_file *cf)
4170 * If this is a temporary file, or a file with unsaved changes, it
4173 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4177 * Quick scan to find packet offsets.
4179 static cf_read_status_t
4180 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4182 const wtap_rec *rec;
4187 progdlg_t *progbar = NULL;
4188 GTimer *prog_timer = g_timer_new();
4191 GTimeVal start_time;
4192 gchar status_str[100];
4197 /* Close the old handle. */
4198 wtap_close(cf->provider.wth);
4200 /* Open the new file. */
4201 /* XXX: this will go through all open_routines for a matching one. But right
4202 now rescan_file() is only used when a file is being saved to a different
4203 format than the original, and the user is not given a choice of which
4204 reader to use (only which format to save it in), so doing this makes
4206 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4207 if (cf->provider.wth == NULL) {
4208 cfile_open_failure_alert_box(fname, err, err_info);
4209 return CF_READ_ERROR;
4212 /* We're scanning a file whose contents should be the same as what
4213 we had before, so we don't discard dissection state etc.. */
4216 /* Set the file name because we need it to set the follow stream filter.
4217 XXX - is that still true? We need it for other reasons, though,
4219 cf->filename = g_strdup(fname);
4221 /* Indicate whether it's a permanent or temporary file. */
4222 cf->is_tempfile = is_tempfile;
4224 /* No user changes yet. */
4225 cf->unsaved_changes = FALSE;
4227 cf->cd_t = wtap_file_type_subtype(cf->provider.wth);
4228 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4230 cf->snap = wtap_snapshot_length(cf->provider.wth);
4232 name_ptr = g_filename_display_basename(cf->filename);
4234 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4236 /* Record the file's compression type.
4237 XXX - do we know this at open time? */
4238 cf->compression_type = wtap_get_compression_type(cf->provider.wth);
4240 /* Find the size of the file. */
4241 size = wtap_file_size(cf->provider.wth, NULL);
4243 g_timer_start(prog_timer);
4245 cf->stop_flag = FALSE;
4246 g_get_current_time(&start_time);
4249 rec = wtap_get_rec(cf->provider.wth);
4250 while ((wtap_read(cf->provider.wth, &err, &err_info, &data_offset))) {
4252 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4253 fdata->file_off = data_offset;
4256 cf->f_datalen = wtap_read_so_far(cf->provider.wth);
4258 /* Create the progress bar if necessary. */
4259 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4260 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4261 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4262 TRUE, &cf->stop_flag, &start_time, progbar_val);
4266 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4267 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4268 * likely trigger UI paint events, which might take a while depending on
4269 * the platform and display. Reset our timer *after* painting.
4271 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4272 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4273 /* update the packet bar content on the first run or frequently on very large files */
4274 update_progress_dlg(progbar, progbar_val, status_str);
4275 compute_elapsed(cf, &start_time);
4276 packets_bar_update();
4277 g_timer_start(prog_timer);
4281 if (cf->stop_flag) {
4282 /* Well, the user decided to abort the rescan. Sadly, as this
4283 isn't a reread, recovering is difficult, so we'll just
4284 close the current capture. */
4288 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4289 it's not already there.
4290 XXX - yes, this is O(N), so if every packet had a different
4291 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4292 there are probably going to be a small number of encapsulation types
4294 if (rec->rec_type == REC_TYPE_PACKET) {
4295 cf_add_encapsulation_type(cf, rec->rec_header.packet_header.pkt_encap);
4299 /* Free the display name */
4302 /* We're done reading the file; destroy the progress bar if it was created. */
4303 if (progbar != NULL)
4304 destroy_progress_dlg(progbar);
4305 g_timer_destroy(prog_timer);
4307 /* We're done reading sequentially through the file. */
4308 cf->state = FILE_READ_DONE;
4310 /* Close the sequential I/O side, to free up memory it requires. */
4311 wtap_sequential_close(cf->provider.wth);
4313 /* compute the time it took to load the file */
4314 compute_elapsed(cf, &start_time);
4316 /* Set the file encapsulation type now; we don't know what it is until
4317 we've looked at all the packets, as we don't know until then whether
4318 there's more than one type (and thus whether it's
4319 WTAP_ENCAP_PER_PACKET). */
4320 cf->lnk_t = wtap_file_encap(cf->provider.wth);
4322 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4324 if (cf->stop_flag) {
4325 /* Our caller will give up at this point. */
4326 return CF_READ_ABORTED;
4330 /* Put up a message box noting that the read failed somewhere along
4331 the line. Don't throw out the stuff we managed to read, though,
4333 cfile_read_failure_alert_box(NULL, err, err_info);
4334 return CF_READ_ERROR;
4340 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4341 wtap_compression_type compression_type,
4342 gboolean discard_comments, gboolean dont_reopen)
4345 gchar *fname_new = NULL;
4348 addrinfo_lists_t *addr_lists;
4352 gchar *display_basename;
4359 save_callback_args_t callback_args;
4360 gboolean needs_reload = FALSE;
4362 /* XXX caller should avoid saving the file while a read is pending
4363 * (e.g. by delaying the save action) */
4364 if (cf->read_lock) {
4365 g_warning("cf_save_records(\"%s\") while the file is being read, potential crash ahead", fname);
4368 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4370 addr_lists = get_addrinfo_list();
4372 if (save_format == cf->cd_t && compression_type == cf->compression_type
4373 && !discard_comments && !cf->unsaved_changes
4374 && (wtap_addrinfo_list_empty(addr_lists) || !wtap_dump_has_name_resolution(save_format))) {
4375 /* We're saving in the format it's already in, and we're not discarding
4376 comments, and there are no changes we have in memory that aren't saved
4377 to the file, and we have no name resolution information to write or
4378 the file format we're saving in doesn't support writing name
4379 resolution information, so we can just move or copy the raw data. */
4381 if (cf->is_tempfile) {
4382 /* The file being saved is a temporary file from a live
4383 capture, so it doesn't need to stay around under that name;
4384 first, try renaming the capture buffer file to the new name.
4385 This acts as a "safe save", in that, if the file already
4386 exists, the existing file will be removed only if the rename
4389 Sadly, on Windows, as we have the current capture file
4390 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4391 (to cause the rename to remove an existing target), as
4392 done by ws_stdio_rename() (ws_rename() is #defined to
4393 be ws_stdio_rename() on Windows) will fail.
4395 According to the MSDN documentation for CreateFile(), if,
4396 when we open a capture file, we were to directly do a CreateFile(),
4397 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4398 convert it to a file descriptor with _open_osfhandle(),
4399 that would allow the file to be renamed out from under us.
4401 However, that doesn't work in practice. Perhaps the problem
4402 is that the process doing the rename is the process that
4403 has the file open. */
4405 if (ws_rename(cf->filename, fname) == 0) {
4406 /* That succeeded - there's no need to copy the source file. */
4407 how_to_save = SAVE_WITH_MOVE;
4409 if (errno == EXDEV) {
4410 /* They're on different file systems, so we have to copy the
4412 how_to_save = SAVE_WITH_COPY;
4414 /* The rename failed, but not because they're on different
4415 file systems - put up an error message. (Or should we
4416 just punt and try to copy? The only reason why I'd
4417 expect the rename to fail and the copy to succeed would
4418 be if we didn't have permission to remove the file from
4419 the temporary directory, and that might be fixable - but
4420 is it worth requiring the user to go off and fix it?) */
4421 cf_rename_failure_alert_box(fname, errno);
4426 /* Windows - copy the file to its new location. */
4427 how_to_save = SAVE_WITH_COPY;
4430 /* It's a permanent file, so we should copy it, and not remove the
4432 how_to_save = SAVE_WITH_COPY;
4435 if (how_to_save == SAVE_WITH_COPY) {
4436 /* Copy the file, if we haven't moved it. If we're overwriting
4437 an existing file, we do it with a "safe save", by writing
4438 to a new file and, if the write succeeds, renaming the
4439 new file on top of the old file. */
4440 if (file_exists(fname)) {
4441 fname_new = g_strdup_printf("%s~", fname);
4442 if (!copy_file_binary_mode(cf->filename, fname_new))
4445 if (!copy_file_binary_mode(cf->filename, fname))
4450 /* Either we're saving in a different format or we're saving changes,
4451 such as added, modified, or removed comments, that haven't yet
4452 been written to the underlying file; we can't do that by copying
4453 or moving the capture file, we have to do it by writing the packets
4456 wtap_dump_params params;
4459 /* XXX: what free's params.shb_hdr? */
4460 wtap_dump_params_init(¶ms, cf->provider.wth);
4462 /* Determine what file encapsulation type we should use. */
4463 encap = wtap_dump_file_encap_type(cf->linktypes);
4464 params.encap = encap;
4466 /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */
4467 params.snaplen = cf->snap;
4469 if (file_exists(fname)) {
4470 /* We're overwriting an existing file; write out to a new file,
4471 and, if that succeeds, rename the new file on top of the
4472 old file. That makes this a "safe save", so that we don't
4473 lose the old file if we have a problem writing out the new
4474 file. (If the existing file is the current capture file,
4475 we *HAVE* to do that, otherwise we're overwriting the file
4476 from which we're reading the packets that we're writing!) */
4477 fname_new = g_strdup_printf("%s~", fname);
4478 pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms,
4481 pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, &err);
4483 /* XXX idb_inf is documented to be used until wtap_dump_close. */
4484 g_free(params.idb_inf);
4485 params.idb_inf = NULL;
4488 cfile_dump_open_failure_alert_box(fname, err, save_format);
4492 /* Add address resolution */
4493 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4495 /* Iterate through the list of packets, processing all the packets. */
4496 callback_args.pdh = pdh;
4497 callback_args.fname = fname;
4498 callback_args.file_type = save_format;
4499 switch (process_specified_records(cf, NULL, "Saving", "packets",
4500 TRUE, save_record, &callback_args, TRUE)) {
4503 /* Completed successfully. */
4507 /* The user decided to abort the saving.
4508 If we're writing to a temporary file, remove it.
4509 XXX - should we do so even if we're not writing to a
4511 wtap_dump_close(pdh, &err);
4512 if (fname_new != NULL)
4513 ws_unlink(fname_new);
4514 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4515 return CF_WRITE_ABORTED;
4518 /* Error while saving.
4519 If we're writing to a temporary file, remove it. */
4520 if (fname_new != NULL)
4521 ws_unlink(fname_new);
4522 wtap_dump_close(pdh, &err);
4526 needs_reload = wtap_dump_get_needs_reload(pdh);
4528 if (!wtap_dump_close(pdh, &err)) {
4529 cfile_close_failure_alert_box(fname, err);
4533 how_to_save = SAVE_WITH_WTAP;
4536 if (fname_new != NULL) {
4537 /* We wrote out to fname_new, and should rename it on top of
4538 fname. fname_new is now closed, so that should be possible even
4539 on Windows. However, on Windows, we first need to close whatever
4540 file descriptors we have open for fname. */
4542 wtap_fdclose(cf->provider.wth);
4544 /* Now do the rename. */
4545 if (ws_rename(fname_new, fname) == -1) {
4546 /* Well, the rename failed. */
4547 cf_rename_failure_alert_box(fname, errno);
4549 /* Attempt to reopen the random file descriptor using the
4550 current file's filename. (At this point, the sequential
4551 file descriptor is closed.) */
4552 if (!wtap_fdreopen(cf->provider.wth, cf->filename, &err)) {
4553 /* Oh, well, we're screwed. */
4554 display_basename = g_filename_display_basename(cf->filename);
4555 simple_error_message_box(
4556 file_open_error_message(err, FALSE), display_basename);
4557 g_free(display_basename);
4564 /* If this was a temporary file, and we didn't do the save by doing
4565 a move, so the tempoary file is still around under its old name,
4567 if (cf->is_tempfile && how_to_save != SAVE_WITH_MOVE) {
4568 /* If this fails, there's not much we can do, so just ignore errors. */
4569 ws_unlink(cf->filename);
4572 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4573 cf->unsaved_changes = FALSE;
4576 switch (how_to_save) {
4578 case SAVE_WITH_MOVE:
4579 /* We just moved the file, so the wtap structure refers to the
4580 new file, and all the information other than the filename
4581 and the "is temporary" status applies to the new file; just
4583 g_free(cf->filename);
4584 cf->filename = g_strdup(fname);
4585 cf->is_tempfile = FALSE;
4586 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4589 case SAVE_WITH_COPY:
4590 /* We just copied the file, so all the information other than
4591 the wtap structure, the filename, and the "is temporary"
4592 status applies to the new file; just update that. */
4593 wtap_close(cf->provider.wth);
4594 /* Although we're just "copying" and then opening the copy, it will
4595 try all open_routine readers to open the copy, so we need to
4596 reset the cfile's open_type. */
4597 cf->open_type = WTAP_TYPE_AUTO;
4598 cf->provider.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4599 if (cf->provider.wth == NULL) {
4600 cfile_open_failure_alert_box(fname, err, err_info);
4603 g_free(cf->filename);
4604 cf->filename = g_strdup(fname);
4605 cf->is_tempfile = FALSE;
4607 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4610 case SAVE_WITH_WTAP:
4611 /* Open and read the file we saved to.
4613 XXX - this is somewhat of a waste; we already have the
4614 packets, all this gets us is updated file type information
4615 (which we could just stuff into "cf"), and having the new
4616 file be the one we have opened and from which we're reading
4617 the data, and it means we have to spend time opening and
4618 reading the file, which could be a significant amount of
4619 time if the file is large.
4621 If the capture-file-writing code were to return the
4622 seek offset of each packet it writes, we could save that
4623 in the frame_data structure for the frame, and just open
4624 the file without reading it again...
4626 ...as long as, for gzipped files, the process of writing
4627 out the file *also* generates the information needed to
4628 support fast random access to the compressed file. */
4629 /* rescan_file will cause us to try all open_routines, so
4630 reset cfile's open_type */
4631 cf->open_type = WTAP_TYPE_AUTO;
4632 /* There are cases when SAVE_WITH_WTAP can result in new packets
4633 being written to the file, e.g ERF records
4634 In that case, we need to reload the whole file */
4636 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4637 if (cf_read(cf, TRUE) != CF_READ_OK) {
4638 /* The rescan failed; just close the file. Either
4639 a dialog was popped up for the failure, so the
4640 user knows what happened, or they stopped the
4641 rescan, in which case they know what happened. */
4642 /* XXX: This is inconsistent with normal open/reload behaviour. */
4648 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4649 /* The rescan failed; just close the file. Either
4650 a dialog was popped up for the failure, so the
4651 user knows what happened, or they stopped the
4652 rescan, in which case they know what happened. */
4659 /* If we were told to discard the comments, do so. */
4660 if (discard_comments) {
4661 /* Remove SHB comment, if any. */
4662 wtap_write_shb_comment(cf->provider.wth, NULL);
4664 /* remove all user comments */
4665 for (framenum = 1; framenum <= cf->count; framenum++) {
4666 fdata = frame_data_sequence_find(cf->provider.frames, framenum);
4668 fdata->has_phdr_comment = FALSE;
4669 fdata->has_user_comment = FALSE;
4672 if (cf->provider.frames_user_comments) {
4673 g_tree_destroy(cf->provider.frames_user_comments);
4674 cf->provider.frames_user_comments = NULL;
4677 cf->packet_comment_count = 0;
4683 if (fname_new != NULL) {
4684 /* We were trying to write to a temporary file; get rid of it if it
4685 exists. (We don't care whether this fails, as, if it fails,
4686 there's not much we can do about it. I guess if it failed for
4687 a reason other than "it doesn't exist", we could report an
4688 error, so the user knows there's a junk file that they might
4689 want to clean up.) */
4690 ws_unlink(fname_new);
4693 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4694 return CF_WRITE_ERROR;
4698 cf_export_specified_packets(capture_file *cf, const char *fname,
4699 packet_range_t *range, guint save_format,
4700 wtap_compression_type compression_type)
4702 gchar *fname_new = NULL;
4705 save_callback_args_t callback_args;
4706 wtap_dump_params params;
4709 packet_range_process_init(range);
4711 /* We're writing out specified packets from the specified capture
4712 file to another file. Even if all captured packets are to be
4713 written, don't special-case the operation - read each packet
4714 and then write it out if it's one of the specified ones. */
4716 /* XXX: what free's params.shb_hdr? */
4717 wtap_dump_params_init(¶ms, cf->provider.wth);
4719 /* Determine what file encapsulation type we should use. */
4720 encap = wtap_dump_file_encap_type(cf->linktypes);
4721 params.encap = encap;
4723 /* Use the snaplen from cf (XXX - does wtap_dump_params_init handle that?) */
4724 params.snaplen = cf->snap;
4726 if (file_exists(fname)) {
4727 /* We're overwriting an existing file; write out to a new file,
4728 and, if that succeeds, rename the new file on top of the
4729 old file. That makes this a "safe save", so that we don't
4730 lose the old file if we have a problem writing out the new
4731 file. (If the existing file is the current capture file,
4732 we *HAVE* to do that, otherwise we're overwriting the file
4733 from which we're reading the packets that we're writing!) */
4734 fname_new = g_strdup_printf("%s~", fname);
4735 pdh = wtap_dump_open(fname_new, save_format, compression_type, ¶ms,
4738 pdh = wtap_dump_open(fname, save_format, compression_type, ¶ms, &err);
4740 /* XXX idb_inf is documented to be used until wtap_dump_close. */
4741 g_free(params.idb_inf);
4742 params.idb_inf = NULL;
4745 cfile_dump_open_failure_alert_box(fname, err, save_format);
4749 /* Add address resolution */
4750 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4752 /* Iterate through the list of packets, processing the packets we were
4755 XXX - we've already called "packet_range_process_init(range)", but
4756 "process_specified_records()" will do it again. Fortunately,
4757 that's harmless in this case, as we haven't done anything to
4758 "range" since we initialized it. */
4759 callback_args.pdh = pdh;
4760 callback_args.fname = fname;
4761 callback_args.file_type = save_format;
4762 switch (process_specified_records(cf, range, "Writing", "specified records",
4763 TRUE, save_record, &callback_args, TRUE)) {
4766 /* Completed successfully. */
4770 /* The user decided to abort the saving.
4771 If we're writing to a temporary file, remove it.
4772 XXX - should we do so even if we're not writing to a
4774 wtap_dump_close(pdh, &err);
4775 if (fname_new != NULL)
4776 ws_unlink(fname_new);
4777 return CF_WRITE_ABORTED;
4781 /* Error while saving.
4782 If we're writing to a temporary file, remove it. */
4783 if (fname_new != NULL)
4784 ws_unlink(fname_new);
4785 wtap_dump_close(pdh, &err);
4789 if (!wtap_dump_close(pdh, &err)) {
4790 cfile_close_failure_alert_box(fname, err);
4794 if (fname_new != NULL) {
4795 /* We wrote out to fname_new, and should rename it on top of
4796 fname; fname is now closed, so that should be possible even
4797 on Windows. Do the rename. */
4798 if (ws_rename(fname_new, fname) == -1) {
4799 /* Well, the rename failed. */
4800 cf_rename_failure_alert_box(fname, errno);
4808 if (fname_new != NULL) {
4809 /* We were trying to write to a temporary file; get rid of it if it
4810 exists. (We don't care whether this fails, as, if it fails,
4811 there's not much we can do about it. I guess if it failed for
4812 a reason other than "it doesn't exist", we could report an
4813 error, so the user knows there's a junk file that they might
4814 want to clean up.) */
4815 ws_unlink(fname_new);
4818 return CF_WRITE_ERROR;
4822 * XXX - whether we mention the source pathname, the target pathname,
4823 * or both depends on the error and on what we find if we look for
4824 * one or both of them.
4827 cf_rename_failure_alert_box(const char *filename, int err)
4829 gchar *display_basename;
4831 display_basename = g_filename_display_basename(filename);
4835 /* XXX - should check whether the source exists and, if not,
4836 report it as the problem and, if so, report the destination
4838 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4843 /* XXX - if we're doing a rename after a safe save, we should
4844 probably say something else. */
4845 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4850 /* XXX - this should probably mention both the source and destination
4852 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4853 display_basename, wtap_strerror(err));
4856 g_free(display_basename);
4859 /* Reload the current capture file. */
4861 cf_reload(capture_file *cf) {
4863 gboolean is_tempfile;
4866 if (cf->read_lock) {
4867 g_warning("Failing cf_reload(\"%s\") since a read is in progress", cf->filename);
4871 /* If the file could be opened, "cf_open()" calls "cf_close()"
4872 to get rid of state for the old capture file before filling in state
4873 for the new capture file. "cf_close()" will remove the file if
4874 it's a temporary file; we don't want that to happen (for one thing,
4875 it'd prevent subsequent reopens from working). Remember whether it's
4876 a temporary file, mark it as not being a temporary file, and then
4877 reopen it as the type of file it was.
4879 Also, "cf_close()" will free "cf->filename", so we must make
4880 a copy of it first. */
4881 filename = g_strdup(cf->filename);
4882 is_tempfile = cf->is_tempfile;
4883 cf->is_tempfile = FALSE;
4884 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4885 switch (cf_read(cf, TRUE)) {
4889 /* Just because we got an error, that doesn't mean we were unable
4890 to read any of the file; we handle what we could get from the
4894 case CF_READ_ABORTED:
4895 /* The user bailed out of re-reading the capture file; the
4896 capture file has been closed - just free the capture file name
4897 string and return (without changing the last containing
4903 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4904 Instead, the file was left open, so we should restore "cf->is_tempfile"
4907 XXX - change the menu? Presumably "cf_open()" will do that;
4908 make sure it does! */
4909 cf->is_tempfile = is_tempfile;
4911 /* "cf_open()" made a copy of the file name we handed it, so
4912 we should free up our copy. */
4922 * indent-tabs-mode: nil
4925 * ex: set shiftwidth=2 tabstop=8 expandtab:
4926 * :indentSize=2:tabSize=8:noTabs=true: