4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0+
21 #include <wsutil/tempfile.h>
22 #include <wsutil/file_util.h>
23 #include <wsutil/filesystem.h>
24 #include <version_info.h>
26 #include <wiretap/merge.h>
28 #include <epan/exceptions.h>
29 #include <epan/epan-int.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>
49 #include "frame_tvbuff.h"
51 #include "ui/alert_box.h"
52 #include "ui/simple_dialog.h"
53 #include "ui/main_statusbar.h"
54 #include "ui/progress_dlg.h"
55 #include "ui/ws_ui_util.h"
57 /* Needed for addrinfo */
58 #ifdef HAVE_SYS_TYPES_H
59 # include <sys/types.h>
62 #ifdef HAVE_SYS_SOCKET_H
63 #include <sys/socket.h>
66 #ifdef HAVE_NETINET_IN_H
67 # include <netinet/in.h>
71 # include <winsock2.h>
72 # include <ws2tcpip.h>
76 gboolean auto_scroll_live; /* GTK+ only? */
79 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
80 column_info *cinfo, gint64 offset);
82 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
89 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
91 static void match_subtree_text(proto_node *node, gpointer data);
92 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
94 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
96 static match_result match_narrow(capture_file *cf, frame_data *fdata,
98 static match_result match_wide(capture_file *cf, frame_data *fdata,
100 static match_result match_binary(capture_file *cf, frame_data *fdata,
102 static match_result match_regex(capture_file *cf, frame_data *fdata,
104 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
106 static match_result match_marked(capture_file *cf, frame_data *fdata,
108 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
110 static gboolean find_packet(capture_file *cf,
111 match_result (*match_function)(capture_file *, frame_data *, void *),
112 void *criterion, search_direction dir);
114 static const char *cf_get_user_packet_comment(frame_set *fs, const frame_data *fd);
116 static void cf_rename_failure_alert_box(const char *filename, int err);
117 static void ref_time_packets(capture_file *cf);
119 /* Seconds spent processing packets between pushing UI updates. */
120 #define PROGBAR_UPDATE_INTERVAL 0.150
122 /* Show the progress bar after this many seconds. */
123 #define PROGBAR_SHOW_DELAY 0.5
126 * We could probably use g_signal_...() instead of the callbacks below but that
127 * would require linking our CLI programs to libgobject and creating an object
128 * instance for the signals.
131 cf_callback_t cb_fct;
133 } cf_callback_data_t;
135 static GList *cf_callbacks = NULL;
138 cf_callback_invoke(int event, gpointer data)
140 cf_callback_data_t *cb;
141 GList *cb_item = cf_callbacks;
143 /* there should be at least one interested */
144 g_assert(cb_item != NULL);
146 while (cb_item != NULL) {
147 cb = (cf_callback_data_t *)cb_item->data;
148 cb->cb_fct(event, data, cb->user_data);
149 cb_item = g_list_next(cb_item);
155 cf_callback_add(cf_callback_t func, gpointer user_data)
157 cf_callback_data_t *cb;
159 cb = g_new(cf_callback_data_t,1);
161 cb->user_data = user_data;
163 cf_callbacks = g_list_prepend(cf_callbacks, cb);
167 cf_callback_remove(cf_callback_t func, gpointer user_data)
169 cf_callback_data_t *cb;
170 GList *cb_item = cf_callbacks;
172 while (cb_item != NULL) {
173 cb = (cf_callback_data_t *)cb_item->data;
174 if (cb->cb_fct == func && cb->user_data == user_data) {
175 cf_callbacks = g_list_remove(cf_callbacks, cb);
179 cb_item = g_list_next(cb_item);
182 g_assert_not_reached();
186 cf_timestamp_auto_precision(capture_file *cf)
190 /* don't try to get the file's precision if none is opened */
191 if (cf->state == FILE_CLOSED) {
195 /* Set the column widths of those columns that show the time in
196 "command-line-specified" format. */
197 for (i = 0; i < cf->cinfo.num_cols; i++) {
198 if (col_has_time_fmt(&cf->cinfo, i)) {
199 packet_list_resize_column(i);
205 cf_get_computed_elapsed(capture_file *cf)
207 return cf->computed_elapsed;
211 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
214 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
219 g_get_current_time(&time_now);
221 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
222 time_now.tv_usec - start_time->tv_usec;
224 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
227 static const nstime_t *
228 ws_get_frame_ts(frame_set *fs, guint32 frame_num)
230 if (fs->prev_dis && fs->prev_dis->num == frame_num)
231 return &fs->prev_dis->abs_ts;
233 if (fs->prev_cap && fs->prev_cap->num == frame_num)
234 return &fs->prev_cap->abs_ts;
237 frame_data *fd = frame_data_sequence_find(fs->frames, frame_num);
239 return (fd) ? &fd->abs_ts : NULL;
246 ws_get_user_comment(frame_set *fs, const frame_data *fd)
248 return cf_get_user_packet_comment(fs, fd);
252 ws_epan_new(capture_file *cf)
254 epan_t *epan = epan_new();
256 epan->fs = &cf->frame_set_info;
257 epan->get_frame_ts = ws_get_frame_ts;
258 epan->get_interface_name = frame_set_get_interface_name;
259 epan->get_interface_description = frame_set_get_interface_description;
260 epan->get_user_comment = ws_get_user_comment;
266 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
271 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
275 /* The open succeeded. Close whatever capture file we had open,
276 and fill in the information for this file. */
279 /* Initialize the packet header. */
280 wtap_phdr_init(&cf->phdr);
282 /* XXX - we really want to initialize this after we've read all
283 the packets, so we know how much we'll ultimately need. */
284 ws_buffer_init(&cf->buf, 1500);
286 /* Create new epan session for dissection.
287 * (The old one was freed in cf_close().)
289 cf->epan = ws_epan_new(cf);
291 /* We're about to start reading the file. */
292 cf->state = FILE_READ_IN_PROGRESS;
294 cf->frame_set_info.wth = wth;
297 /* Set the file name because we need it to set the follow stream filter.
298 XXX - is that still true? We need it for other reasons, though,
300 cf->filename = g_strdup(fname);
302 /* Indicate whether it's a permanent or temporary file. */
303 cf->is_tempfile = is_tempfile;
305 /* No user changes yet. */
306 cf->unsaved_changes = FALSE;
308 cf->computed_elapsed = 0;
310 cf->cd_t = wtap_file_type_subtype(cf->frame_set_info.wth);
311 cf->open_type = type;
312 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
314 cf->packet_comment_count = 0;
315 cf->displayed_count = 0;
316 cf->marked_count = 0;
317 cf->ignored_count = 0;
318 cf->ref_time_count = 0;
319 cf->drops_known = FALSE;
321 cf->snap = wtap_snapshot_length(cf->frame_set_info.wth);
323 /* Allocate a frame_data_sequence for the frames in this file */
324 cf->frame_set_info.frames = new_frame_data_sequence();
326 nstime_set_zero(&cf->elapsed_time);
327 cf->frame_set_info.ref = NULL;
328 cf->frame_set_info.prev_dis = NULL;
329 cf->frame_set_info.prev_cap = NULL;
332 packet_list_queue_draw();
333 cf_callback_invoke(cf_cb_file_opened, cf);
335 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
336 /* tell the BER dissector the file name */
337 ber_set_filename(cf->filename);
340 wtap_set_cb_new_ipv4(cf->frame_set_info.wth, add_ipv4_name);
341 wtap_set_cb_new_ipv6(cf->frame_set_info.wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
346 cfile_open_failure_alert_box(fname, *err, err_info);
351 * Add an encapsulation type to cf->linktypes.
354 cf_add_encapsulation_type(capture_file *cf, int encap)
358 for (i = 0; i < cf->linktypes->len; i++) {
359 if (g_array_index(cf->linktypes, gint, i) == encap)
360 return; /* it's already there */
362 /* It's not already there - add it. */
363 g_array_append_val(cf->linktypes, encap);
366 /* Reset everything to a pristine state */
368 cf_close(capture_file *cf)
370 cf->stop_flag = FALSE;
371 if (cf->state == FILE_CLOSED)
372 return; /* Nothing to do */
374 /* Die if we're in the middle of reading a file. */
375 g_assert(cf->state != FILE_READ_IN_PROGRESS);
377 cf_callback_invoke(cf_cb_file_closing, cf);
379 /* close things, if not already closed before */
380 color_filters_cleanup();
382 if (cf->frame_set_info.wth) {
383 wtap_close(cf->frame_set_info.wth);
384 cf->frame_set_info.wth = NULL;
386 /* We have no file open... */
387 if (cf->filename != NULL) {
388 /* If it's a temporary file, remove it. */
390 ws_unlink(cf->filename);
391 g_free(cf->filename);
394 /* ...which means we have no changes to that file to save. */
395 cf->unsaved_changes = FALSE;
397 /* no open_routine type */
398 cf->open_type = WTAP_TYPE_AUTO;
400 /* Clean up the packet header. */
401 wtap_phdr_cleanup(&cf->phdr);
403 /* Free up the packet buffer. */
404 ws_buffer_free(&cf->buf);
406 dfilter_free(cf->rfcode);
408 if (cf->frame_set_info.frames != NULL) {
409 free_frame_data_sequence(cf->frame_set_info.frames);
410 cf->frame_set_info.frames = NULL;
412 if (cf->frame_set_info.frames_user_comments) {
413 g_tree_destroy(cf->frame_set_info.frames_user_comments);
414 cf->frame_set_info.frames_user_comments = NULL;
416 cf_unselect_packet(cf); /* nothing to select */
417 cf->first_displayed = 0;
418 cf->last_displayed = 0;
420 /* No frames, no frame selected, no field in that frame selected. */
422 cf->current_frame = 0;
424 cf->finfo_selected = NULL;
426 /* No frame link-layer types, either. */
427 if (cf->linktypes != NULL) {
428 g_array_free(cf->linktypes, TRUE);
429 cf->linktypes = NULL;
432 /* Clear the packet list. */
433 packet_list_freeze();
438 nstime_set_zero(&cf->elapsed_time);
440 reset_tap_listeners();
445 /* We have no file open. */
446 cf->state = FILE_CLOSED;
448 cf_callback_invoke(cf_cb_file_closed, cf);
452 * TRUE if the progress dialog doesn't exist and it looks like we'll
453 * take > 2s to load, FALSE otherwise.
455 static inline gboolean
456 progress_is_slow(progdlg_t *progdlg, GTimer *prog_timer, gint64 size, gint64 pos)
460 if (progdlg) return FALSE;
461 elapsed = g_timer_elapsed(prog_timer, NULL);
462 if ((elapsed / 2 > PROGBAR_SHOW_DELAY && (size / pos) > 2) /* It looks like we're going to be slow. */
463 || elapsed > PROGBAR_SHOW_DELAY) { /* We are indeed slow. */
470 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
474 progbar_val = (gfloat) file_pos / (gfloat) size;
475 if (progbar_val > 1.0) {
477 /* The file probably grew while we were reading it.
478 * Update file size, and try again.
480 size = wtap_file_size(cf->frame_set_info.wth, NULL);
483 progbar_val = (gfloat) file_pos / (gfloat) size;
485 /* If it's still > 1, either "wtap_file_size()" failed (in which
486 * case there's not much we can do about it), or the file
487 * *shrank* (in which case there's not much we can do about
488 * it); just clip the progress value at 1.0.
490 if (progbar_val > 1.0f)
494 g_snprintf(status_str, status_size,
495 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
496 file_pos / 1024, size / 1024);
502 cf_read(capture_file *cf, gboolean reloading)
505 gchar *err_info = NULL;
507 progdlg_t *volatile progbar = NULL;
508 GTimer *prog_timer = g_timer_new();
512 volatile gboolean create_proto_tree;
515 volatile gboolean is_read_aborted = FALSE;
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 whether the file is compressed.
554 XXX - do we know this at open time? */
555 cf->iscompressed = wtap_iscompressed(cf->frame_set_info.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->frame_set_info.wth, NULL);
583 g_timer_start(prog_timer);
585 while ((wtap_read(cf->frame_set_info.wth, &err, &err_info, &data_offset))) {
588 file_pos = wtap_read_so_far(cf->frame_set_info.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);
618 if (cf->state == FILE_READ_ABORTED) {
619 /* Well, the user decided to exit Wireshark. Break out of the
620 loop, and let the code below (which is called even if there
621 aren't any packets left to read) exit. */
622 is_read_aborted = TRUE;
626 /* Well, the user decided to abort the read. He/She will be warned and
627 it might be enough for him/her to work with the already loaded
629 This is especially true for very large capture files, where you don't
630 want to wait loading the whole file (which may last minutes or even
631 hours even on fast machines) just to see that it was the wrong file. */
634 read_packet(cf, dfcode, &edt, cinfo, data_offset);
637 CATCH(OutOfMemoryError) {
638 simple_message_box(ESD_TYPE_ERROR, NULL,
639 "More information and workarounds can be found at\n"
640 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
641 "Sorry, but Wireshark has run out of memory and has to terminate now.");
643 /* Could we close the current capture and free up memory from that? */
645 /* we have to terminate, as we cannot recover from the memory error */
651 /* Free the display name */
654 /* Cleanup and release all dfilter resources */
655 dfilter_free(dfcode);
657 epan_dissect_cleanup(&edt);
659 /* We're done reading the file; destroy the progress bar if it was created. */
661 destroy_progress_dlg(progbar);
662 g_timer_destroy(prog_timer);
664 /* We're done reading sequentially through the file. */
665 cf->state = FILE_READ_DONE;
667 /* Close the sequential I/O side, to free up memory it requires. */
668 wtap_sequential_close(cf->frame_set_info.wth);
670 /* Allow the protocol dissectors to free up memory that they
671 * don't need after the sequential run-through of the packets. */
672 postseq_cleanup_all_protocols();
674 /* compute the time it took to load the file */
675 compute_elapsed(cf, &start_time);
677 /* Set the file encapsulation type now; we don't know what it is until
678 we've looked at all the packets, as we don't know until then whether
679 there's more than one type (and thus whether it's
680 WTAP_ENCAP_PER_PACKET). */
681 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
683 cf->current_frame = frame_data_sequence_find(cf->frame_set_info.frames, cf->first_displayed);
688 cf_callback_invoke(cf_cb_file_reload_finished, cf);
690 cf_callback_invoke(cf_cb_file_read_finished, cf);
692 /* If we have any displayed packets to select, select the first of those
693 packets by making the first row the selected row. */
694 if (cf->first_displayed != 0) {
695 packet_list_select_first_row();
698 if (is_read_aborted) {
700 * Well, the user decided to exit Wireshark while reading this *offline*
701 * capture file (Live captures are handled by something like
702 * cf_continue_tail). Clean up accordingly.
705 return CF_READ_ABORTED;
709 simple_message_box(ESD_TYPE_WARN, NULL,
710 "The remaining packets in the file were discarded.\n"
712 "As a lot of packets from the original file will be missing,\n"
713 "remember to be careful when saving the current content to a file.\n",
714 "File loading was cancelled.");
715 return CF_READ_ERROR;
719 /* Put up a message box noting that the read failed somewhere along
720 the line. Don't throw out the stuff we managed to read, though,
722 cfile_read_failure_alert_box(NULL, err, err_info);
723 return CF_READ_ERROR;
730 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
733 volatile int newly_displayed_packets = 0;
736 gboolean create_proto_tree;
740 /* Compile the current display filter.
741 * We assume this will not fail since cf->dfilter is only set in
742 * cf_filter IFF the filter was valid.
744 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
745 g_assert(!cf->dfilter || (compiled && dfcode));
747 /* Get the union of the flags for all tap listeners. */
748 tap_flags = union_of_tap_listener_flags();
751 * Determine whether we need to create a protocol tree.
754 * we're going to apply a display filter;
756 * one of the tap listeners is going to apply a filter;
758 * one of the tap listeners requires a protocol tree;
760 * a postdissector wants field values or protocols on
764 (dfcode != NULL || have_filtering_tap_listeners() ||
765 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
769 packet_list_check_end();
770 /* Don't freeze/thaw the list when doing live capture */
771 /*packet_list_freeze();*/
773 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
775 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
778 gint64 data_offset = 0;
781 /* If any tap listeners require the columns, construct them. */
782 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
784 while (to_read != 0) {
785 wtap_cleareof(cf->frame_set_info.wth);
786 if (!wtap_read(cf->frame_set_info.wth, err, &err_info, &data_offset)) {
789 if (cf->state == FILE_READ_ABORTED) {
790 /* Well, the user decided to exit Wireshark. Break out of the
791 loop, and let the code below (which is called even if there
792 aren't any packets left to read) exit. */
795 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
796 newly_displayed_packets++;
801 CATCH(OutOfMemoryError) {
802 simple_message_box(ESD_TYPE_ERROR, NULL,
803 "More information and workarounds can be found at\n"
804 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
805 "Sorry, but Wireshark has run out of memory and has to terminate now.");
807 /* Could we close the current capture and free up memory from that? */
808 return CF_READ_ABORTED;
810 /* we have to terminate, as we cannot recover from the memory error */
816 /* Update the file encapsulation; it might have changed based on the
817 packets we've read. */
818 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
820 /* Cleanup and release all dfilter resources */
821 dfilter_free(dfcode);
823 epan_dissect_cleanup(&edt);
825 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
826 cf->count, cf->state, *err);*/
828 /* Don't freeze/thaw the list when doing live capture */
829 /*packet_list_thaw();*/
830 /* With the new packet list the first packet
831 * isn't automatically selected.
833 if (!cf->current_frame)
834 packet_list_select_first_row();
836 /* moving to the end of the packet list - if the user requested so and
837 we have some new packets. */
838 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
839 packet_list_moveto_end();
841 if (cf->state == FILE_READ_ABORTED) {
842 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
843 so that our caller can kill off the capture child process;
844 this will cause an EOF on the pipe from the child, so
845 "cf_finish_tail()" will be called, and it will clean up
847 return CF_READ_ABORTED;
848 } else if (*err != 0) {
849 /* We got an error reading the capture file.
850 XXX - pop up a dialog box instead? */
851 if (err_info != NULL) {
852 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
853 wtap_strerror(*err), cf->filename, err_info);
856 g_warning("Error \"%s\" while reading \"%s\"",
857 wtap_strerror(*err), cf->filename);
859 return CF_READ_ERROR;
865 cf_fake_continue_tail(capture_file *cf) {
866 cf->state = FILE_READ_DONE;
870 cf_finish_tail(capture_file *cf, int *err)
877 gboolean create_proto_tree;
881 /* Compile the current display filter.
882 * We assume this will not fail since cf->dfilter is only set in
883 * cf_filter IFF the filter was valid.
885 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
886 g_assert(!cf->dfilter || (compiled && dfcode));
888 /* Get the union of the flags for all tap listeners. */
889 tap_flags = union_of_tap_listener_flags();
891 /* If any tap listeners require the columns, construct them. */
892 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
895 * Determine whether we need to create a protocol tree.
898 * we're going to apply a display filter;
900 * one of the tap listeners is going to apply a filter;
902 * one of the tap listeners requires a protocol tree;
904 * a postdissector wants field values or protocols on
908 (dfcode != NULL || have_filtering_tap_listeners() ||
909 (tap_flags & TL_REQUIRES_PROTO_TREE) || postdissectors_want_hfids());
911 if (cf->frame_set_info.wth == NULL) {
913 return CF_READ_ERROR;
916 packet_list_check_end();
917 /* Don't freeze/thaw the list when doing live capture */
918 /*packet_list_freeze();*/
920 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
922 while ((wtap_read(cf->frame_set_info.wth, err, &err_info, &data_offset))) {
923 if (cf->state == FILE_READ_ABORTED) {
924 /* Well, the user decided to abort the read. Break out of the
925 loop, and let the code below (which is called even if there
926 aren't any packets left to read) exit. */
929 read_packet(cf, dfcode, &edt, cinfo, data_offset);
932 /* Cleanup and release all dfilter resources */
933 dfilter_free(dfcode);
935 epan_dissect_cleanup(&edt);
937 /* Don't freeze/thaw the list when doing live capture */
938 /*packet_list_thaw();*/
940 if (cf->state == FILE_READ_ABORTED) {
941 /* Well, the user decided to abort the read. We're only called
942 when the child capture process closes the pipe to us (meaning
943 it's probably exited), so we can just close the capture
944 file; we return CF_READ_ABORTED so our caller can do whatever
945 is appropriate when that happens. */
947 return CF_READ_ABORTED;
950 if (auto_scroll_live && cf->count != 0)
951 packet_list_moveto_end();
953 /* We're done reading sequentially through the file. */
954 cf->state = FILE_READ_DONE;
956 /* We're done reading sequentially through the file; close the
957 sequential I/O side, to free up memory it requires. */
958 wtap_sequential_close(cf->frame_set_info.wth);
960 /* Allow the protocol dissectors to free up memory that they
961 * don't need after the sequential run-through of the packets. */
962 postseq_cleanup_all_protocols();
964 /* Update the file encapsulation; it might have changed based on the
965 packets we've read. */
966 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
968 /* Update the details in the file-set dialog, as the capture file
969 * has likely grown since we first stat-ed it */
970 fileset_update_file(cf->filename);
973 /* We got an error reading the capture file.
974 XXX - pop up a dialog box? */
975 if (err_info != NULL) {
976 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
977 wtap_strerror(*err), cf->filename, err_info);
980 g_warning("Error \"%s\" while reading \"%s\"",
981 wtap_strerror(*err), cf->filename);
983 return CF_READ_ERROR;
988 #endif /* HAVE_LIBPCAP */
991 cf_get_display_name(capture_file *cf)
995 /* Return a name to use in displays */
996 if (!cf->is_tempfile) {
997 /* Get the last component of the file name, and use that. */
999 displayname = g_filename_display_basename(cf->filename);
1001 displayname=g_strdup("(No file)");
1004 /* The file we read is a temporary file from a live capture or
1005 a merge operation; we don't mention its name, but, if it's
1006 from a capture, give the source of the capture. */
1008 displayname = g_strdup(cf->source);
1010 displayname = g_strdup("(Untitled)");
1016 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1022 cf->source = g_strdup(source);
1024 cf->source = g_strdup("");
1028 const gchar *cf_get_tempfile_source(capture_file *cf) {
1036 /* XXX - use a macro instead? */
1038 cf_get_packet_count(capture_file *cf)
1043 /* XXX - use a macro instead? */
1045 cf_is_tempfile(capture_file *cf)
1047 return cf->is_tempfile;
1050 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1052 cf->is_tempfile = is_tempfile;
1056 /* XXX - use a macro instead? */
1057 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1059 cf->drops_known = drops_known;
1062 /* XXX - use a macro instead? */
1063 void cf_set_drops(capture_file *cf, guint32 drops)
1068 /* XXX - use a macro instead? */
1069 gboolean cf_get_drops_known(capture_file *cf)
1071 return cf->drops_known;
1074 /* XXX - use a macro instead? */
1075 guint32 cf_get_drops(capture_file *cf)
1080 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1082 cf->rfcode = rfcode;
1086 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1087 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1088 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1092 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1093 &cf->frame_set_info.ref, cf->frame_set_info.prev_dis);
1094 cf->frame_set_info.prev_cap = fdata;
1096 if (dfcode != NULL) {
1097 epan_dissect_prime_with_dfilter(edt, dfcode);
1100 /* Prepare coloring rules, this ensures that display filter rules containing
1101 * frame.color_rule references are still processed.
1102 * TODO: actually detect that situation or maybe apply other optimizations? */
1103 if (edt->tree && color_filters_used()) {
1104 color_filters_prime_edt(edt);
1105 fdata->flags.need_colorize = 1;
1109 if (!fdata->flags.visited) {
1110 /* This is the first pass, so prime the epan_dissect_t with the
1111 hfids postdissectors want on the first pass. */
1112 prime_epan_dissect_with_postdissector_wanted_hfids(edt);
1115 /* Dissect the frame. */
1116 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1118 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1119 if (dfcode != NULL) {
1120 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1122 if (fdata->flags.passed_dfilter) {
1123 /* This frame passed the display filter but it may depend on other
1124 * (potentially not displayed) frames. Find those frames and mark them
1127 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frame_set_info.frames);
1130 fdata->flags.passed_dfilter = 1;
1132 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1133 cf->displayed_count++;
1135 if (add_to_packet_list) {
1136 /* We fill the needed columns from new_packet_list */
1137 row = packet_list_append(cinfo, fdata);
1140 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1142 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1143 cf->frame_set_info.prev_dis = fdata;
1145 /* If we haven't yet seen the first frame, this is it. */
1146 if (cf->first_displayed == 0)
1147 cf->first_displayed = fdata->num;
1149 /* This is the last frame we've seen so far. */
1150 cf->last_displayed = fdata->num;
1153 epan_dissect_reset(edt);
1157 /* read in a new packet */
1158 /* returns the row of the new packet in the packet list or -1 if not displayed */
1160 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1161 column_info *cinfo, gint64 offset)
1163 struct wtap_pkthdr *phdr = wtap_phdr(cf->frame_set_info.wth);
1164 const guint8 *buf = wtap_buf_ptr(cf->frame_set_info.wth);
1168 gboolean passed = TRUE;
1171 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1172 it's not already there.
1173 XXX - yes, this is O(N), so if every packet had a different
1174 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1175 there are probably going to be a small number of encapsulation types
1177 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1179 /* The frame number of this packet is one more than the count of
1180 frames in the file so far. */
1181 framenum = cf->count + 1;
1183 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1186 epan_dissect_t rf_edt;
1188 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1189 epan_dissect_prime_with_dfilter(&rf_edt, cf->rfcode);
1190 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1191 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1192 epan_dissect_cleanup(&rf_edt);
1196 /* This does a shallow copy of fdlocal, which is good enough. */
1197 fdata = frame_data_sequence_add(cf->frame_set_info.frames, &fdlocal);
1200 if (phdr->opt_comment != NULL)
1201 cf->packet_comment_count++;
1202 cf->f_datalen = offset + fdlocal.cap_len;
1204 if (!cf->redissecting) {
1205 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1206 cinfo, phdr, buf, TRUE);
1214 typedef struct _callback_data_t {
1217 GTimeVal start_time;
1225 merge_callback(merge_event event, int num _U_,
1226 const merge_in_file_t in_files[], const guint in_file_count,
1230 callback_data_t *cb_data = (callback_data_t*) data;
1232 g_assert(cb_data != NULL);
1236 case MERGE_EVENT_INPUT_FILES_OPENED:
1240 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1244 case MERGE_EVENT_READY_TO_MERGE:
1245 /* Get the sum of the sizes of all the files. */
1246 for (i = 0; i < in_file_count; i++)
1247 cb_data->f_len += in_files[i].size;
1249 cb_data->prog_timer = g_timer_new();
1250 g_timer_start(cb_data->prog_timer);
1252 g_get_current_time(&cb_data->start_time);
1255 case MERGE_EVENT_PACKET_WAS_READ:
1257 gint64 data_offset = 0;
1259 /* Get the sum of the data offsets in all of the files. */
1261 for (i = 0; i < in_file_count; i++)
1262 data_offset += in_files[i].data_offset;
1264 /* Create the progress bar if necessary.
1265 We check on every iteration of the loop, so that it takes no
1266 longer than the standard time to create it (otherwise, for a
1267 large file, we might take considerably longer than that standard
1268 time in order to get to the next progress bar step). */
1269 if (cb_data->progbar == NULL) {
1270 cb_data->progbar = delayed_create_progress_dlg(cb_data->pd_window, "Merging", "files",
1271 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1275 * Update the progress bar, but do it only after
1276 * PROGBAR_UPDATE_INTERVAL has elapsed. Calling update_progress_dlg
1277 * and packets_bar_update will likely trigger UI paint events, which
1278 * might take a while depending on the platform and display. Reset
1279 * our timer *after* painting.
1281 if (g_timer_elapsed(cb_data->prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1283 gint64 file_pos = 0;
1284 /* Get the sum of the seek positions in all of the files. */
1285 for (i = 0; i < in_file_count; i++)
1286 file_pos += wtap_read_so_far(in_files[i].wth);
1288 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1289 if (progbar_val > 1.0f) {
1290 /* Some file probably grew while we were reading it.
1291 That "shouldn't happen", so we'll just clip the progress
1296 if (cb_data->progbar != NULL) {
1297 gchar status_str[100];
1298 g_snprintf(status_str, sizeof(status_str),
1299 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1300 file_pos / 1024, cb_data->f_len / 1024);
1301 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1303 g_timer_start(cb_data->prog_timer);
1308 case MERGE_EVENT_DONE:
1309 /* We're done merging the files; destroy the progress bar if it was created. */
1310 if (cb_data->progbar != NULL)
1311 destroy_progress_dlg(cb_data->progbar);
1312 g_timer_destroy(cb_data->prog_timer);
1316 return cb_data->stop_flag;
1322 cf_merge_files_to_tempfile(gpointer pd_window, char **out_filenamep,
1323 int in_file_count, char *const *in_filenames,
1324 int file_type, gboolean do_append)
1327 gchar *err_info = NULL;
1329 guint32 err_framenum;
1330 merge_result status;
1331 merge_progress_callback_t cb;
1332 callback_data_t *cb_data = g_new0(callback_data_t, 1);
1334 /* prepare our callback routine */
1335 cb_data->pd_window = pd_window;
1336 cb.callback_func = merge_callback;
1339 cf_callback_invoke(cf_cb_file_merge_started, NULL);
1341 /* merge the files */
1342 status = merge_files_to_tempfile(out_filenamep, "wireshark", file_type,
1343 (const char *const *) in_filenames,
1344 in_file_count, do_append,
1345 IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1346 "Wireshark", &cb, &err, &err_info,
1347 &err_fileno, &err_framenum);
1355 case MERGE_USER_ABORTED:
1356 /* this isn't really an error, though we will return CF_ERROR later */
1359 case MERGE_ERR_CANT_OPEN_INFILE:
1360 cfile_open_failure_alert_box(in_filenames[err_fileno], err, err_info);
1363 case MERGE_ERR_CANT_OPEN_OUTFILE:
1364 cfile_dump_open_failure_alert_box(*out_filenamep, err, file_type);
1367 case MERGE_ERR_CANT_READ_INFILE:
1368 cfile_read_failure_alert_box(in_filenames[err_fileno], err, err_info);
1371 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1372 simple_error_message_box("Record %u of \"%s\" has an interface ID that does not match any IDB in its file.",
1373 err_framenum, in_filenames[err_fileno]);
1376 case MERGE_ERR_CANT_WRITE_OUTFILE:
1377 cfile_write_failure_alert_box(in_filenames[err_fileno],
1378 *out_filenamep, err, err_info,
1379 err_framenum, file_type);
1382 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1383 cfile_close_failure_alert_box(*out_filenamep, err);
1387 simple_error_message_box("Unknown merge_files error %d", status);
1391 cf_callback_invoke(cf_cb_file_merge_finished, NULL);
1393 if (status != MERGE_OK) {
1394 /* Callers aren't expected to treat an error or an explicit abort
1395 differently - we put up error dialogs ourselves, so they don't
1403 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1405 const char *filter_new = dftext ? dftext : "";
1406 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1409 GTimeVal start_time;
1411 /* if new filter equals old one, do nothing unless told to do so */
1412 if (!force && strcmp(filter_new, filter_old) == 0) {
1418 if (dftext == NULL) {
1419 /* The new filter is an empty filter (i.e., display all packets).
1420 * so leave dfcode==NULL
1424 * We have a filter; make a copy of it (as we'll be saving it),
1425 * and try to compile it.
1427 dftext = g_strdup(dftext);
1428 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1429 /* The attempt failed; report an error. */
1430 simple_message_box(ESD_TYPE_ERROR, NULL,
1431 "See the help for a description of the display filter syntax.",
1432 "\"%s\" isn't a valid display filter: %s",
1440 if (dfcode == NULL) {
1441 /* Yes - free the filter text, and set it to null. */
1447 /* We have a valid filter. Replace the current filter. */
1448 g_free(cf->dfilter);
1449 cf->dfilter = dftext;
1450 g_get_current_time(&start_time);
1453 /* Now rescan the packet list, applying the new filter, but not
1454 throwing away information constructed on a previous pass. */
1455 if (cf->state != FILE_CLOSED) {
1456 if (dftext == NULL) {
1457 rescan_packets(cf, "Resetting", "Filter", FALSE);
1459 rescan_packets(cf, "Filtering", dftext, FALSE);
1463 /* Cleanup and release all dfilter resources */
1464 dfilter_free(dfcode);
1470 cf_reftime_packets(capture_file *cf)
1472 ref_time_packets(cf);
1476 cf_redissect_packets(capture_file *cf)
1478 if (cf->state != FILE_CLOSED) {
1479 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1484 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1485 struct wtap_pkthdr *phdr, Buffer *buf)
1490 if (!wtap_seek_read(cf->frame_set_info.wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1491 cfile_read_failure_alert_box(cf->filename, err, err_info);
1498 cf_read_record(capture_file *cf, frame_data *fdata)
1500 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1503 /* Rescan the list of packets, reconstructing the CList.
1505 "action" describes why we're doing this; it's used in the progress
1508 "action_item" describes what we're doing; it's used in the progress
1511 "redissect" is TRUE if we need to make the dissectors reconstruct
1512 any state information they have (because a preference that affects
1513 some dissector has changed, meaning some dissector might construct
1514 its state differently from the way it was constructed the last time). */
1516 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1518 /* Rescan packets new packet list */
1521 progdlg_t *progbar = NULL;
1522 GTimer *prog_timer = g_timer_new();
1524 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1525 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1526 gboolean selected_frame_seen;
1528 GTimeVal start_time;
1529 gchar status_str[100];
1533 gboolean create_proto_tree;
1535 gboolean add_to_packet_list = FALSE;
1537 guint32 frames_count;
1539 /* Compile the current display filter.
1540 * We assume this will not fail since cf->dfilter is only set in
1541 * cf_filter IFF the filter was valid.
1543 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1544 g_assert(!cf->dfilter || (compiled && dfcode));
1546 /* Get the union of the flags for all tap listeners. */
1547 tap_flags = union_of_tap_listener_flags();
1549 /* If any tap listeners require the columns, construct them. */
1550 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1553 * Determine whether we need to create a protocol tree.
1556 * we're going to apply a display filter;
1558 * one of the tap listeners is going to apply a filter;
1560 * one of the tap listeners requires a protocol tree;
1562 * we're redissecting and a postdissector wants field
1563 * values or protocols on the first pass.
1566 (dfcode != NULL || have_filtering_tap_listeners() ||
1567 (tap_flags & TL_REQUIRES_PROTO_TREE) ||
1568 (redissect && postdissectors_want_hfids()));
1570 reset_tap_listeners();
1571 /* Which frame, if any, is the currently selected frame?
1572 XXX - should the selected frame or the focus frame be the "current"
1573 frame, that frame being the one from which "Find Frame" searches
1575 selected_frame = cf->current_frame;
1577 /* Mark frame num as not found */
1578 selected_frame_num = -1;
1580 /* Freeze the packet list while we redo it, so we don't get any
1581 screen updates while it happens. */
1582 packet_list_freeze();
1585 /* We need to re-initialize all the state information that protocols
1586 keep, because some preference that controls a dissector has changed,
1587 which might cause the state information to be constructed differently
1588 by that dissector. */
1590 /* We might receive new packets while redissecting, and we don't
1591 want to dissect those before their time. */
1592 cf->redissecting = TRUE;
1594 /* 'reset' dissection session */
1595 epan_free(cf->epan);
1596 if (cf->edt && cf->edt->pi.fd) {
1597 /* All pointers in "per frame proto data" for the currently selected
1598 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1599 Free them here to avoid unintended usage in packet_list_clear(). */
1600 frame_data_destroy(cf->edt->pi.fd);
1602 cf->epan = ws_epan_new(cf);
1603 cf->cinfo.epan = cf->epan;
1605 /* A new Lua tap listener may be registered in lua_prime_all_fields()
1606 called via epan_new() / init_dissection() when reloading Lua plugins. */
1607 if (!create_proto_tree && have_filtering_tap_listeners()) {
1608 create_proto_tree = TRUE;
1611 /* We need to redissect the packets so we have to discard our old
1612 * packet list store. */
1613 packet_list_clear();
1614 add_to_packet_list = TRUE;
1617 /* We don't yet know which will be the first and last frames displayed. */
1618 cf->first_displayed = 0;
1619 cf->last_displayed = 0;
1621 /* We currently don't display any packets */
1622 cf->displayed_count = 0;
1624 /* Iterate through the list of frames. Call a routine for each frame
1625 to check whether it should be displayed and, if so, add it to
1626 the display list. */
1627 cf->frame_set_info.ref = NULL;
1628 cf->frame_set_info.prev_dis = NULL;
1629 cf->frame_set_info.prev_cap = NULL;
1632 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1634 g_timer_start(prog_timer);
1635 /* Count of packets at which we've looked. */
1637 /* Progress so far. */
1640 cf->stop_flag = FALSE;
1641 g_get_current_time(&start_time);
1643 /* no previous row yet */
1644 prev_frame_num = -1;
1647 preceding_frame_num = -1;
1648 preceding_frame = NULL;
1649 following_frame_num = -1;
1650 following_frame = NULL;
1652 selected_frame_seen = FALSE;
1654 frames_count = cf->count;
1656 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1658 for (framenum = 1; framenum <= frames_count; framenum++) {
1659 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1661 /* Create the progress bar if necessary.
1662 We check on every iteration of the loop, so that it takes no
1663 longer than the standard time to create it (otherwise, for a
1664 large file, we might take considerably longer than that standard
1665 time in order to get to the next progress bar step). */
1666 if (progbar == NULL)
1667 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1673 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
1674 * has elapsed. Calling update_progress_dlg and packets_bar_update will
1675 * likely trigger UI paint events, which might take a while depending on
1676 * the platform and display. Reset our timer *after* painting.
1678 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
1679 /* let's not divide by zero. I should never be started
1680 * with count == 0, so let's assert that
1682 g_assert(cf->count > 0);
1683 progbar_val = (gfloat) count / frames_count;
1685 if (progbar != NULL) {
1686 g_snprintf(status_str, sizeof(status_str),
1687 "%4u of %u frames", count, frames_count);
1688 update_progress_dlg(progbar, progbar_val, status_str);
1691 g_timer_start(prog_timer);
1694 if (cf->stop_flag) {
1695 /* Well, the user decided to abort the filtering. Just stop.
1697 XXX - go back to the previous filter? Users probably just
1698 want not to wait for a filtering operation to finish;
1699 unless we cancel by having no filter, reverting to the
1700 previous filter will probably be even more expensive than
1701 continuing the filtering, as it involves going back to the
1702 beginning and filtering, and even with no filter we currently
1703 have to re-generate the entire clist, which is also expensive.
1705 I'm not sure what Network Monitor does, but it doesn't appear
1706 to give you an unfiltered display if you cancel. */
1713 /* Since all state for the frame was destroyed, mark the frame
1714 * as not visited, free the GSList referring to the state
1715 * data (the per-frame data itself was freed by
1716 * "init_dissection()"), and null out the GSList pointer. */
1717 frame_data_reset(fdata);
1718 frames_count = cf->count;
1721 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1722 fdata->flags.dependent_of_displayed = 0;
1724 if (!cf_read_record(cf, fdata))
1725 break; /* error reading the frame */
1727 /* If the previous frame is displayed, and we haven't yet seen the
1728 selected frame, remember that frame - it's the closest one we've
1729 yet seen before the selected frame. */
1730 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1731 preceding_frame_num = prev_frame_num;
1732 preceding_frame = prev_frame;
1735 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1737 ws_buffer_start_ptr(&cf->buf),
1738 add_to_packet_list);
1740 /* If this frame is displayed, and this is the first frame we've
1741 seen displayed after the selected frame, remember this frame -
1742 it's the closest one we've yet seen at or after the selected
1744 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1745 following_frame_num = fdata->num;
1746 following_frame = fdata;
1748 if (fdata == selected_frame) {
1749 selected_frame_seen = TRUE;
1750 if (fdata->flags.passed_dfilter)
1751 selected_frame_num = fdata->num;
1754 /* Remember this frame - it'll be the previous frame
1755 on the next pass through the loop. */
1756 prev_frame_num = fdata->num;
1760 epan_dissect_cleanup(&edt);
1762 /* We are done redissecting the packet list. */
1763 cf->redissecting = FALSE;
1766 frames_count = cf->count;
1767 /* Clear out what remains of the visited flags and per-frame data
1770 XXX - that may cause various forms of bogosity when dissecting
1771 these frames, as they won't have been seen by this sequential
1772 pass, but the only alternative I see is to keep scanning them
1773 even though the user requested that the scan stop, and that
1774 would leave the user stuck with an Wireshark grinding on
1775 until it finishes. Should we just stick them with that? */
1776 for (; framenum <= frames_count; framenum++) {
1777 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1778 frame_data_reset(fdata);
1782 /* We're done filtering the packets; destroy the progress bar if it
1784 if (progbar != NULL)
1785 destroy_progress_dlg(progbar);
1786 g_timer_destroy(prog_timer);
1788 /* Unfreeze the packet list. */
1789 if (!add_to_packet_list)
1790 packet_list_recreate_visible_rows();
1792 /* Compute the time it took to filter the file */
1793 compute_elapsed(cf, &start_time);
1797 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1799 if (selected_frame_num == -1) {
1800 /* The selected frame didn't pass the filter. */
1801 if (selected_frame == NULL) {
1802 /* That's because there *was* no selected frame. Make the first
1803 displayed frame the current frame. */
1804 selected_frame_num = 0;
1806 /* Find the nearest displayed frame to the selected frame (whether
1807 it's before or after that frame) and make that the current frame.
1808 If the next and previous displayed frames are equidistant from the
1809 selected frame, choose the next one. */
1810 g_assert(following_frame == NULL ||
1811 following_frame->num >= selected_frame->num);
1812 g_assert(preceding_frame == NULL ||
1813 preceding_frame->num <= selected_frame->num);
1814 if (following_frame == NULL) {
1815 /* No frame after the selected frame passed the filter, so we
1816 have to select the last displayed frame before the selected
1818 selected_frame_num = preceding_frame_num;
1819 selected_frame = preceding_frame;
1820 } else if (preceding_frame == NULL) {
1821 /* No frame before the selected frame passed the filter, so we
1822 have to select the first displayed frame after the selected
1824 selected_frame_num = following_frame_num;
1825 selected_frame = following_frame;
1827 /* Frames before and after the selected frame passed the filter, so
1828 we'll select the previous frame */
1829 selected_frame_num = preceding_frame_num;
1830 selected_frame = preceding_frame;
1835 if (selected_frame_num == -1) {
1836 /* There are no frames displayed at all. */
1837 cf_unselect_packet(cf);
1839 /* Either the frame that was selected passed the filter, or we've
1840 found the nearest displayed frame to that frame. Select it, make
1841 it the focus row, and make it visible. */
1842 /* Set to invalid to force update of packet list and packet details */
1843 cf->current_row = -1;
1844 if (selected_frame_num == 0) {
1845 packet_list_select_first_row();
1847 if (!packet_list_select_row_from_data(selected_frame)) {
1848 /* We didn't find a row corresponding to this frame.
1849 This means that the frame isn't being displayed currently,
1850 so we can't select it. */
1851 simple_message_box(ESD_TYPE_INFO, NULL,
1852 "The capture file is probably not fully dissected.",
1853 "End of capture exceeded.");
1858 /* Cleanup and release all dfilter resources */
1859 dfilter_free(dfcode);
1864 * Scan through all frame data and recalculate the ref time
1865 * without rereading the file.
1866 * XXX - do we need a progres bar or is this fast enough?
1869 ref_time_packets(capture_file *cf)
1875 cf->frame_set_info.ref = NULL;
1876 cf->frame_set_info.prev_dis = NULL;
1879 for (framenum = 1; framenum <= cf->count; framenum++) {
1880 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1882 /* just add some value here until we know if it is being displayed or not */
1883 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1889 /* If we don't have the time stamp of the first packet in the
1890 capture, it's because this is the first packet. Save the time
1891 stamp of this packet as the time stamp of the first packet. */
1892 if (cf->frame_set_info.ref == NULL)
1893 cf->frame_set_info.ref = fdata;
1894 /* if this frames is marked as a reference time frame, reset
1895 firstsec and firstusec to this frame */
1896 if (fdata->flags.ref_time)
1897 cf->frame_set_info.ref = fdata;
1899 /* If we don't have the time stamp of the previous displayed packet,
1900 it's because this is the first displayed packet. Save the time
1901 stamp of this packet as the time stamp of the previous displayed
1903 if (cf->frame_set_info.prev_dis == NULL) {
1904 cf->frame_set_info.prev_dis = fdata;
1907 /* Get the time elapsed between the first packet and this packet. */
1908 fdata->frame_ref_num = (fdata != cf->frame_set_info.ref) ? cf->frame_set_info.ref->num : 0;
1909 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->frame_set_info.ref->abs_ts);
1911 /* If it's greater than the current elapsed time, set the elapsed time
1912 to it (we check for "greater than" so as not to be confused by
1913 time moving backwards). */
1914 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1915 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1916 cf->elapsed_time = rel_ts;
1919 /* If this frame is displayed, get the time elapsed between the
1920 previous displayed packet and this packet. */
1921 if ( fdata->flags.passed_dfilter ) {
1922 fdata->prev_dis_num = cf->frame_set_info.prev_dis->num;
1923 cf->frame_set_info.prev_dis = fdata;
1929 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1930 /* This frame either passed the display filter list or is marked as
1931 a time reference frame. All time reference frames are displayed
1932 even if they don't pass the display filter */
1933 if (fdata->flags.ref_time) {
1934 /* if this was a TIME REF frame we should reset the cum_bytes field */
1935 cf->cum_bytes = fdata->pkt_len;
1936 fdata->cum_bytes = cf->cum_bytes;
1938 /* increase cum_bytes with this packets length */
1939 cf->cum_bytes += fdata->pkt_len;
1952 process_specified_records(capture_file *cf, packet_range_t *range,
1953 const char *string1, const char *string2, gboolean terminate_is_stop,
1954 gboolean (*callback)(capture_file *, frame_data *,
1955 struct wtap_pkthdr *, const guint8 *, void *),
1956 void *callback_args,
1957 gboolean show_progress_bar)
1962 psp_return_t ret = PSP_FINISHED;
1964 progdlg_t *progbar = NULL;
1965 GTimer *prog_timer = g_timer_new();
1968 GTimeVal progbar_start_time;
1969 gchar progbar_status_str[100];
1970 range_process_e process_this;
1971 struct wtap_pkthdr phdr;
1973 wtap_phdr_init(&phdr);
1974 ws_buffer_init(&buf, 1500);
1976 g_timer_start(prog_timer);
1977 /* Count of packets at which we've looked. */
1979 /* Progress so far. */
1982 cf->stop_flag = FALSE;
1983 g_get_current_time(&progbar_start_time);
1986 packet_range_process_init(range);
1988 /* Iterate through all the packets, printing the packets that
1989 were selected by the current display filter. */
1990 for (framenum = 1; framenum <= cf->count; framenum++) {
1991 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
1993 /* Create the progress bar if necessary.
1994 We check on every iteration of the loop, so that it takes no
1995 longer than the standard time to create it (otherwise, for a
1996 large file, we might take considerably longer than that standard
1997 time in order to get to the next progress bar step). */
1998 if (show_progress_bar && progbar == NULL)
1999 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2002 &progbar_start_time,
2006 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
2007 * has elapsed. Calling update_progress_dlg and packets_bar_update will
2008 * likely trigger UI paint events, which might take a while depending on
2009 * the platform and display. Reset our timer *after* painting.
2011 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
2012 /* let's not divide by zero. I should never be started
2013 * with count == 0, so let's assert that
2015 g_assert(cf->count > 0);
2016 progbar_val = (gfloat) progbar_count / cf->count;
2018 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2019 "%4u of %u packets", progbar_count, cf->count);
2020 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2022 g_timer_start(prog_timer);
2025 if (cf->stop_flag) {
2026 /* Well, the user decided to abort the operation. Just stop,
2027 and arrange to return PSP_STOPPED to our caller, so they know
2028 it was stopped explicitly. */
2035 if (range != NULL) {
2036 /* do we have to process this packet? */
2037 process_this = packet_range_process_packet(range, fdata);
2038 if (process_this == range_process_next) {
2039 /* this packet uninteresting, continue with next one */
2041 } else if (process_this == range_processing_finished) {
2042 /* all interesting packets processed, stop the loop */
2047 /* Get the packet */
2048 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2049 /* Attempt to get the packet failed. */
2053 /* Process the packet */
2054 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2055 /* Callback failed. We assume it reported the error appropriately. */
2061 /* We're done printing the packets; destroy the progress bar if
2063 if (progbar != NULL)
2064 destroy_progress_dlg(progbar);
2065 g_timer_destroy(prog_timer);
2067 wtap_phdr_cleanup(&phdr);
2068 ws_buffer_free(&buf);
2076 } retap_callback_args_t;
2079 retap_packet(capture_file *cf, frame_data *fdata,
2080 struct wtap_pkthdr *phdr, const guint8 *pd,
2083 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2085 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2086 epan_dissect_reset(&args->edt);
2092 cf_retap_packets(capture_file *cf)
2094 packet_range_t range;
2095 retap_callback_args_t callback_args;
2096 gboolean create_proto_tree;
2100 /* Presumably the user closed the capture file. */
2102 return CF_READ_ABORTED;
2105 cf_callback_invoke(cf_cb_file_retap_started, cf);
2107 /* Get the union of the flags for all tap listeners. */
2108 tap_flags = union_of_tap_listener_flags();
2110 /* If any tap listeners require the columns, construct them. */
2111 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2114 * Determine whether we need to create a protocol tree.
2117 * one of the tap listeners is going to apply a filter;
2119 * one of the tap listeners requires a protocol tree.
2122 (have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
2124 /* Reset the tap listeners. */
2125 reset_tap_listeners();
2127 epan_dissect_init(&callback_args.edt, cf->epan, create_proto_tree, FALSE);
2129 /* Iterate through the list of packets, dissecting all packets and
2130 re-running the taps. */
2131 packet_range_init(&range, cf);
2132 packet_range_process_init(&range);
2134 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2135 "all packets", TRUE, retap_packet,
2136 &callback_args, TRUE);
2138 epan_dissect_cleanup(&callback_args.edt);
2140 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2144 /* Completed successfully. */
2148 /* Well, the user decided to abort the refiltering.
2149 Return CF_READ_ABORTED so our caller knows they did that. */
2150 return CF_READ_ABORTED;
2153 /* Error while retapping. */
2154 return CF_READ_ERROR;
2157 g_assert_not_reached();
2162 print_args_t *print_args;
2163 gboolean print_header_line;
2164 char *header_line_buf;
2165 int header_line_buf_len;
2166 gboolean print_formfeed;
2167 gboolean print_separator;
2171 int num_visible_cols;
2174 } print_callback_args_t;
2177 print_packet(capture_file *cf, frame_data *fdata,
2178 struct wtap_pkthdr *phdr, const guint8 *pd,
2181 print_callback_args_t *args = (print_callback_args_t *)argsp;
2187 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2188 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2189 col_item_t* col_item;
2191 /* Fill in the column information if we're printing the summary
2193 if (args->print_args->print_summary) {
2194 col_custom_prime_edt(&args->edt, &cf->cinfo);
2195 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2196 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2198 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2200 if (args->print_formfeed) {
2201 if (!new_page(args->print_args->stream))
2204 if (args->print_separator) {
2205 if (!print_line(args->print_args->stream, 0, ""))
2211 * We generate bookmarks, if the output format supports them.
2212 * The name is "__frameN__".
2214 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2216 if (args->print_args->print_summary) {
2217 if (!args->print_args->print_col_headings)
2218 args->print_header_line = FALSE;
2219 if (args->print_header_line) {
2220 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2222 args->print_header_line = FALSE; /* we might not need to print any more */
2224 cp = &args->line_buf[0];
2226 for (i = 0; i < args->num_visible_cols; i++) {
2227 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2228 /* Find the length of the string for this column. */
2229 column_len = (int) strlen(col_item->col_data);
2230 if (args->col_widths[i] > column_len)
2231 column_len = args->col_widths[i];
2233 /* Make sure there's room in the line buffer for the column; if not,
2234 double its length. */
2235 line_len += column_len + 1; /* "+1" for space */
2236 if (line_len > args->line_buf_len) {
2237 cp_off = (int) (cp - args->line_buf);
2238 args->line_buf_len = 2 * line_len;
2239 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2240 cp = args->line_buf + cp_off;
2243 /* Right-justify the packet number column. */
2244 if (col_item->col_fmt == COL_NUMBER)
2245 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2247 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2249 if (i != args->num_visible_cols - 1)
2255 * Generate a bookmark, using the summary line as the title.
2257 if (!print_bookmark(args->print_args->stream, bookmark_name,
2261 if (!print_line(args->print_args->stream, 0, args->line_buf))
2265 * Generate a bookmark, using "Frame N" as the title, as we're not
2266 * printing the summary line.
2268 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2269 if (!print_bookmark(args->print_args->stream, bookmark_name,
2272 } /* if (print_summary) */
2274 if (args->print_args->print_dissections != print_dissections_none) {
2275 if (args->print_args->print_summary) {
2276 /* Separate the summary line from the tree with a blank line. */
2277 if (!print_line(args->print_args->stream, 0, ""))
2281 /* Print the information in that tree. */
2282 if (!proto_tree_print(args->print_args->print_dissections,
2283 args->print_args->print_hex, &args->edt, NULL,
2284 args->print_args->stream))
2287 /* Print a blank line if we print anything after this (aka more than one packet). */
2288 args->print_separator = TRUE;
2290 /* Print a header line if we print any more packet summaries */
2291 if (args->print_args->print_col_headings)
2292 args->print_header_line = TRUE;
2295 if (args->print_args->print_hex) {
2296 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2297 if (!print_line(args->print_args->stream, 0, ""))
2300 /* Print the full packet data as hex. */
2301 if (!print_hex_data(args->print_args->stream, &args->edt))
2304 /* Print a blank line if we print anything after this (aka more than one packet). */
2305 args->print_separator = TRUE;
2307 /* Print a header line if we print any more packet summaries */
2308 if (args->print_args->print_col_headings)
2309 args->print_header_line = TRUE;
2310 } /* if (args->print_args->print_dissections != print_dissections_none) */
2312 epan_dissect_reset(&args->edt);
2314 /* do we want to have a formfeed between each packet from now on? */
2315 if (args->print_args->print_formfeed) {
2316 args->print_formfeed = TRUE;
2322 epan_dissect_reset(&args->edt);
2327 cf_print_packets(capture_file *cf, print_args_t *print_args,
2328 gboolean show_progress_bar)
2330 print_callback_args_t callback_args;
2333 int i, cp_off, column_len, line_len;
2334 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2338 gboolean proto_tree_needed;
2340 callback_args.print_args = print_args;
2341 callback_args.print_header_line = print_args->print_col_headings;
2342 callback_args.header_line_buf = NULL;
2343 callback_args.header_line_buf_len = 256;
2344 callback_args.print_formfeed = FALSE;
2345 callback_args.print_separator = FALSE;
2346 callback_args.line_buf = NULL;
2347 callback_args.line_buf_len = 256;
2348 callback_args.col_widths = NULL;
2349 callback_args.num_visible_cols = 0;
2350 callback_args.visible_cols = NULL;
2352 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2353 destroy_print_stream(print_args->stream);
2354 return CF_PRINT_WRITE_ERROR;
2357 if (print_args->print_summary) {
2358 /* We're printing packet summaries. Allocate the header line buffer
2359 and get the column widths. */
2360 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2362 /* Find the number of visible columns and the last visible column */
2363 for (i = 0; i < prefs.num_cols; i++) {
2365 clp = g_list_nth(prefs.col_list, i);
2366 if (clp == NULL) /* Sanity check, Invalid column requested */
2369 cfmt = (fmt_data *) clp->data;
2370 if (cfmt->visible) {
2372 last_visible_col = i;
2376 /* Find the widths for each of the columns - maximum of the
2377 width of the title and the width of the data - and construct
2378 a buffer with a line containing the column titles. */
2379 callback_args.num_visible_cols = num_visible_col;
2380 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2381 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2382 cp = &callback_args.header_line_buf[0];
2384 visible_col_count = 0;
2385 for (i = 0; i < cf->cinfo.num_cols; i++) {
2387 clp = g_list_nth(prefs.col_list, i);
2388 if (clp == NULL) /* Sanity check, Invalid column requested */
2391 cfmt = (fmt_data *) clp->data;
2392 if (cfmt->visible == FALSE)
2395 /* Save the order of visible columns */
2396 callback_args.visible_cols[visible_col_count] = i;
2398 /* Don't pad the last column. */
2399 if (i == last_visible_col)
2400 callback_args.col_widths[visible_col_count] = 0;
2402 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2403 data_width = get_column_char_width(get_column_format(i));
2404 if (data_width > callback_args.col_widths[visible_col_count])
2405 callback_args.col_widths[visible_col_count] = data_width;
2408 /* Find the length of the string for this column. */
2409 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2410 if (callback_args.col_widths[i] > column_len)
2411 column_len = callback_args.col_widths[visible_col_count];
2413 /* Make sure there's room in the line buffer for the column; if not,
2414 double its length. */
2415 line_len += column_len + 1; /* "+1" for space */
2416 if (line_len > callback_args.header_line_buf_len) {
2417 cp_off = (int) (cp - callback_args.header_line_buf);
2418 callback_args.header_line_buf_len = 2 * line_len;
2419 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2420 callback_args.header_line_buf_len + 1);
2421 cp = callback_args.header_line_buf + cp_off;
2424 /* Right-justify the packet number column. */
2425 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2426 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2428 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2430 if (i != cf->cinfo.num_cols - 1)
2433 visible_col_count++;
2437 /* Now start out the main line buffer with the same length as the
2438 header line buffer. */
2439 callback_args.line_buf_len = callback_args.header_line_buf_len;
2440 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2441 } /* if (print_summary) */
2443 /* Create the protocol tree, and make it visible, if we're printing
2444 the dissection or the hex data.
2445 XXX - do we need it if we're just printing the hex data? */
2447 callback_args.print_args->print_dissections != print_dissections_none ||
2448 callback_args.print_args->print_hex ||
2449 have_custom_cols(&cf->cinfo) || have_field_extractors();
2450 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2452 /* Iterate through the list of packets, printing the packets we were
2454 ret = process_specified_records(cf, &print_args->range, "Printing",
2455 "selected packets", TRUE, print_packet,
2456 &callback_args, show_progress_bar);
2457 epan_dissect_cleanup(&callback_args.edt);
2458 g_free(callback_args.header_line_buf);
2459 g_free(callback_args.line_buf);
2460 g_free(callback_args.col_widths);
2461 g_free(callback_args.visible_cols);
2466 /* Completed successfully. */
2470 /* Well, the user decided to abort the printing.
2472 XXX - note that what got generated before they did that
2473 will get printed if we're piping to a print program; we'd
2474 have to write to a file and then hand that to the print
2475 program to make it actually not print anything. */
2479 /* Error while printing.
2481 XXX - note that what got generated before they did that
2482 will get printed if we're piping to a print program; we'd
2483 have to write to a file and then hand that to the print
2484 program to make it actually not print anything. */
2485 destroy_print_stream(print_args->stream);
2486 return CF_PRINT_WRITE_ERROR;
2489 if (!print_finale(print_args->stream)) {
2490 destroy_print_stream(print_args->stream);
2491 return CF_PRINT_WRITE_ERROR;
2494 if (!destroy_print_stream(print_args->stream))
2495 return CF_PRINT_WRITE_ERROR;
2503 print_args_t *print_args;
2504 } write_packet_callback_args_t;
2507 write_pdml_packet(capture_file *cf, frame_data *fdata,
2508 struct wtap_pkthdr *phdr, const guint8 *pd,
2511 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2513 /* Create the protocol tree, but don't fill in the column information. */
2514 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2516 /* Write out the information in that tree. */
2517 write_pdml_proto_tree(NULL, NULL, PF_NONE, &args->edt, args->fh, FALSE);
2519 epan_dissect_reset(&args->edt);
2521 return !ferror(args->fh);
2525 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2527 write_packet_callback_args_t callback_args;
2531 fh = ws_fopen(print_args->file, "w");
2533 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2535 write_pdml_preamble(fh, cf->filename);
2538 return CF_PRINT_WRITE_ERROR;
2541 callback_args.fh = fh;
2542 callback_args.print_args = print_args;
2543 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2545 /* Iterate through the list of packets, printing the packets we were
2547 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2548 "selected packets", TRUE,
2549 write_pdml_packet, &callback_args, TRUE);
2551 epan_dissect_cleanup(&callback_args.edt);
2556 /* Completed successfully. */
2560 /* Well, the user decided to abort the printing. */
2564 /* Error while printing. */
2566 return CF_PRINT_WRITE_ERROR;
2569 write_pdml_finale(fh);
2572 return CF_PRINT_WRITE_ERROR;
2575 /* XXX - check for an error */
2582 write_psml_packet(capture_file *cf, frame_data *fdata,
2583 struct wtap_pkthdr *phdr, const guint8 *pd,
2586 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2588 /* Fill in the column information */
2589 col_custom_prime_edt(&args->edt, &cf->cinfo);
2590 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2591 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2593 /* Write out the column information. */
2594 write_psml_columns(&args->edt, args->fh, FALSE);
2596 epan_dissect_reset(&args->edt);
2598 return !ferror(args->fh);
2602 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2604 write_packet_callback_args_t callback_args;
2608 gboolean proto_tree_needed;
2610 fh = ws_fopen(print_args->file, "w");
2612 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2614 write_psml_preamble(&cf->cinfo, fh);
2617 return CF_PRINT_WRITE_ERROR;
2620 callback_args.fh = fh;
2621 callback_args.print_args = print_args;
2623 /* Fill in the column information, only create the protocol tree
2624 if having custom columns or field extractors. */
2625 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2626 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2628 /* Iterate through the list of packets, printing the packets we were
2630 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2631 "selected packets", TRUE,
2632 write_psml_packet, &callback_args, TRUE);
2634 epan_dissect_cleanup(&callback_args.edt);
2639 /* Completed successfully. */
2643 /* Well, the user decided to abort the printing. */
2647 /* Error while printing. */
2649 return CF_PRINT_WRITE_ERROR;
2652 write_psml_finale(fh);
2655 return CF_PRINT_WRITE_ERROR;
2658 /* XXX - check for an error */
2665 write_csv_packet(capture_file *cf, frame_data *fdata,
2666 struct wtap_pkthdr *phdr, const guint8 *pd,
2669 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2671 /* Fill in the column information */
2672 col_custom_prime_edt(&args->edt, &cf->cinfo);
2673 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2674 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2676 /* Write out the column information. */
2677 write_csv_columns(&args->edt, args->fh);
2679 epan_dissect_reset(&args->edt);
2681 return !ferror(args->fh);
2685 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2687 write_packet_callback_args_t callback_args;
2688 gboolean proto_tree_needed;
2692 fh = ws_fopen(print_args->file, "w");
2694 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2696 write_csv_column_titles(&cf->cinfo, fh);
2699 return CF_PRINT_WRITE_ERROR;
2702 callback_args.fh = fh;
2703 callback_args.print_args = print_args;
2705 /* only create the protocol tree if having custom columns or field extractors. */
2706 proto_tree_needed = have_custom_cols(&cf->cinfo) || have_field_extractors();
2707 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2709 /* Iterate through the list of packets, printing the packets we were
2711 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2712 "selected packets", TRUE,
2713 write_csv_packet, &callback_args, TRUE);
2715 epan_dissect_cleanup(&callback_args.edt);
2720 /* Completed successfully. */
2724 /* Well, the user decided to abort the printing. */
2728 /* Error while printing. */
2730 return CF_PRINT_WRITE_ERROR;
2733 /* XXX - check for an error */
2740 carrays_write_packet(capture_file *cf, frame_data *fdata,
2741 struct wtap_pkthdr *phdr,
2742 const guint8 *pd, void *argsp)
2744 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2746 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2747 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2748 epan_dissect_reset(&args->edt);
2750 return !ferror(args->fh);
2754 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2756 write_packet_callback_args_t callback_args;
2760 fh = ws_fopen(print_args->file, "w");
2763 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2767 return CF_PRINT_WRITE_ERROR;
2770 callback_args.fh = fh;
2771 callback_args.print_args = print_args;
2772 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2774 /* Iterate through the list of packets, printing the packets we were
2776 ret = process_specified_records(cf, &print_args->range,
2778 "selected packets", TRUE,
2779 carrays_write_packet, &callback_args, TRUE);
2781 epan_dissect_cleanup(&callback_args.edt);
2785 /* Completed successfully. */
2788 /* Well, the user decided to abort the printing. */
2791 /* Error while printing. */
2793 return CF_PRINT_WRITE_ERROR;
2801 write_json_packet(capture_file *cf, frame_data *fdata,
2802 struct wtap_pkthdr *phdr, const guint8 *pd,
2805 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2807 /* Create the protocol tree, but don't fill in the column information. */
2808 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2810 /* Write out the information in that tree. */
2811 write_json_proto_tree(NULL, args->print_args->print_dissections,
2812 args->print_args->print_hex, NULL, PF_NONE,
2813 &args->edt, proto_node_group_children_by_unique, args->fh);
2815 epan_dissect_reset(&args->edt);
2817 return !ferror(args->fh);
2821 cf_write_json_packets(capture_file *cf, print_args_t *print_args)
2823 write_packet_callback_args_t callback_args;
2827 fh = ws_fopen(print_args->file, "w");
2829 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2831 write_json_preamble(fh);
2834 return CF_PRINT_WRITE_ERROR;
2837 callback_args.fh = fh;
2838 callback_args.print_args = print_args;
2839 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2841 /* Iterate through the list of packets, printing the packets we were
2843 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2844 "selected packets", TRUE,
2845 write_json_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 write_json_finale(fh);
2868 return CF_PRINT_WRITE_ERROR;
2871 /* XXX - check for an error */
2878 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2879 search_direction dir)
2883 mdata.string = string;
2884 mdata.string_len = strlen(string);
2885 return find_packet(cf, match_protocol_tree, &mdata, dir);
2889 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2891 mdata->frame_matched = FALSE;
2892 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2893 mdata->string_len = strlen(mdata->string);
2895 /* Iterate through all the nodes looking for matching text */
2896 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2897 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2901 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2903 match_data *mdata = (match_data *)criterion;
2906 /* Load the frame's data. */
2907 if (!cf_read_record(cf, fdata)) {
2908 /* Attempt to get the packet failed. */
2912 /* Construct the protocol tree, including the displayed text */
2913 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2914 /* We don't need the column information */
2915 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2917 /* Iterate through all the nodes, seeing if they have text that matches. */
2919 mdata->frame_matched = FALSE;
2920 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2921 epan_dissect_cleanup(&edt);
2922 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2926 match_subtree_text(proto_node *node, gpointer data)
2928 match_data *mdata = (match_data *) data;
2929 const gchar *string = mdata->string;
2930 size_t string_len = mdata->string_len;
2931 capture_file *cf = mdata->cf;
2932 field_info *fi = PNODE_FINFO(node);
2933 gchar label_str[ITEM_LABEL_LENGTH];
2940 /* dissection with an invisible proto tree? */
2943 if (mdata->frame_matched) {
2944 /* We already had a match; don't bother doing any more work. */
2948 /* Don't match invisible entries. */
2949 if (PROTO_ITEM_IS_HIDDEN(node))
2952 /* was a free format label produced? */
2954 label_ptr = fi->rep->representation;
2956 /* no, make a generic label */
2957 label_ptr = label_str;
2958 proto_item_fill_label(fi, label_str);
2962 if (g_regex_match(cf->regex, label_ptr, (GRegexMatchFlags) 0, NULL)) {
2963 mdata->frame_matched = TRUE;
2968 /* Does that label match? */
2969 label_len = strlen(label_ptr);
2970 for (i = 0; i < label_len; i++) {
2971 c_char = label_ptr[i];
2973 c_char = g_ascii_toupper(c_char);
2974 if (c_char == string[c_match]) {
2976 if (c_match == string_len) {
2977 /* No need to look further; we have a match */
2978 mdata->frame_matched = TRUE;
2987 /* Recurse into the subtree, if it exists */
2988 if (node->first_child != NULL)
2989 proto_tree_children_foreach(node, match_subtree_text, mdata);
2993 cf_find_packet_summary_line(capture_file *cf, const char *string,
2994 search_direction dir)
2998 mdata.string = string;
2999 mdata.string_len = strlen(string);
3000 return find_packet(cf, match_summary_line, &mdata, dir);
3004 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3006 match_data *mdata = (match_data *)criterion;
3007 const gchar *string = mdata->string;
3008 size_t string_len = mdata->string_len;
3010 const char *info_column;
3011 size_t info_column_len;
3012 match_result result = MR_NOTMATCHED;
3018 /* Load the frame's data. */
3019 if (!cf_read_record(cf, fdata)) {
3020 /* Attempt to get the packet failed. */
3024 /* Don't bother constructing the protocol tree */
3025 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3026 /* Get the column information */
3027 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3030 /* Find the Info column */
3031 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3032 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
3033 /* Found it. See if we match. */
3034 info_column = edt.pi.cinfo->columns[colx].col_data;
3035 info_column_len = strlen(info_column);
3037 if (g_regex_match(cf->regex, info_column, (GRegexMatchFlags) 0, NULL)) {
3038 result = MR_MATCHED;
3042 for (i = 0; i < info_column_len; i++) {
3043 c_char = info_column[i];
3045 c_char = g_ascii_toupper(c_char);
3046 if (c_char == string[c_match]) {
3048 if (c_match == string_len) {
3049 result = MR_MATCHED;
3059 epan_dissect_cleanup(&edt);
3066 } cbs_t; /* "Counted byte string" */
3070 * The current match_* routines only support ASCII case insensitivity and don't
3071 * convert UTF-8 inputs to UTF-16 for matching.
3073 * We could modify them to use the GLib Unicode routines or the International
3074 * Components for Unicode library but it's not apparent that we could do so
3075 * without consuming a lot more CPU and memory or that searching would be
3076 * significantly better.
3080 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3081 search_direction dir)
3086 info.data_len = string_size;
3088 /* Regex, String or hex search? */
3090 /* Regular Expression search */
3091 return find_packet(cf, match_regex, NULL, dir);
3092 } else if (cf->string) {
3093 /* String search - what type of string? */
3094 switch (cf->scs_type) {
3096 case SCS_NARROW_AND_WIDE:
3097 return find_packet(cf, match_narrow_and_wide, &info, dir);
3100 return find_packet(cf, match_narrow, &info, dir);
3103 return find_packet(cf, match_wide, &info, dir);
3106 g_assert_not_reached();
3110 return find_packet(cf, match_binary, &info, dir);
3114 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3116 cbs_t *info = (cbs_t *)criterion;
3117 const guint8 *ascii_text = info->data;
3118 size_t textlen = info->data_len;
3119 match_result result;
3126 /* Load the frame's data. */
3127 if (!cf_read_record(cf, fdata)) {
3128 /* Attempt to get the packet failed. */
3132 result = MR_NOTMATCHED;
3133 buf_len = fdata->cap_len;
3134 pd = ws_buffer_start_ptr(&cf->buf);
3136 while (i < buf_len) {
3139 c_char = g_ascii_toupper(c_char);
3140 if (c_char != '\0') {
3141 if (c_char == ascii_text[c_match]) {
3143 if (c_match == textlen) {
3144 result = MR_MATCHED;
3145 cf->search_pos = i; /* Save the position of the last character
3146 for highlighting the field. */
3147 cf->search_len = (guint32)textlen;
3152 g_assert(i>=c_match);
3153 i -= (guint32)c_match;
3163 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3166 cbs_t *info = (cbs_t *)criterion;
3167 const guint8 *ascii_text = info->data;
3168 size_t textlen = info->data_len;
3169 match_result result;
3175 /* Load the frame's data. */
3176 if (!cf_read_record(cf, fdata)) {
3177 /* Attempt to get the packet failed. */
3181 result = MR_NOTMATCHED;
3182 buf_len = fdata->cap_len;
3183 pd = ws_buffer_start_ptr(&cf->buf);
3185 while (i < buf_len) {
3188 c_char = g_ascii_toupper(c_char);
3189 if (c_char == ascii_text[c_match]) {
3191 if (c_match == textlen) {
3192 result = MR_MATCHED;
3193 cf->search_pos = i; /* Save the position of the last character
3194 for highlighting the field. */
3195 cf->search_len = (guint32)textlen;
3200 g_assert(i>=c_match);
3201 i -= (guint32)c_match;
3211 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3213 cbs_t *info = (cbs_t *)criterion;
3214 const guint8 *ascii_text = info->data;
3215 size_t textlen = info->data_len;
3216 match_result result;
3223 /* Load the frame's data. */
3224 if (!cf_read_record(cf, fdata)) {
3225 /* Attempt to get the packet failed. */
3229 result = MR_NOTMATCHED;
3230 buf_len = fdata->cap_len;
3231 pd = ws_buffer_start_ptr(&cf->buf);
3233 while (i < buf_len) {
3236 c_char = g_ascii_toupper(c_char);
3237 if (c_char == ascii_text[c_match]) {
3239 if (c_match == textlen) {
3240 result = MR_MATCHED;
3241 cf->search_pos = i; /* Save the position of the last character
3242 for highlighting the field. */
3243 cf->search_len = (guint32)textlen;
3249 g_assert(i>=(c_match*2));
3250 i -= (guint32)c_match*2;
3259 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3261 cbs_t *info = (cbs_t *)criterion;
3262 const guint8 *binary_data = info->data;
3263 size_t datalen = info->data_len;
3264 match_result result;
3270 /* Load the frame's data. */
3271 if (!cf_read_record(cf, fdata)) {
3272 /* Attempt to get the packet failed. */
3276 result = MR_NOTMATCHED;
3277 buf_len = fdata->cap_len;
3278 pd = ws_buffer_start_ptr(&cf->buf);
3280 while (i < buf_len) {
3281 if (pd[i] == binary_data[c_match]) {
3283 if (c_match == datalen) {
3284 result = MR_MATCHED;
3285 cf->search_pos = i; /* Save the position of the last character
3286 for highlighting the field. */
3287 cf->search_len = (guint32)datalen;
3292 g_assert(i>=c_match);
3293 i -= (guint32)c_match;
3302 match_regex(capture_file *cf, frame_data *fdata, void *criterion _U_)
3304 match_result result = MR_NOTMATCHED;
3305 GMatchInfo *match_info = NULL;
3307 /* Load the frame's data. */
3308 if (!cf_read_record(cf, fdata)) {
3309 /* Attempt to get the packet failed. */
3313 if (g_regex_match_full(cf->regex, (const gchar *)ws_buffer_start_ptr(&cf->buf), fdata->cap_len,
3314 0, (GRegexMatchFlags) 0, &match_info, NULL))
3316 gint start_pos = 0, end_pos = 0;
3317 g_match_info_fetch_pos (match_info, 0, &start_pos, &end_pos);
3318 cf->search_pos = end_pos - 1;
3319 cf->search_len = end_pos - start_pos;
3320 result = MR_MATCHED;
3326 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3327 search_direction dir)
3329 return find_packet(cf, match_dfilter, sfcode, dir);
3333 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3334 search_direction dir)
3339 if (!dfilter_compile(filter, &sfcode, NULL)) {
3341 * XXX - this shouldn't happen, as the filter string is machine
3346 if (sfcode == NULL) {
3348 * XXX - this shouldn't happen, as the filter string is machine
3353 result = find_packet(cf, match_dfilter, sfcode, dir);
3354 dfilter_free(sfcode);
3359 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3361 dfilter_t *sfcode = (dfilter_t *)criterion;
3363 match_result result;
3365 /* Load the frame's data. */
3366 if (!cf_read_record(cf, fdata)) {
3367 /* Attempt to get the packet failed. */
3371 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3372 epan_dissect_prime_with_dfilter(&edt, sfcode);
3373 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3374 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3375 epan_dissect_cleanup(&edt);
3380 cf_find_packet_marked(capture_file *cf, search_direction dir)
3382 return find_packet(cf, match_marked, NULL, dir);
3386 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3388 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3392 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3394 return find_packet(cf, match_time_reference, NULL, dir);
3398 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3400 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3404 find_packet(capture_file *cf,
3405 match_result (*match_function)(capture_file *, frame_data *, void *),
3406 void *criterion, search_direction dir)
3408 frame_data *start_fd;
3411 frame_data *new_fd = NULL;
3412 progdlg_t *progbar = NULL;
3413 GTimer *prog_timer = g_timer_new();
3417 GTimeVal start_time;
3418 gchar status_str[100];
3420 match_result result;
3422 start_fd = cf->current_frame;
3423 if (start_fd != NULL) {
3424 /* Iterate through the list of packets, starting at the packet we've
3425 picked, calling a routine to run the filter on the packet, see if
3426 it matches, and stop if so. */
3428 framenum = start_fd->num;
3430 g_timer_start(prog_timer);
3431 /* Progress so far. */
3434 cf->stop_flag = FALSE;
3435 g_get_current_time(&start_time);
3437 title = cf->sfilter?cf->sfilter:"";
3439 /* Create the progress bar if necessary.
3440 We check on every iteration of the loop, so that it takes no
3441 longer than the standard time to create it (otherwise, for a
3442 large file, we might take considerably longer than that standard
3443 time in order to get to the next progress bar step). */
3444 if (progbar == NULL)
3445 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3446 FALSE, &cf->stop_flag, &start_time, progbar_val);
3449 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
3450 * has elapsed. Calling update_progress_dlg and packets_bar_update will
3451 * likely trigger UI paint events, which might take a while depending on
3452 * the platform and display. Reset our timer *after* painting.
3454 if (g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
3455 /* let's not divide by zero. I should never be started
3456 * with count == 0, so let's assert that
3458 g_assert(cf->count > 0);
3460 progbar_val = (gfloat) count / cf->count;
3462 g_snprintf(status_str, sizeof(status_str),
3463 "%4u of %u packets", count, cf->count);
3464 update_progress_dlg(progbar, progbar_val, status_str);
3466 g_timer_start(prog_timer);
3469 if (cf->stop_flag) {
3470 /* Well, the user decided to abort the search. Go back to the
3471 frame where we started. */
3476 /* Go past the current frame. */
3477 if (dir == SD_BACKWARD) {
3478 /* Go on to the previous frame. */
3479 if (framenum == 1) {
3481 * XXX - other apps have a bit more of a detailed message
3482 * for this, and instead of offering "OK" and "Cancel",
3483 * they offer things such as "Continue" and "Cancel";
3484 * we need an API for popping up alert boxes with
3485 * {Verb} and "Cancel".
3488 if (prefs.gui_find_wrap)
3490 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3491 framenum = cf->count; /* wrap around */
3495 statusbar_push_temporary_msg("Search reached the beginning.");
3496 framenum = start_fd->num; /* stay on previous packet */
3501 /* Go on to the next frame. */
3502 if (framenum == cf->count) {
3503 if (prefs.gui_find_wrap)
3505 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3506 framenum = 1; /* wrap around */
3510 statusbar_push_temporary_msg("Search reached the end.");
3511 framenum = start_fd->num; /* stay on previous packet */
3516 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
3520 /* Is this packet in the display? */
3521 if (fdata->flags.passed_dfilter) {
3522 /* Yes. Does it match the search criterion? */
3523 result = (*match_function)(cf, fdata, criterion);
3524 if (result == MR_ERROR) {
3525 /* Error; our caller has reported the error. Go back to the frame
3526 where we started. */
3529 } else if (result == MR_MATCHED) {
3530 /* Yes. Go to the new frame. */
3536 if (fdata == start_fd) {
3537 /* We're back to the frame we were on originally, and that frame
3538 doesn't match the search filter. The search failed. */
3543 /* We're done scanning the packets; destroy the progress bar if it
3545 if (progbar != NULL)
3546 destroy_progress_dlg(progbar);
3547 g_timer_destroy(prog_timer);
3550 if (new_fd != NULL) {
3551 /* Find and select */
3552 cf->search_in_progress = TRUE;
3553 found = packet_list_select_row_from_data(new_fd);
3554 cf->search_in_progress = FALSE;
3555 cf->search_pos = 0; /* Reset the position */
3556 cf->search_len = 0; /* Reset length */
3558 /* We didn't find a row corresponding to this frame.
3559 This means that the frame isn't being displayed currently,
3560 so we can't select it. */
3561 simple_message_box(ESD_TYPE_INFO, NULL,
3562 "The capture file is probably not fully dissected.",
3563 "End of capture exceeded.");
3566 return TRUE; /* success */
3568 return FALSE; /* failure */
3572 cf_goto_frame(capture_file *cf, guint fnumber)
3576 if (cf == NULL || cf->frame_set_info.frames == NULL) {
3577 /* we don't have a loaded capture file - fix for bugs 11810 & 11989 */
3578 statusbar_push_temporary_msg("There is no file loaded");
3579 return FALSE; /* we failed to go to that packet */
3582 fdata = frame_data_sequence_find(cf->frame_set_info.frames, fnumber);
3584 if (fdata == NULL) {
3585 /* we didn't find a packet with that packet number */
3586 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3587 return FALSE; /* we failed to go to that packet */
3589 if (!fdata->flags.passed_dfilter) {
3590 /* that packet currently isn't displayed */
3591 /* XXX - add it to the set of displayed packets? */
3592 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3593 return FALSE; /* we failed to go to that packet */
3596 if (!packet_list_select_row_from_data(fdata)) {
3597 /* We didn't find a row corresponding to this frame.
3598 This means that the frame isn't being displayed currently,
3599 so we can't select it. */
3600 simple_message_box(ESD_TYPE_INFO, NULL,
3601 "The capture file is probably not fully dissected.",
3602 "End of capture exceeded.");
3605 return TRUE; /* we got to that packet */
3609 * Go to frame specified by currently selected protocol tree item.
3612 cf_goto_framenum(capture_file *cf)
3614 header_field_info *hfinfo;
3617 if (cf->finfo_selected) {
3618 hfinfo = cf->finfo_selected->hfinfo;
3620 if (hfinfo->type == FT_FRAMENUM) {
3621 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3623 return cf_goto_frame(cf, framenum);
3630 /* Select the packet on a given row. */
3632 cf_select_packet(capture_file *cf, int row)
3634 epan_dissect_t *old_edt;
3637 /* Get the frame data struct pointer for this frame */
3638 fdata = packet_list_get_row_data(row);
3640 if (fdata == NULL) {
3644 /* Get the data in that frame. */
3645 if (!cf_read_record (cf, fdata)) {
3649 /* Record that this frame is the current frame. */
3650 cf->current_frame = fdata;
3651 cf->current_row = row;
3654 /* Create the logical protocol tree. */
3655 /* We don't need the columns here. */
3656 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3658 tap_build_interesting(cf->edt);
3659 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3660 cf->current_frame, NULL);
3662 dfilter_macro_build_ftv_cache(cf->edt->tree);
3664 cf_callback_invoke(cf_cb_packet_selected, cf);
3666 if (old_edt != NULL)
3667 epan_dissect_free(old_edt);
3671 /* Unselect the selected packet, if any. */
3673 cf_unselect_packet(capture_file *cf)
3675 epan_dissect_t *old_edt = cf->edt;
3679 /* No packet is selected. */
3680 cf->current_frame = NULL;
3681 cf->current_row = 0;
3683 cf_callback_invoke(cf_cb_packet_unselected, cf);
3685 /* No protocol tree means no selected field. */
3686 cf_unselect_field(cf);
3688 /* Destroy the epan_dissect_t for the unselected packet. */
3689 if (old_edt != NULL)
3690 epan_dissect_free(old_edt);
3693 /* Unset the selected protocol tree field, if any. */
3695 cf_unselect_field(capture_file *cf)
3697 cf->finfo_selected = NULL;
3699 cf_callback_invoke(cf_cb_field_unselected, cf);
3703 * Mark a particular frame.
3706 cf_mark_frame(capture_file *cf, frame_data *frame)
3708 if (! frame->flags.marked) {
3709 frame->flags.marked = TRUE;
3710 if (cf->count > cf->marked_count)
3716 * Unmark a particular frame.
3719 cf_unmark_frame(capture_file *cf, frame_data *frame)
3721 if (frame->flags.marked) {
3722 frame->flags.marked = FALSE;
3723 if (cf->marked_count > 0)
3729 * Ignore a particular frame.
3732 cf_ignore_frame(capture_file *cf, frame_data *frame)
3734 if (! frame->flags.ignored) {
3735 frame->flags.ignored = TRUE;
3736 if (cf->count > cf->ignored_count)
3737 cf->ignored_count++;
3742 * Un-ignore a particular frame.
3745 cf_unignore_frame(capture_file *cf, frame_data *frame)
3747 if (frame->flags.ignored) {
3748 frame->flags.ignored = FALSE;
3749 if (cf->ignored_count > 0)
3750 cf->ignored_count--;
3755 * Read the section comment.
3758 cf_read_section_comment(capture_file *cf)
3760 wtap_block_t shb_inf;
3764 /* XXX - support multiple SHBs */
3765 shb_inf = wtap_file_get_shb(cf->frame_set_info.wth);
3767 /* Get the first comment from the SHB. */
3768 /* XXX - support multiple comments */
3769 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS)
3775 * Modify the section comment.
3778 cf_update_section_comment(capture_file *cf, gchar *comment)
3780 wtap_block_t shb_inf;
3784 /* XXX - support multiple SHBs */
3785 shb_inf = wtap_file_get_shb(cf->frame_set_info.wth);
3787 /* Get the first comment from the SHB. */
3788 /* XXX - support multiple comments */
3789 if (wtap_block_get_nth_string_option_value(shb_inf, OPT_COMMENT, 0, &shb_comment) != WTAP_OPTTYPE_SUCCESS) {
3790 /* There's no comment - add one. */
3791 wtap_block_add_string_option(shb_inf, OPT_COMMENT, comment, strlen(comment));
3793 /* See if the comment has changed or not */
3794 if (strcmp(shb_comment, comment) == 0) {
3799 /* The comment has changed, let's update it */
3800 wtap_block_set_nth_string_option_value(shb_inf, OPT_COMMENT, 0, comment, strlen(comment));
3802 /* Mark the file as having unsaved changes */
3803 cf->unsaved_changes = TRUE;
3807 cf_get_user_packet_comment(frame_set *fs, const frame_data *fd)
3809 if (fs->frames_user_comments)
3810 return (const char *)g_tree_lookup(fs->frames_user_comments, fd);
3817 * Get the comment on a packet (record).
3818 * If the comment has been edited, it returns the result of the edit,
3819 * otherwise it returns the comment from the file.
3822 cf_get_packet_comment(capture_file *cf, const frame_data *fd)
3826 /* fetch user comment */
3827 if (fd->flags.has_user_comment)
3828 return g_strdup(cf_get_user_packet_comment(&cf->frame_set_info, fd));
3830 /* fetch phdr comment */
3831 if (fd->flags.has_phdr_comment) {
3832 struct wtap_pkthdr phdr; /* Packet header */
3833 Buffer buf; /* Packet data */
3835 wtap_phdr_init(&phdr);
3836 ws_buffer_init(&buf, 1500);
3838 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3839 { /* XXX, what we can do here? */ }
3841 comment = phdr.opt_comment;
3842 wtap_phdr_cleanup(&phdr);
3843 ws_buffer_free(&buf);
3850 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3852 const frame_data *fdata1 = (const frame_data *) a;
3853 const frame_data *fdata2 = (const frame_data *) b;
3855 return (fdata1->num < fdata2->num) ? -1 :
3856 (fdata1->num > fdata2->num) ? 1 :
3861 * Update(replace) the comment on a capture from a frame
3864 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3866 char *pkt_comment = cf_get_packet_comment(cf, fd);
3868 /* Check if the comment has changed */
3869 if (!g_strcmp0(pkt_comment, new_comment)) {
3870 g_free(pkt_comment);
3873 g_free(pkt_comment);
3876 cf->packet_comment_count--;
3879 cf->packet_comment_count++;
3881 fd->flags.has_user_comment = TRUE;
3883 if (!cf->frame_set_info.frames_user_comments)
3884 cf->frame_set_info.frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3886 /* insert new packet comment */
3887 g_tree_replace(cf->frame_set_info.frames_user_comments, fd, g_strdup(new_comment));
3889 expert_update_comment_count(cf->packet_comment_count);
3891 /* OK, we have unsaved changes. */
3892 cf->unsaved_changes = TRUE;
3897 * What types of comments does this capture file have?
3900 cf_comment_types(capture_file *cf)
3902 guint32 comment_types = 0;
3904 if (cf_read_section_comment(cf) != NULL)
3905 comment_types |= WTAP_COMMENT_PER_SECTION;
3906 if (cf->packet_comment_count != 0)
3907 comment_types |= WTAP_COMMENT_PER_PACKET;
3908 return comment_types;
3912 * Add a resolved address to this file's list of resolved addresses.
3915 cf_add_ip_name_from_string(capture_file *cf, const char *addr, const char *name)
3918 * XXX - support multiple resolved address lists, and add to the one
3919 * attached to this file?
3921 if (!add_ip_name_from_string(addr, name))
3924 /* OK, we have unsaved changes. */
3925 cf->unsaved_changes = TRUE;
3933 } save_callback_args_t;
3936 * Save a capture to a file, in a particular format, saving either
3937 * all packets, all currently-displayed packets, or all marked packets.
3939 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3940 * up a message box for the failure.
3943 save_record(capture_file *cf, frame_data *fdata,
3944 struct wtap_pkthdr *phdr, const guint8 *pd,
3947 save_callback_args_t *args = (save_callback_args_t *)argsp;
3948 struct wtap_pkthdr hdr;
3951 const char *pkt_comment;
3953 if (fdata->flags.has_user_comment)
3954 pkt_comment = cf_get_user_packet_comment(&cf->frame_set_info, fdata);
3956 pkt_comment = phdr->opt_comment;
3958 /* init the wtap header for saving */
3959 /* TODO: reuse phdr */
3960 /* XXX - these are the only flags that correspond to data that we have
3961 in the frame_data structure and that matter on a per-packet basis.
3963 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3964 and "on the wire" lengths, or it doesn't.
3966 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3969 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3970 from the packet flags. */
3971 hdr.rec_type = phdr->rec_type;
3972 hdr.presence_flags = 0;
3973 if (fdata->flags.has_ts)
3974 hdr.presence_flags |= WTAP_HAS_TS;
3975 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3976 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3977 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
3978 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
3980 hdr.caplen = phdr->caplen;
3981 hdr.len = phdr->len;
3982 hdr.pkt_encap = phdr->pkt_encap;
3984 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
3986 hdr.pack_flags = phdr->pack_flags;
3987 hdr.opt_comment = g_strdup(pkt_comment);
3988 hdr.has_comment_changed = fdata->flags.has_user_comment ? TRUE : FALSE;
3991 hdr.pseudo_header = phdr->pseudo_header;
3994 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3996 /* and save the packet */
3997 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
3998 cfile_write_failure_alert_box(NULL, args->fname, err, err_info, fdata->num,
4003 g_free(hdr.opt_comment);
4008 * Can this capture file be written out in any format using Wiretap
4009 * rather than by copying the raw data?
4012 cf_can_write_with_wiretap(capture_file *cf)
4014 /* We don't care whether we support the comments in this file or not;
4015 if we can't, we'll offer the user the option of discarding the
4017 return wtap_dump_can_write(cf->linktypes, 0);
4021 * Should we let the user do a save?
4025 * the file has unsaved changes, and we can save it in some
4026 * format through Wiretap
4030 * the file is a temporary file and has no unsaved changes (so
4031 * that "saving" it just means copying it).
4033 * XXX - we shouldn't allow files to be edited if they can't be saved,
4034 * so cf->unsaved_changes should be true only if the file can be saved.
4036 * We don't care whether we support the comments in this file or not;
4037 * if we can't, we'll offer the user the option of discarding the
4041 cf_can_save(capture_file *cf)
4043 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4044 /* Saved changes, and we can write it out with Wiretap. */
4048 if (cf->is_tempfile && !cf->unsaved_changes) {
4050 * Temporary file with no unsaved changes, so we can just do a
4056 /* Nothing to save. */
4061 * Should we let the user do a "save as"?
4065 * we can save it in some format through Wiretap
4069 * the file is a temporary file and has no unsaved changes (so
4070 * that "saving" it just means copying it).
4072 * XXX - we shouldn't allow files to be edited if they can't be saved,
4073 * so cf->unsaved_changes should be true only if the file can be saved.
4075 * We don't care whether we support the comments in this file or not;
4076 * if we can't, we'll offer the user the option of discarding the
4080 cf_can_save_as(capture_file *cf)
4082 if (wtap_dump_can_write(cf->linktypes, 0)) {
4083 /* We can write it out with Wiretap. */
4087 if (cf->is_tempfile && !cf->unsaved_changes) {
4089 * Temporary file with no unsaved changes, so we can just do a
4095 /* Nothing to save. */
4100 * Does this file have unsaved data?
4103 cf_has_unsaved_data(capture_file *cf)
4106 * If this is a temporary file, or a file with unsaved changes, it
4109 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4113 * Quick scan to find packet offsets.
4115 static cf_read_status_t
4116 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile)
4118 const struct wtap_pkthdr *phdr;
4123 progdlg_t *progbar = NULL;
4124 GTimer *prog_timer = g_timer_new();
4127 GTimeVal start_time;
4128 gchar status_str[100];
4133 /* Close the old handle. */
4134 wtap_close(cf->frame_set_info.wth);
4136 /* Open the new file. */
4137 /* XXX: this will go through all open_routines for a matching one. But right
4138 now rescan_file() is only used when a file is being saved to a different
4139 format than the original, and the user is not given a choice of which
4140 reader to use (only which format to save it in), so doing this makes
4142 cf->frame_set_info.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4143 if (cf->frame_set_info.wth == NULL) {
4144 cfile_open_failure_alert_box(fname, err, err_info);
4145 return CF_READ_ERROR;
4148 /* We're scanning a file whose contents should be the same as what
4149 we had before, so we don't discard dissection state etc.. */
4152 /* Set the file name because we need it to set the follow stream filter.
4153 XXX - is that still true? We need it for other reasons, though,
4155 cf->filename = g_strdup(fname);
4157 /* Indicate whether it's a permanent or temporary file. */
4158 cf->is_tempfile = is_tempfile;
4160 /* No user changes yet. */
4161 cf->unsaved_changes = FALSE;
4163 cf->cd_t = wtap_file_type_subtype(cf->frame_set_info.wth);
4164 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4166 cf->snap = wtap_snapshot_length(cf->frame_set_info.wth);
4168 name_ptr = g_filename_display_basename(cf->filename);
4170 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4172 /* Record whether the file is compressed.
4173 XXX - do we know this at open time? */
4174 cf->iscompressed = wtap_iscompressed(cf->frame_set_info.wth);
4176 /* Find the size of the file. */
4177 size = wtap_file_size(cf->frame_set_info.wth, NULL);
4179 g_timer_start(prog_timer);
4181 cf->stop_flag = FALSE;
4182 g_get_current_time(&start_time);
4185 phdr = wtap_phdr(cf->frame_set_info.wth);
4186 while ((wtap_read(cf->frame_set_info.wth, &err, &err_info, &data_offset))) {
4188 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
4189 fdata->file_off = data_offset;
4192 cf->f_datalen = wtap_read_so_far(cf->frame_set_info.wth);
4194 /* Create the progress bar if necessary. */
4195 if (progress_is_slow(progbar, prog_timer, size, cf->f_datalen)) {
4196 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4197 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4198 TRUE, &cf->stop_flag, &start_time, progbar_val);
4202 * Update the progress bar, but do it only after PROGBAR_UPDATE_INTERVAL
4203 * has elapsed. Calling update_progress_dlg and packets_bar_update will
4204 * likely trigger UI paint events, which might take a while depending on
4205 * the platform and display. Reset our timer *after* painting.
4207 if (progbar && g_timer_elapsed(prog_timer, NULL) > PROGBAR_UPDATE_INTERVAL) {
4208 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4209 /* update the packet bar content on the first run or frequently on very large files */
4210 update_progress_dlg(progbar, progbar_val, status_str);
4211 compute_elapsed(cf, &start_time);
4212 packets_bar_update();
4213 g_timer_start(prog_timer);
4217 if (cf->stop_flag) {
4218 /* Well, the user decided to abort the rescan. Sadly, as this
4219 isn't a reread, recovering is difficult, so we'll just
4220 close the current capture. */
4224 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4225 it's not already there.
4226 XXX - yes, this is O(N), so if every packet had a different
4227 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4228 there are probably going to be a small number of encapsulation types
4230 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4233 /* Free the display name */
4236 /* We're done reading the file; destroy the progress bar if it was created. */
4237 if (progbar != NULL)
4238 destroy_progress_dlg(progbar);
4239 g_timer_destroy(prog_timer);
4241 /* We're done reading sequentially through the file. */
4242 cf->state = FILE_READ_DONE;
4244 /* Close the sequential I/O side, to free up memory it requires. */
4245 wtap_sequential_close(cf->frame_set_info.wth);
4247 /* compute the time it took to load the file */
4248 compute_elapsed(cf, &start_time);
4250 /* Set the file encapsulation type now; we don't know what it is until
4251 we've looked at all the packets, as we don't know until then whether
4252 there's more than one type (and thus whether it's
4253 WTAP_ENCAP_PER_PACKET). */
4254 cf->lnk_t = wtap_file_encap(cf->frame_set_info.wth);
4256 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4258 if (cf->stop_flag) {
4259 /* Our caller will give up at this point. */
4260 return CF_READ_ABORTED;
4264 /* Put up a message box noting that the read failed somewhere along
4265 the line. Don't throw out the stuff we managed to read, though,
4267 cfile_read_failure_alert_box(NULL, err, err_info);
4268 return CF_READ_ERROR;
4274 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4275 gboolean compressed, gboolean discard_comments,
4276 gboolean dont_reopen)
4279 gchar *fname_new = NULL;
4282 addrinfo_lists_t *addr_lists;
4286 gchar *display_basename;
4293 save_callback_args_t callback_args;
4294 gboolean needs_reload = FALSE;
4296 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4298 addr_lists = get_addrinfo_list();
4300 if (save_format == cf->cd_t && compressed == cf->iscompressed
4301 && !discard_comments && !cf->unsaved_changes
4302 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4303 /* We're saving in the format it's already in, and we're
4304 not discarding comments, and there are no changes we have
4305 in memory that aren't saved to the file, and we have no name
4306 resolution blocks to write, so we can just move or copy the raw data. */
4308 if (cf->is_tempfile) {
4309 /* The file being saved is a temporary file from a live
4310 capture, so it doesn't need to stay around under that name;
4311 first, try renaming the capture buffer file to the new name.
4312 This acts as a "safe save", in that, if the file already
4313 exists, the existing file will be removed only if the rename
4316 Sadly, on Windows, as we have the current capture file
4317 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4318 (to cause the rename to remove an existing target), as
4319 done by ws_stdio_rename() (ws_rename() is #defined to
4320 be ws_stdio_rename() on Windows) will fail.
4322 According to the MSDN documentation for CreateFile(), if,
4323 when we open a capture file, we were to directly do a CreateFile(),
4324 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4325 convert it to a file descriptor with _open_osfhandle(),
4326 that would allow the file to be renamed out from under us.
4328 However, that doesn't work in practice. Perhaps the problem
4329 is that the process doing the rename is the process that
4330 has the file open. */
4332 if (ws_rename(cf->filename, fname) == 0) {
4333 /* That succeeded - there's no need to copy the source file. */
4334 how_to_save = SAVE_WITH_MOVE;
4336 if (errno == EXDEV) {
4337 /* They're on different file systems, so we have to copy the
4339 how_to_save = SAVE_WITH_COPY;
4341 /* The rename failed, but not because they're on different
4342 file systems - put up an error message. (Or should we
4343 just punt and try to copy? The only reason why I'd
4344 expect the rename to fail and the copy to succeed would
4345 be if we didn't have permission to remove the file from
4346 the temporary directory, and that might be fixable - but
4347 is it worth requiring the user to go off and fix it?) */
4348 cf_rename_failure_alert_box(fname, errno);
4353 how_to_save = SAVE_WITH_COPY;
4356 /* It's a permanent file, so we should copy it, and not remove the
4358 how_to_save = SAVE_WITH_COPY;
4361 if (how_to_save == SAVE_WITH_COPY) {
4362 /* Copy the file, if we haven't moved it. If we're overwriting
4363 an existing file, we do it with a "safe save", by writing
4364 to a new file and, if the write succeeds, renaming the
4365 new file on top of the old file. */
4366 if (file_exists(fname)) {
4367 fname_new = g_strdup_printf("%s~", fname);
4368 if (!copy_file_binary_mode(cf->filename, fname_new))
4371 if (!copy_file_binary_mode(cf->filename, fname))
4376 /* Either we're saving in a different format or we're saving changes,
4377 such as added, modified, or removed comments, that haven't yet
4378 been written to the underlying file; we can't do that by copying
4379 or moving the capture file, we have to do it by writing the packets
4382 GArray *shb_hdrs = NULL;
4383 wtapng_iface_descriptions_t *idb_inf = NULL;
4384 GArray *nrb_hdrs = NULL;
4387 /* XXX: what free's this shb_hdr? */
4388 shb_hdrs = wtap_file_get_shb_for_new_file(cf->frame_set_info.wth);
4389 idb_inf = wtap_file_get_idb_info(cf->frame_set_info.wth);
4390 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->frame_set_info.wth);
4392 /* Determine what file encapsulation type we should use. */
4393 encap = wtap_dump_file_encap_type(cf->linktypes);
4395 if (file_exists(fname)) {
4396 /* We're overwriting an existing file; write out to a new file,
4397 and, if that succeeds, rename the new file on top of the
4398 old file. That makes this a "safe save", so that we don't
4399 lose the old file if we have a problem writing out the new
4400 file. (If the existing file is the current capture file,
4401 we *HAVE* to do that, otherwise we're overwriting the file
4402 from which we're reading the packets that we're writing!) */
4403 fname_new = g_strdup_printf("%s~", fname);
4404 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4405 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4407 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4408 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4414 cfile_dump_open_failure_alert_box(fname, err, save_format);
4418 /* Add address resolution */
4419 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4421 /* Iterate through the list of packets, processing all the packets. */
4422 callback_args.pdh = pdh;
4423 callback_args.fname = fname;
4424 callback_args.file_type = save_format;
4425 switch (process_specified_records(cf, NULL, "Saving", "packets",
4426 TRUE, save_record, &callback_args, TRUE)) {
4429 /* Completed successfully. */
4433 /* The user decided to abort the saving.
4434 If we're writing to a temporary file, remove it.
4435 XXX - should we do so even if we're not writing to a
4437 wtap_dump_close(pdh, &err);
4438 if (fname_new != NULL)
4439 ws_unlink(fname_new);
4440 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4441 return CF_WRITE_ABORTED;
4444 /* Error while saving.
4445 If we're writing to a temporary file, remove it. */
4446 if (fname_new != NULL)
4447 ws_unlink(fname_new);
4448 wtap_dump_close(pdh, &err);
4452 needs_reload = wtap_dump_get_needs_reload(pdh);
4454 if (!wtap_dump_close(pdh, &err)) {
4455 cfile_close_failure_alert_box(fname, err);
4459 how_to_save = SAVE_WITH_WTAP;
4462 if (fname_new != NULL) {
4463 /* We wrote out to fname_new, and should rename it on top of
4464 fname. fname_new is now closed, so that should be possible even
4465 on Windows. However, on Windows, we first need to close whatever
4466 file descriptors we have open for fname. */
4468 wtap_fdclose(cf->frame_set_info.wth);
4470 /* Now do the rename. */
4471 if (ws_rename(fname_new, fname) == -1) {
4472 /* Well, the rename failed. */
4473 cf_rename_failure_alert_box(fname, errno);
4475 /* Attempt to reopen the random file descriptor using the
4476 current file's filename. (At this point, the sequential
4477 file descriptor is closed.) */
4478 if (!wtap_fdreopen(cf->frame_set_info.wth, cf->filename, &err)) {
4479 /* Oh, well, we're screwed. */
4480 display_basename = g_filename_display_basename(cf->filename);
4481 simple_error_message_box(
4482 file_open_error_message(err, FALSE), display_basename);
4483 g_free(display_basename);
4490 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4491 cf->unsaved_changes = FALSE;
4494 switch (how_to_save) {
4496 case SAVE_WITH_MOVE:
4497 /* We just moved the file, so the wtap structure refers to the
4498 new file, and all the information other than the filename
4499 and the "is temporary" status applies to the new file; just
4501 g_free(cf->filename);
4502 cf->filename = g_strdup(fname);
4503 cf->is_tempfile = FALSE;
4504 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4507 case SAVE_WITH_COPY:
4508 /* We just copied the file, s all the information other than
4509 the wtap structure, the filename, and the "is temporary"
4510 status applies to the new file; just update that. */
4511 wtap_close(cf->frame_set_info.wth);
4512 /* Although we're just "copying" and then opening the copy, it will
4513 try all open_routine readers to open the copy, so we need to
4514 reset the cfile's open_type. */
4515 cf->open_type = WTAP_TYPE_AUTO;
4516 cf->frame_set_info.wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4517 if (cf->frame_set_info.wth == NULL) {
4518 cfile_open_failure_alert_box(fname, err, err_info);
4521 g_free(cf->filename);
4522 cf->filename = g_strdup(fname);
4523 cf->is_tempfile = FALSE;
4525 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4528 case SAVE_WITH_WTAP:
4529 /* Open and read the file we saved to.
4531 XXX - this is somewhat of a waste; we already have the
4532 packets, all this gets us is updated file type information
4533 (which we could just stuff into "cf"), and having the new
4534 file be the one we have opened and from which we're reading
4535 the data, and it means we have to spend time opening and
4536 reading the file, which could be a significant amount of
4537 time if the file is large.
4539 If the capture-file-writing code were to return the
4540 seek offset of each packet it writes, we could save that
4541 in the frame_data structure for the frame, and just open
4542 the file without reading it again...
4544 ...as long as, for gzipped files, the process of writing
4545 out the file *also* generates the information needed to
4546 support fast random access to the compressed file. */
4547 /* rescan_file will cause us to try all open_routines, so
4548 reset cfile's open_type */
4549 cf->open_type = WTAP_TYPE_AUTO;
4550 /* There are cases when SAVE_WITH_WTAP can result in new packets
4551 being written to the file, e.g ERF records
4552 In that case, we need to reload the whole file */
4554 if (cf_open(cf, fname, WTAP_TYPE_AUTO, FALSE, &err) == CF_OK) {
4555 if (cf_read(cf, TRUE) != CF_READ_OK) {
4556 /* The rescan failed; just close the file. Either
4557 a dialog was popped up for the failure, so the
4558 user knows what happened, or they stopped the
4559 rescan, in which case they know what happened. */
4560 /* XXX: This is inconsistent with normal open/reload behaviour. */
4566 if (rescan_file(cf, fname, FALSE) != CF_READ_OK) {
4567 /* The rescan failed; just close the file. Either
4568 a dialog was popped up for the failure, so the
4569 user knows what happened, or they stopped the
4570 rescan, in which case they know what happened. */
4577 /* If we were told to discard the comments, do so. */
4578 if (discard_comments) {
4579 /* Remove SHB comment, if any. */
4580 wtap_write_shb_comment(cf->frame_set_info.wth, NULL);
4582 /* remove all user comments */
4583 for (framenum = 1; framenum <= cf->count; framenum++) {
4584 fdata = frame_data_sequence_find(cf->frame_set_info.frames, framenum);
4586 fdata->flags.has_phdr_comment = FALSE;
4587 fdata->flags.has_user_comment = FALSE;
4590 if (cf->frame_set_info.frames_user_comments) {
4591 g_tree_destroy(cf->frame_set_info.frames_user_comments);
4592 cf->frame_set_info.frames_user_comments = NULL;
4595 cf->packet_comment_count = 0;
4601 if (fname_new != NULL) {
4602 /* We were trying to write to a temporary file; get rid of it if it
4603 exists. (We don't care whether this fails, as, if it fails,
4604 there's not much we can do about it. I guess if it failed for
4605 a reason other than "it doesn't exist", we could report an
4606 error, so the user knows there's a junk file that they might
4607 want to clean up.) */
4608 ws_unlink(fname_new);
4611 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4612 return CF_WRITE_ERROR;
4616 cf_export_specified_packets(capture_file *cf, const char *fname,
4617 packet_range_t *range, guint save_format,
4618 gboolean compressed)
4620 gchar *fname_new = NULL;
4623 save_callback_args_t callback_args;
4624 GArray *shb_hdrs = NULL;
4625 wtapng_iface_descriptions_t *idb_inf = NULL;
4626 GArray *nrb_hdrs = NULL;
4629 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4631 packet_range_process_init(range);
4633 /* We're writing out specified packets from the specified capture
4634 file to another file. Even if all captured packets are to be
4635 written, don't special-case the operation - read each packet
4636 and then write it out if it's one of the specified ones. */
4638 /* XXX: what free's this shb_hdr? */
4639 shb_hdrs = wtap_file_get_shb_for_new_file(cf->frame_set_info.wth);
4640 idb_inf = wtap_file_get_idb_info(cf->frame_set_info.wth);
4641 nrb_hdrs = wtap_file_get_nrb_for_new_file(cf->frame_set_info.wth);
4643 /* Determine what file encapsulation type we should use. */
4644 encap = wtap_dump_file_encap_type(cf->linktypes);
4646 if (file_exists(fname)) {
4647 /* We're overwriting an existing file; write out to a new file,
4648 and, if that succeeds, rename the new file on top of the
4649 old file. That makes this a "safe save", so that we don't
4650 lose the old file if we have a problem writing out the new
4651 file. (If the existing file is the current capture file,
4652 we *HAVE* to do that, otherwise we're overwriting the file
4653 from which we're reading the packets that we're writing!) */
4654 fname_new = g_strdup_printf("%s~", fname);
4655 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4656 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4658 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4659 compressed, shb_hdrs, idb_inf, nrb_hdrs, &err);
4665 cfile_dump_open_failure_alert_box(fname, err, save_format);
4669 /* Add address resolution */
4670 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4672 /* Iterate through the list of packets, processing the packets we were
4675 XXX - we've already called "packet_range_process_init(range)", but
4676 "process_specified_records()" will do it again. Fortunately,
4677 that's harmless in this case, as we haven't done anything to
4678 "range" since we initialized it. */
4679 callback_args.pdh = pdh;
4680 callback_args.fname = fname;
4681 callback_args.file_type = save_format;
4682 switch (process_specified_records(cf, range, "Writing", "specified records",
4683 TRUE, save_record, &callback_args, TRUE)) {
4686 /* Completed successfully. */
4690 /* The user decided to abort the saving.
4691 If we're writing to a temporary file, remove it.
4692 XXX - should we do so even if we're not writing to a
4694 wtap_dump_close(pdh, &err);
4695 if (fname_new != NULL)
4696 ws_unlink(fname_new);
4697 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4698 return CF_WRITE_ABORTED;
4702 /* Error while saving.
4703 If we're writing to a temporary file, remove it. */
4704 if (fname_new != NULL)
4705 ws_unlink(fname_new);
4706 wtap_dump_close(pdh, &err);
4710 if (!wtap_dump_close(pdh, &err)) {
4711 cfile_close_failure_alert_box(fname, err);
4715 if (fname_new != NULL) {
4716 /* We wrote out to fname_new, and should rename it on top of
4717 fname; fname is now closed, so that should be possible even
4718 on Windows. Do the rename. */
4719 if (ws_rename(fname_new, fname) == -1) {
4720 /* Well, the rename failed. */
4721 cf_rename_failure_alert_box(fname, errno);
4726 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4730 if (fname_new != NULL) {
4731 /* We were trying to write to a temporary file; get rid of it if it
4732 exists. (We don't care whether this fails, as, if it fails,
4733 there's not much we can do about it. I guess if it failed for
4734 a reason other than "it doesn't exist", we could report an
4735 error, so the user knows there's a junk file that they might
4736 want to clean up.) */
4737 ws_unlink(fname_new);
4740 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4741 return CF_WRITE_ERROR;
4745 * XXX - whether we mention the source pathname, the target pathname,
4746 * or both depends on the error and on what we find if we look for
4747 * one or both of them.
4750 cf_rename_failure_alert_box(const char *filename, int err)
4752 gchar *display_basename;
4754 display_basename = g_filename_display_basename(filename);
4758 /* XXX - should check whether the source exists and, if not,
4759 report it as the problem and, if so, report the destination
4761 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4766 /* XXX - if we're doing a rename after a safe save, we should
4767 probably say something else. */
4768 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4773 /* XXX - this should probably mention both the source and destination
4775 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4776 display_basename, wtap_strerror(err));
4779 g_free(display_basename);
4782 /* Reload the current capture file. */
4784 cf_reload(capture_file *cf) {
4786 gboolean is_tempfile;
4789 /* If the file could be opened, "cf_open()" calls "cf_close()"
4790 to get rid of state for the old capture file before filling in state
4791 for the new capture file. "cf_close()" will remove the file if
4792 it's a temporary file; we don't want that to happen (for one thing,
4793 it'd prevent subsequent reopens from working). Remember whether it's
4794 a temporary file, mark it as not being a temporary file, and then
4795 reopen it as the type of file it was.
4797 Also, "cf_close()" will free "cf->filename", so we must make
4798 a copy of it first. */
4799 filename = g_strdup(cf->filename);
4800 is_tempfile = cf->is_tempfile;
4801 cf->is_tempfile = FALSE;
4802 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
4803 switch (cf_read(cf, TRUE)) {
4807 /* Just because we got an error, that doesn't mean we were unable
4808 to read any of the file; we handle what we could get from the
4812 case CF_READ_ABORTED:
4813 /* The user bailed out of re-reading the capture file; the
4814 capture file has been closed - just free the capture file name
4815 string and return (without changing the last containing
4821 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
4822 Instead, the file was left open, so we should restore "cf->is_tempfile"
4825 XXX - change the menu? Presumably "cf_open()" will do that;
4826 make sure it does! */
4827 cf->is_tempfile = is_tempfile;
4829 /* "cf_open()" made a copy of the file name we handed it, so
4830 we should free up our copy. */
4840 * indent-tabs-mode: nil
4843 * ex: set shiftwidth=2 tabstop=8 expandtab:
4844 * :indentSize=2:tabSize=8:noTabs=true: