4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <wsutil/tempfile.h>
34 #include <wsutil/file_util.h>
35 #include <wsutil/filesystem.h>
36 #include <wsutil/ws_version_info.h>
38 #include <wiretap/merge.h>
40 #include <epan/exceptions.h>
41 #include <epan/epan-int.h>
42 #include <epan/epan.h>
43 #include <epan/column.h>
44 #include <epan/packet.h>
45 #include <epan/column-utils.h>
46 #include <epan/expert.h>
47 #include <epan/prefs.h>
48 #include <epan/dfilter/dfilter.h>
49 #include <epan/epan_dissect.h>
51 #include <epan/dissectors/packet-ber.h>
52 #include <epan/timestamp.h>
53 #include <epan/dfilter/dfilter-macro.h>
54 #include <epan/strutil.h>
55 #include <epan/addr_resolv.h>
58 #include "color_filters.h"
62 #include "frame_tvbuff.h"
64 #include "ui/alert_box.h"
65 #include "ui/simple_dialog.h"
66 #include "ui/main_statusbar.h"
67 #include "ui/progress_dlg.h"
68 #include "ui/ui_util.h"
70 /* Needed for addrinfo */
71 #ifdef HAVE_SYS_TYPES_H
72 # include <sys/types.h>
75 #ifdef HAVE_SYS_SOCKET_H
76 #include <sys/socket.h>
79 #ifdef HAVE_NETINET_IN_H
80 # include <netinet/in.h>
87 #ifdef HAVE_WINSOCK2_H
88 # include <winsock2.h>
91 #if defined(_WIN32) && defined(INET6)
92 # include <ws2tcpip.h>
96 gboolean auto_scroll_live; /* GTK+ only? */
99 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
100 column_info *cinfo, gint64 offset);
102 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
109 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
111 static void match_subtree_text(proto_node *node, gpointer data);
112 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
114 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
116 static match_result match_narrow(capture_file *cf, frame_data *fdata,
118 static match_result match_wide(capture_file *cf, frame_data *fdata,
120 static match_result match_binary(capture_file *cf, frame_data *fdata,
122 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
124 static match_result match_marked(capture_file *cf, frame_data *fdata,
126 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
128 static gboolean find_packet(capture_file *cf,
129 match_result (*match_function)(capture_file *, frame_data *, void *),
130 void *criterion, search_direction dir);
132 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
134 static void cf_open_failure_alert_box(const char *filename, int err,
135 gchar *err_info, gboolean for_writing,
137 static void cf_rename_failure_alert_box(const char *filename, int err);
138 static void cf_close_failure_alert_box(const char *filename, int err);
139 static void ref_time_packets(capture_file *cf);
140 /* Update the progress bar this many times when reading a file. */
141 #define N_PROGBAR_UPDATES 100
142 /* We read around 200k/100ms don't update the progress bar more often than that */
143 #define MIN_QUANTUM 200000
144 #define MIN_NUMBER_OF_PACKET 1500
147 * We could probably use g_signal_...() instead of the callbacks below but that
148 * would require linking our CLI programs to libgobject and creating an object
149 * instance for the signals.
152 cf_callback_t cb_fct;
154 } cf_callback_data_t;
156 static GList *cf_callbacks = NULL;
159 cf_callback_invoke(int event, gpointer data)
161 cf_callback_data_t *cb;
162 GList *cb_item = cf_callbacks;
164 /* there should be at least one interested */
165 g_assert(cb_item != NULL);
167 while (cb_item != NULL) {
168 cb = (cf_callback_data_t *)cb_item->data;
169 cb->cb_fct(event, data, cb->user_data);
170 cb_item = g_list_next(cb_item);
176 cf_callback_add(cf_callback_t func, gpointer user_data)
178 cf_callback_data_t *cb;
180 cb = g_new(cf_callback_data_t,1);
182 cb->user_data = user_data;
184 cf_callbacks = g_list_prepend(cf_callbacks, cb);
188 cf_callback_remove(cf_callback_t func, gpointer user_data)
190 cf_callback_data_t *cb;
191 GList *cb_item = cf_callbacks;
193 while (cb_item != NULL) {
194 cb = (cf_callback_data_t *)cb_item->data;
195 if (cb->cb_fct == func && cb->user_data == user_data) {
196 cf_callbacks = g_list_remove(cf_callbacks, cb);
200 cb_item = g_list_next(cb_item);
203 g_assert_not_reached();
207 cf_timestamp_auto_precision(capture_file *cf)
211 /* don't try to get the file's precision if none is opened */
212 if (cf->state == FILE_CLOSED) {
216 /* Set the column widths of those columns that show the time in
217 "command-line-specified" format. */
218 for (i = 0; i < cf->cinfo.num_cols; i++) {
219 if (col_has_time_fmt(&cf->cinfo, i)) {
220 packet_list_resize_column(i);
226 cf_get_computed_elapsed(capture_file *cf)
228 return cf->computed_elapsed;
232 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
235 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
240 g_get_current_time(&time_now);
242 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
243 time_now.tv_usec - start_time->tv_usec;
245 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
248 static const nstime_t *
249 ws_get_frame_ts(void *data, guint32 frame_num)
251 capture_file *cf = (capture_file *) data;
253 if (cf->prev_dis && cf->prev_dis->num == frame_num)
254 return &cf->prev_dis->abs_ts;
256 if (cf->prev_cap && cf->prev_cap->num == frame_num)
257 return &cf->prev_cap->abs_ts;
260 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
262 return (fd) ? &fd->abs_ts : NULL;
269 ws_get_user_comment(void *data, const frame_data *fd)
271 capture_file *cf = (capture_file *) data;
273 return cf_get_user_packet_comment(cf, fd);
277 ws_epan_new(capture_file *cf)
279 epan_t *epan = epan_new();
282 epan->get_frame_ts = ws_get_frame_ts;
283 epan->get_interface_name = cap_file_get_interface_name;
284 epan->get_user_comment = ws_get_user_comment;
290 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
295 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
299 /* The open succeeded. Close whatever capture file we had open,
300 and fill in the information for this file. */
303 /* Initialize the packet header. */
304 wtap_phdr_init(&cf->phdr);
306 /* XXX - we really want to initialize this after we've read all
307 the packets, so we know how much we'll ultimately need. */
308 ws_buffer_init(&cf->buf, 1500);
310 /* Create new epan session for dissection.
311 * (The old one was freed in cf_close().)
313 cf->epan = ws_epan_new(cf);
315 /* We're about to start reading the file. */
316 cf->state = FILE_READ_IN_PROGRESS;
321 /* Set the file name because we need it to set the follow stream filter.
322 XXX - is that still true? We need it for other reasons, though,
324 cf->filename = g_strdup(fname);
326 /* Indicate whether it's a permanent or temporary file. */
327 cf->is_tempfile = is_tempfile;
329 /* No user changes yet. */
330 cf->unsaved_changes = FALSE;
332 cf->computed_elapsed = 0;
334 cf->cd_t = wtap_file_type_subtype(cf->wth);
335 cf->open_type = type;
336 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
338 cf->packet_comment_count = 0;
339 cf->displayed_count = 0;
340 cf->marked_count = 0;
341 cf->ignored_count = 0;
342 cf->ref_time_count = 0;
343 cf->drops_known = FALSE;
345 cf->snap = wtap_snapshot_length(cf->wth);
347 /* Snapshot length not known. */
348 cf->has_snap = FALSE;
349 cf->snap = WTAP_MAX_PACKET_SIZE;
353 /* Allocate a frame_data_sequence for the frames in this file */
354 cf->frames = new_frame_data_sequence();
356 nstime_set_zero(&cf->elapsed_time);
362 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
363 cf_timestamp_auto_precision(cf);
365 packet_list_queue_draw();
366 cf_callback_invoke(cf_cb_file_opened, cf);
368 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
369 /* tell the BER dissector the file name */
370 ber_set_filename(cf->filename);
373 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
374 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
379 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
384 * Add an encapsulation type to cf->linktypes.
387 cf_add_encapsulation_type(capture_file *cf, int encap)
391 for (i = 0; i < cf->linktypes->len; i++) {
392 if (g_array_index(cf->linktypes, gint, i) == encap)
393 return; /* it's already there */
395 /* It's not already there - add it. */
396 g_array_append_val(cf->linktypes, encap);
399 /* Reset everything to a pristine state */
401 cf_close(capture_file *cf)
403 cf->stop_flag = FALSE;
404 if (cf->state == FILE_CLOSED)
405 return; /* Nothing to do */
407 /* Die if we're in the middle of reading a file. */
408 g_assert(cf->state != FILE_READ_IN_PROGRESS);
410 cf_callback_invoke(cf_cb_file_closing, cf);
412 /* close things, if not already closed before */
413 color_filters_cleanup();
419 /* We have no file open... */
420 if (cf->filename != NULL) {
421 /* If it's a temporary file, remove it. */
423 ws_unlink(cf->filename);
424 g_free(cf->filename);
427 /* ...which means we have no changes to that file to save. */
428 cf->unsaved_changes = FALSE;
430 /* no open_routine type */
431 cf->open_type = WTAP_TYPE_AUTO;
433 /* Clean up the packet header. */
434 wtap_phdr_cleanup(&cf->phdr);
436 /* Free up the packet buffer. */
437 ws_buffer_free(&cf->buf);
439 dfilter_free(cf->rfcode);
441 if (cf->frames != NULL) {
442 free_frame_data_sequence(cf->frames);
445 #ifdef WANT_PACKET_EDITOR
446 if (cf->edited_frames) {
447 g_tree_destroy(cf->edited_frames);
448 cf->edited_frames = NULL;
451 if (cf->frames_user_comments) {
452 g_tree_destroy(cf->frames_user_comments);
453 cf->frames_user_comments = NULL;
455 cf_unselect_packet(cf); /* nothing to select */
456 cf->first_displayed = 0;
457 cf->last_displayed = 0;
459 /* No frames, no frame selected, no field in that frame selected. */
461 cf->current_frame = 0;
463 cf->finfo_selected = NULL;
465 /* No frame link-layer types, either. */
466 if (cf->linktypes != NULL) {
467 g_array_free(cf->linktypes, TRUE);
468 cf->linktypes = NULL;
471 /* Clear the packet list. */
472 packet_list_freeze();
477 nstime_set_zero(&cf->elapsed_time);
479 reset_tap_listeners();
484 /* We have no file open. */
485 cf->state = FILE_CLOSED;
487 cf_callback_invoke(cf_cb_file_closed, cf);
491 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
495 progbar_val = (gfloat) file_pos / (gfloat) size;
496 if (progbar_val > 1.0) {
498 /* The file probably grew while we were reading it.
499 * Update file size, and try again.
501 size = wtap_file_size(cf->wth, NULL);
504 progbar_val = (gfloat) file_pos / (gfloat) size;
506 /* If it's still > 1, either "wtap_file_size()" failed (in which
507 * case there's not much we can do about it), or the file
508 * *shrank* (in which case there's not much we can do about
509 * it); just clip the progress value at 1.0.
511 if (progbar_val > 1.0f)
515 g_snprintf(status_str, status_size,
516 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
517 file_pos / 1024, size / 1024);
523 cf_read(capture_file *cf, gboolean reloading)
528 progdlg_t *progbar = NULL;
532 volatile gboolean create_proto_tree;
536 /* Compile the current display filter.
537 * We assume this will not fail since cf->dfilter is only set in
538 * cf_filter IFF the filter was valid.
540 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
541 g_assert(!cf->dfilter || (compiled && dfcode));
543 /* Get the union of the flags for all tap listeners. */
544 tap_flags = union_of_tap_listener_flags();
546 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
548 reset_tap_listeners();
550 name_ptr = g_filename_display_basename(cf->filename);
553 cf_callback_invoke(cf_cb_file_reload_started, cf);
555 cf_callback_invoke(cf_cb_file_read_started, cf);
557 /* Record whether the file is compressed.
558 XXX - do we know this at open time? */
559 cf->iscompressed = wtap_iscompressed(cf->wth);
561 /* The packet list window will be empty until the file is completly loaded */
562 packet_list_freeze();
564 cf->stop_flag = FALSE;
565 g_get_current_time(&start_time);
567 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
571 int displayed_once = 0;
579 gint64 progbar_quantum;
580 gint64 progbar_nextstep;
582 gchar status_str[100];
586 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
588 /* Find the size of the file. */
589 size = wtap_file_size(cf->wth, NULL);
591 /* Update the progress bar when it gets to this value. */
592 progbar_nextstep = 0;
593 /* When we reach the value that triggers a progress bar update,
594 bump that value by this amount. */
596 progbar_quantum = size/N_PROGBAR_UPDATES;
597 if (progbar_quantum < MIN_QUANTUM)
598 progbar_quantum = MIN_QUANTUM;
602 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
605 file_pos = wtap_read_so_far(cf->wth);
607 /* Create the progress bar if necessary.
608 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
610 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
611 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
613 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
614 TRUE, &cf->stop_flag, &start_time, progbar_val);
616 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
617 TRUE, &cf->stop_flag, &start_time, progbar_val);
620 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
621 when we update it, we have to run the GTK+ main loop to get it
622 to repaint what's pending, and doing so may involve an "ioctl()"
623 to see if there's any pending input from an X server, and doing
624 that for every packet can be costly, especially on a big file. */
625 if (file_pos >= progbar_nextstep) {
626 if (progbar != NULL) {
627 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
628 /* update the packet bar content on the first run or frequently on very large files */
630 if (progbar_quantum > 500000 || displayed_once == 0) {
631 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
633 packets_bar_update();
636 #endif /* HAVE_LIBPCAP */
637 update_progress_dlg(progbar, progbar_val, status_str);
639 progbar_nextstep += progbar_quantum;
644 /* Well, the user decided to abort the read. He/She will be warned and
645 it might be enough for him/her to work with the already loaded
647 This is especially true for very large capture files, where you don't
648 want to wait loading the whole file (which may last minutes or even
649 hours even on fast machines) just to see that it was the wrong file. */
652 read_packet(cf, dfcode, &edt, cinfo, data_offset);
655 CATCH(OutOfMemoryError) {
656 simple_message_box(ESD_TYPE_ERROR, NULL,
657 "More information and workarounds can be found at\n"
658 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
659 "Sorry, but Wireshark has run out of memory and has to terminate now.");
661 /* Could we close the current capture and free up memory from that? */
663 /* we have to terminate, as we cannot recover from the memory error */
669 /* Free the display name */
672 /* Cleanup and release all dfilter resources */
673 if (dfcode != NULL) {
674 dfilter_free(dfcode);
677 epan_dissect_cleanup(&edt);
679 /* We're done reading the file; destroy the progress bar if it was created. */
681 destroy_progress_dlg(progbar);
683 /* We're done reading sequentially through the file. */
684 cf->state = FILE_READ_DONE;
686 /* Close the sequential I/O side, to free up memory it requires. */
687 wtap_sequential_close(cf->wth);
689 /* Allow the protocol dissectors to free up memory that they
690 * don't need after the sequential run-through of the packets. */
691 postseq_cleanup_all_protocols();
693 /* compute the time it took to load the file */
694 compute_elapsed(cf, &start_time);
696 /* Set the file encapsulation type now; we don't know what it is until
697 we've looked at all the packets, as we don't know until then whether
698 there's more than one type (and thus whether it's
699 WTAP_ENCAP_PER_PACKET). */
700 cf->lnk_t = wtap_file_encap(cf->wth);
702 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
707 cf_callback_invoke(cf_cb_file_reload_finished, cf);
709 cf_callback_invoke(cf_cb_file_read_finished, cf);
711 /* If we have any displayed packets to select, select the first of those
712 packets by making the first row the selected row. */
713 if (cf->first_displayed != 0) {
714 packet_list_select_first_row();
718 simple_message_box(ESD_TYPE_WARN, NULL,
719 "The remaining packets in the file were discarded.\n"
721 "As a lot of packets from the original file will be missing,\n"
722 "remember to be careful when saving the current content to a file.\n",
723 "File loading was cancelled.");
724 return CF_READ_ERROR;
728 /* Put up a message box noting that the read failed somewhere along
729 the line. Don't throw out the stuff we managed to read, though,
733 case WTAP_ERR_UNSUPPORTED:
734 simple_error_message_box(
735 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
736 err_info != NULL ? err_info : "no information supplied");
740 case WTAP_ERR_SHORT_READ:
741 simple_error_message_box(
742 "The capture file appears to have been cut short"
743 " in the middle of a packet.");
746 case WTAP_ERR_BAD_FILE:
747 simple_error_message_box(
748 "The capture file appears to be damaged or corrupt.\n(%s)",
749 err_info != NULL ? err_info : "no information supplied");
753 case WTAP_ERR_DECOMPRESS:
754 simple_error_message_box(
755 "The compressed capture file appears to be damaged or corrupt.\n(%s)",
756 err_info != NULL ? err_info : "no information supplied");
761 simple_error_message_box(
762 "An error occurred while reading the"
763 " capture file: %s.", wtap_strerror(err));
766 return CF_READ_ERROR;
773 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
776 volatile int newly_displayed_packets = 0;
779 gboolean create_proto_tree;
783 /* Compile the current display filter.
784 * We assume this will not fail since cf->dfilter is only set in
785 * cf_filter IFF the filter was valid.
787 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
788 g_assert(!cf->dfilter || (compiled && dfcode));
790 /* Get the union of the flags for all tap listeners. */
791 tap_flags = union_of_tap_listener_flags();
793 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
797 packet_list_check_end();
798 /* Don't freeze/thaw the list when doing live capture */
799 /*packet_list_freeze();*/
801 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
803 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
806 gint64 data_offset = 0;
809 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
811 while (to_read != 0) {
812 wtap_cleareof(cf->wth);
813 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
816 if (cf->state == FILE_READ_ABORTED) {
817 /* Well, the user decided to exit Wireshark. Break out of the
818 loop, and let the code below (which is called even if there
819 aren't any packets left to read) exit. */
822 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
823 newly_displayed_packets++;
828 CATCH(OutOfMemoryError) {
829 simple_message_box(ESD_TYPE_ERROR, NULL,
830 "More information and workarounds can be found at\n"
831 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
832 "Sorry, but Wireshark has run out of memory and has to terminate now.");
834 /* Could we close the current capture and free up memory from that? */
835 return CF_READ_ABORTED;
837 /* we have to terminate, as we cannot recover from the memory error */
843 /* Update the file encapsulation; it might have changed based on the
844 packets we've read. */
845 cf->lnk_t = wtap_file_encap(cf->wth);
847 /* Cleanup and release all dfilter resources */
848 if (dfcode != NULL) {
849 dfilter_free(dfcode);
852 epan_dissect_cleanup(&edt);
854 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
855 cf->count, cf->state, *err);*/
857 /* Don't freeze/thaw the list when doing live capture */
858 /*packet_list_thaw();*/
859 /* With the new packet list the first packet
860 * isn't automatically selected.
862 if (!cf->current_frame)
863 packet_list_select_first_row();
865 /* moving to the end of the packet list - if the user requested so and
866 we have some new packets. */
867 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
868 packet_list_moveto_end();
870 if (cf->state == FILE_READ_ABORTED) {
871 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
872 so that our caller can kill off the capture child process;
873 this will cause an EOF on the pipe from the child, so
874 "cf_finish_tail()" will be called, and it will clean up
876 return CF_READ_ABORTED;
877 } else if (*err != 0) {
878 /* We got an error reading the capture file.
879 XXX - pop up a dialog box instead? */
880 if (err_info != NULL) {
881 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
882 wtap_strerror(*err), cf->filename, err_info);
885 g_warning("Error \"%s\" while reading \"%s\"",
886 wtap_strerror(*err), cf->filename);
888 return CF_READ_ERROR;
894 cf_fake_continue_tail(capture_file *cf) {
895 cf->state = FILE_READ_DONE;
899 cf_finish_tail(capture_file *cf, int *err)
906 gboolean create_proto_tree;
910 /* Compile the current display filter.
911 * We assume this will not fail since cf->dfilter is only set in
912 * cf_filter IFF the filter was valid.
914 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
915 g_assert(!cf->dfilter || (compiled && dfcode));
917 /* Get the union of the flags for all tap listeners. */
918 tap_flags = union_of_tap_listener_flags();
919 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
921 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
923 if (cf->wth == NULL) {
925 return CF_READ_ERROR;
928 packet_list_check_end();
929 /* Don't freeze/thaw the list when doing live capture */
930 /*packet_list_freeze();*/
932 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
934 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
935 if (cf->state == FILE_READ_ABORTED) {
936 /* Well, the user decided to abort the read. Break out of the
937 loop, and let the code below (which is called even if there
938 aren't any packets left to read) exit. */
941 read_packet(cf, dfcode, &edt, cinfo, data_offset);
944 /* Cleanup and release all dfilter resources */
945 if (dfcode != NULL) {
946 dfilter_free(dfcode);
949 epan_dissect_cleanup(&edt);
951 /* Don't freeze/thaw the list when doing live capture */
952 /*packet_list_thaw();*/
954 if (cf->state == FILE_READ_ABORTED) {
955 /* Well, the user decided to abort the read. We're only called
956 when the child capture process closes the pipe to us (meaning
957 it's probably exited), so we can just close the capture
958 file; we return CF_READ_ABORTED so our caller can do whatever
959 is appropriate when that happens. */
961 return CF_READ_ABORTED;
964 if (auto_scroll_live && cf->count != 0)
965 packet_list_moveto_end();
967 /* We're done reading sequentially through the file. */
968 cf->state = FILE_READ_DONE;
970 /* We're done reading sequentially through the file; close the
971 sequential I/O side, to free up memory it requires. */
972 wtap_sequential_close(cf->wth);
974 /* Allow the protocol dissectors to free up memory that they
975 * don't need after the sequential run-through of the packets. */
976 postseq_cleanup_all_protocols();
978 /* Update the file encapsulation; it might have changed based on the
979 packets we've read. */
980 cf->lnk_t = wtap_file_encap(cf->wth);
982 /* Update the details in the file-set dialog, as the capture file
983 * has likely grown since we first stat-ed it */
984 fileset_update_file(cf->filename);
987 /* We got an error reading the capture file.
988 XXX - pop up a dialog box? */
989 if (err_info != NULL) {
990 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
991 wtap_strerror(*err), cf->filename, err_info);
994 g_warning("Error \"%s\" while reading \"%s\"",
995 wtap_strerror(*err), cf->filename);
997 return CF_READ_ERROR;
1002 #endif /* HAVE_LIBPCAP */
1005 cf_get_display_name(capture_file *cf)
1009 /* Return a name to use in displays */
1010 if (!cf->is_tempfile) {
1011 /* Get the last component of the file name, and use that. */
1013 displayname = g_filename_display_basename(cf->filename);
1015 displayname=g_strdup("(No file)");
1018 /* The file we read is a temporary file from a live capture or
1019 a merge operation; we don't mention its name, but, if it's
1020 from a capture, give the source of the capture. */
1022 displayname = g_strdup(cf->source);
1024 displayname = g_strdup("(Untitled)");
1030 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1036 cf->source = g_strdup(source);
1038 cf->source = g_strdup("");
1042 const gchar *cf_get_tempfile_source(capture_file *cf) {
1050 /* XXX - use a macro instead? */
1052 cf_get_packet_count(capture_file *cf)
1057 /* XXX - use a macro instead? */
1059 cf_is_tempfile(capture_file *cf)
1061 return cf->is_tempfile;
1064 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1066 cf->is_tempfile = is_tempfile;
1070 /* XXX - use a macro instead? */
1071 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1073 cf->drops_known = drops_known;
1076 /* XXX - use a macro instead? */
1077 void cf_set_drops(capture_file *cf, guint32 drops)
1082 /* XXX - use a macro instead? */
1083 gboolean cf_get_drops_known(capture_file *cf)
1085 return cf->drops_known;
1088 /* XXX - use a macro instead? */
1089 guint32 cf_get_drops(capture_file *cf)
1094 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1096 cf->rfcode = rfcode;
1100 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1101 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1102 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1106 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1107 &cf->ref, cf->prev_dis);
1108 cf->prev_cap = fdata;
1110 if (dfcode != NULL) {
1111 epan_dissect_prime_dfilter(edt, dfcode);
1114 /* Dissect the frame. */
1115 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1117 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1118 if (dfcode != NULL) {
1119 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1121 if (fdata->flags.passed_dfilter) {
1122 /* This frame passed the display filter but it may depend on other
1123 * (potentially not displayed) frames. Find those frames and mark them
1126 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1129 fdata->flags.passed_dfilter = 1;
1131 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1132 cf->displayed_count++;
1134 if (add_to_packet_list) {
1135 /* We fill the needed columns from new_packet_list */
1136 row = packet_list_append(cinfo, fdata);
1139 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1141 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1142 cf->prev_dis = fdata;
1144 /* If we haven't yet seen the first frame, this is it.
1146 XXX - we must do this before we add the row to the display,
1147 as, if the display's GtkCList's selection mode is
1148 GTK_SELECTION_BROWSE, when the first entry is added to it,
1149 "cf_select_packet()" will be called, and it will fetch the row
1150 data for the 0th row, and will get a null pointer rather than
1151 "fdata", as "gtk_clist_append()" won't yet have returned and
1152 thus "gtk_clist_set_row_data()" won't yet have been called.
1154 We thus need to leave behind bread crumbs so that
1155 "cf_select_packet()" can find this frame. See the comment
1156 in "cf_select_packet()". */
1157 if (cf->first_displayed == 0)
1158 cf->first_displayed = fdata->num;
1160 /* This is the last frame we've seen so far. */
1161 cf->last_displayed = fdata->num;
1164 epan_dissect_reset(edt);
1168 /* read in a new packet */
1169 /* returns the row of the new packet in the packet list or -1 if not displayed */
1171 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1172 column_info *cinfo, gint64 offset)
1174 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1175 const guint8 *buf = wtap_buf_ptr(cf->wth);
1182 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1183 it's not already there.
1184 XXX - yes, this is O(N), so if every packet had a different
1185 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1186 there are probably going to be a small number of encapsulation types
1188 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1190 /* The frame number of this packet is one more than the count of
1191 frames in the file so far. */
1192 framenum = cf->count + 1;
1194 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1198 epan_dissect_t rf_edt;
1200 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1201 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1202 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1203 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1204 epan_dissect_cleanup(&rf_edt);
1208 /* This does a shallow copy of fdlocal, which is good enough. */
1209 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1212 if (phdr->opt_comment != NULL)
1213 cf->packet_comment_count++;
1214 cf->f_datalen = offset + fdlocal.cap_len;
1216 if (!cf->redissecting) {
1217 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1218 cinfo, phdr, buf, TRUE);
1226 typedef struct _callback_data_t {
1228 gint64 progbar_nextstep;
1229 gint64 progbar_quantum;
1230 GTimeVal start_time;
1237 merge_callback(merge_event event, int num _U_,
1238 const merge_in_file_t in_files[], const guint in_file_count,
1242 callback_data_t *cb_data = (callback_data_t*) data;
1244 g_assert(cb_data != NULL);
1248 case MERGE_EVENT_INPUT_FILES_OPENED:
1252 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1256 case MERGE_EVENT_READY_TO_MERGE:
1257 /* Get the sum of the sizes of all the files. */
1258 for (i = 0; i < in_file_count; i++)
1259 cb_data->f_len += in_files[i].size;
1261 /* When we reach the value that triggers a progress bar update,
1262 bump that value by this amount. */
1263 cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES;
1265 g_get_current_time(&cb_data->start_time);
1268 case MERGE_EVENT_PACKET_WAS_READ:
1270 gint64 data_offset = 0;
1272 /* Get the sum of the data offsets in all of the files. */
1274 for (i = 0; i < in_file_count; i++)
1275 data_offset += in_files[i].data_offset;
1277 /* Create the progress bar if necessary.
1278 We check on every iteration of the loop, so that it takes no
1279 longer than the standard time to create it (otherwise, for a
1280 large file, we might take considerably longer than that standard
1281 time in order to get to the next progress bar step). */
1282 if (cb_data->progbar == NULL) {
1283 cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1284 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1287 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1288 when we update it, we have to run the GTK+ main loop to get it
1289 to repaint what's pending, and doing so may involve an "ioctl()"
1290 to see if there's any pending input from an X server, and doing
1291 that for every packet can be costly, especially on a big file. */
1292 if (data_offset >= cb_data->progbar_nextstep) {
1294 gint64 file_pos = 0;
1295 /* Get the sum of the seek positions in all of the files. */
1296 for (i = 0; i < in_file_count; i++)
1297 file_pos += wtap_read_so_far(in_files[i].wth);
1299 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1300 if (progbar_val > 1.0f) {
1301 /* Some file probably grew while we were reading it.
1302 That "shouldn't happen", so we'll just clip the progress
1307 if (cb_data->progbar != NULL) {
1308 gchar status_str[100];
1309 g_snprintf(status_str, sizeof(status_str),
1310 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1311 file_pos / 1024, cb_data->f_len / 1024);
1312 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1314 cb_data->progbar_nextstep += cb_data->progbar_quantum;
1319 case MERGE_EVENT_DONE:
1320 /* We're done merging the files; destroy the progress bar if it was created. */
1321 if (cb_data->progbar != NULL)
1322 destroy_progress_dlg(cb_data->progbar);
1326 return cb_data->stop_flag;
1332 cf_merge_files(char **out_filenamep, int in_file_count,
1333 char *const *in_filenames, int file_type, gboolean do_append)
1339 gchar *err_info = NULL;
1341 merge_result status;
1342 merge_progress_callback_t cb;
1345 if (*out_filenamep != NULL) {
1346 out_filename = *out_filenamep;
1347 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1351 out_fd = create_tempfile(&tmpname, "wireshark");
1354 out_filename = g_strdup(tmpname);
1355 *out_filenamep = out_filename;
1358 cf_open_failure_alert_box(out_filename, err, NULL, TRUE, file_type);
1362 /* prepare our callback routine */
1363 cb.callback_func = merge_callback;
1364 cb.data = g_malloc0(sizeof(callback_data_t));
1366 /* merge the files */
1367 status = merge_files(out_fd, out_filename, file_type,
1368 (const char *const *) in_filenames, in_file_count,
1369 do_append, IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1370 "Wireshark", &cb, &err, &err_info, &err_fileno);
1378 case MERGE_USER_ABORTED:
1379 /* this isn't really an error, though we will return CF_ERROR later */
1382 case MERGE_ERR_CANT_OPEN_INFILE:
1383 cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
1388 case MERGE_ERR_CANT_OPEN_OUTFILE:
1389 cf_open_failure_alert_box(out_filename, err, err_info, TRUE,
1394 case MERGE_ERR_CANT_READ_INFILE: /* fall through */
1395 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1396 case MERGE_ERR_CANT_WRITE_OUTFILE:
1397 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1399 simple_error_message_box("%s", err_info ? err_info : "unknown error");
1404 /* for general case, no need to close out_fd: file handle associated to this file
1405 descriptor was already closed by the call to wtap_dump_close() in merge_files() */
1407 if (status != MERGE_OK) {
1408 /* Callers aren't expected to treat an error or an explicit abort
1409 differently - we put up error dialogs ourselves, so they don't
1417 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1419 const char *filter_new = dftext ? dftext : "";
1420 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1423 GTimeVal start_time;
1425 /* if new filter equals old one, do nothing unless told to do so */
1426 if (!force && strcmp(filter_new, filter_old) == 0) {
1432 if (dftext == NULL) {
1433 /* The new filter is an empty filter (i.e., display all packets).
1434 * so leave dfcode==NULL
1438 * We have a filter; make a copy of it (as we'll be saving it),
1439 * and try to compile it.
1441 dftext = g_strdup(dftext);
1442 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1443 /* The attempt failed; report an error. */
1444 simple_message_box(ESD_TYPE_ERROR, NULL,
1445 "See the help for a description of the display filter syntax.",
1446 "\"%s\" isn't a valid display filter: %s",
1454 if (dfcode == NULL) {
1455 /* Yes - free the filter text, and set it to null. */
1461 /* We have a valid filter. Replace the current filter. */
1462 g_free(cf->dfilter);
1463 cf->dfilter = dftext;
1464 g_get_current_time(&start_time);
1467 /* Now rescan the packet list, applying the new filter, but not
1468 throwing away information constructed on a previous pass. */
1469 if (cf->state != FILE_CLOSED) {
1470 if (dftext == NULL) {
1471 rescan_packets(cf, "Resetting", "Filter", FALSE);
1473 rescan_packets(cf, "Filtering", dftext, FALSE);
1477 /* Cleanup and release all dfilter resources */
1478 dfilter_free(dfcode);
1484 cf_reftime_packets(capture_file *cf)
1486 ref_time_packets(cf);
1490 cf_redissect_packets(capture_file *cf)
1492 if (cf->state != FILE_CLOSED) {
1493 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1498 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1499 struct wtap_pkthdr *phdr, Buffer *buf)
1503 gchar *display_basename;
1505 #ifdef WANT_PACKET_EDITOR
1506 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1507 if (G_UNLIKELY(fdata->file_off == -1)) {
1508 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1511 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1515 *phdr = frame->phdr;
1516 ws_buffer_assure_space(buf, frame->phdr.caplen);
1517 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1522 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1523 display_basename = g_filename_display_basename(cf->filename);
1526 case WTAP_ERR_BAD_FILE:
1527 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1528 display_basename, wtap_strerror(err),
1529 err_info != NULL ? err_info : "no information supplied");
1534 simple_error_message_box(
1535 "An error occurred while reading from the file \"%s\": %s.",
1536 display_basename, wtap_strerror(err));
1539 g_free(display_basename);
1546 cf_read_record(capture_file *cf, frame_data *fdata)
1548 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1551 /* Rescan the list of packets, reconstructing the CList.
1553 "action" describes why we're doing this; it's used in the progress
1556 "action_item" describes what we're doing; it's used in the progress
1559 "redissect" is TRUE if we need to make the dissectors reconstruct
1560 any state information they have (because a preference that affects
1561 some dissector has changed, meaning some dissector might construct
1562 its state differently from the way it was constructed the last time). */
1564 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1566 /* Rescan packets new packet list */
1569 progdlg_t *progbar = NULL;
1571 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1572 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1573 gboolean selected_frame_seen;
1575 GTimeVal start_time;
1576 gchar status_str[100];
1577 int progbar_nextstep;
1578 int progbar_quantum;
1582 gboolean create_proto_tree;
1584 gboolean add_to_packet_list = FALSE;
1586 guint32 frames_count;
1588 /* Compile the current display filter.
1589 * We assume this will not fail since cf->dfilter is only set in
1590 * cf_filter IFF the filter was valid.
1592 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1593 g_assert(!cf->dfilter || (compiled && dfcode));
1595 /* Get the union of the flags for all tap listeners. */
1596 tap_flags = union_of_tap_listener_flags();
1597 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1599 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1601 reset_tap_listeners();
1602 /* Which frame, if any, is the currently selected frame?
1603 XXX - should the selected frame or the focus frame be the "current"
1604 frame, that frame being the one from which "Find Frame" searches
1606 selected_frame = cf->current_frame;
1608 /* Mark frame num as not found */
1609 selected_frame_num = -1;
1611 /* Freeze the packet list while we redo it, so we don't get any
1612 screen updates while it happens. */
1613 packet_list_freeze();
1616 /* We need to re-initialize all the state information that protocols
1617 keep, because some preference that controls a dissector has changed,
1618 which might cause the state information to be constructed differently
1619 by that dissector. */
1621 /* We might receive new packets while redissecting, and we don't
1622 want to dissect those before their time. */
1623 cf->redissecting = TRUE;
1625 /* 'reset' dissection session */
1626 epan_dissect_free(cf->edt);
1628 epan_free(cf->epan);
1629 cf->epan = ws_epan_new(cf);
1630 cf->cinfo.epan = cf->epan;
1632 /* We need to redissect the packets so we have to discard our old
1633 * packet list store. */
1634 packet_list_clear();
1635 add_to_packet_list = TRUE;
1638 /* We don't yet know which will be the first and last frames displayed. */
1639 cf->first_displayed = 0;
1640 cf->last_displayed = 0;
1642 /* We currently don't display any packets */
1643 cf->displayed_count = 0;
1645 /* Iterate through the list of frames. Call a routine for each frame
1646 to check whether it should be displayed and, if so, add it to
1647 the display list. */
1649 cf->prev_dis = NULL;
1650 cf->prev_cap = NULL;
1653 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1655 /* Update the progress bar when it gets to this value. */
1656 progbar_nextstep = 0;
1657 /* When we reach the value that triggers a progress bar update,
1658 bump that value by this amount. */
1659 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1660 /* Count of packets at which we've looked. */
1662 /* Progress so far. */
1665 cf->stop_flag = FALSE;
1666 g_get_current_time(&start_time);
1668 /* no previous row yet */
1669 prev_frame_num = -1;
1672 preceding_frame_num = -1;
1673 preceding_frame = NULL;
1674 following_frame_num = -1;
1675 following_frame = NULL;
1677 selected_frame_seen = FALSE;
1679 frames_count = cf->count;
1681 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1683 for (framenum = 1; framenum <= frames_count; framenum++) {
1684 fdata = frame_data_sequence_find(cf->frames, framenum);
1686 /* Create the progress bar if necessary.
1687 We check on every iteration of the loop, so that it takes no
1688 longer than the standard time to create it (otherwise, for a
1689 large file, we might take considerably longer than that standard
1690 time in order to get to the next progress bar step). */
1691 if (progbar == NULL)
1692 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1697 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1698 when we update it, we have to run the GTK+ main loop to get it
1699 to repaint what's pending, and doing so may involve an "ioctl()"
1700 to see if there's any pending input from an X server, and doing
1701 that for every packet can be costly, especially on a big file. */
1702 if (count >= progbar_nextstep) {
1703 /* let's not divide by zero. I should never be started
1704 * with count == 0, so let's assert that
1706 g_assert(cf->count > 0);
1707 progbar_val = (gfloat) count / frames_count;
1709 if (progbar != NULL) {
1710 g_snprintf(status_str, sizeof(status_str),
1711 "%4u of %u frames", count, frames_count);
1712 update_progress_dlg(progbar, progbar_val, status_str);
1715 progbar_nextstep += progbar_quantum;
1718 if (cf->stop_flag) {
1719 /* Well, the user decided to abort the filtering. Just stop.
1721 XXX - go back to the previous filter? Users probably just
1722 want not to wait for a filtering operation to finish;
1723 unless we cancel by having no filter, reverting to the
1724 previous filter will probably be even more expensive than
1725 continuing the filtering, as it involves going back to the
1726 beginning and filtering, and even with no filter we currently
1727 have to re-generate the entire clist, which is also expensive.
1729 I'm not sure what Network Monitor does, but it doesn't appear
1730 to give you an unfiltered display if you cancel. */
1737 /* Since all state for the frame was destroyed, mark the frame
1738 * as not visited, free the GSList referring to the state
1739 * data (the per-frame data itself was freed by
1740 * "init_dissection()"), and null out the GSList pointer. */
1741 frame_data_reset(fdata);
1742 frames_count = cf->count;
1745 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1746 fdata->flags.dependent_of_displayed = 0;
1748 if (!cf_read_record(cf, fdata))
1749 break; /* error reading the frame */
1751 /* If the previous frame is displayed, and we haven't yet seen the
1752 selected frame, remember that frame - it's the closest one we've
1753 yet seen before the selected frame. */
1754 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1755 preceding_frame_num = prev_frame_num;
1756 preceding_frame = prev_frame;
1759 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1761 ws_buffer_start_ptr(&cf->buf),
1762 add_to_packet_list);
1764 /* If this frame is displayed, and this is the first frame we've
1765 seen displayed after the selected frame, remember this frame -
1766 it's the closest one we've yet seen at or after the selected
1768 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1769 following_frame_num = fdata->num;
1770 following_frame = fdata;
1772 if (fdata == selected_frame) {
1773 selected_frame_seen = TRUE;
1774 if (fdata->flags.passed_dfilter)
1775 selected_frame_num = fdata->num;
1778 /* Remember this frame - it'll be the previous frame
1779 on the next pass through the loop. */
1780 prev_frame_num = fdata->num;
1784 epan_dissect_cleanup(&edt);
1786 /* We are done redissecting the packet list. */
1787 cf->redissecting = FALSE;
1790 frames_count = cf->count;
1791 /* Clear out what remains of the visited flags and per-frame data
1794 XXX - that may cause various forms of bogosity when dissecting
1795 these frames, as they won't have been seen by this sequential
1796 pass, but the only alternative I see is to keep scanning them
1797 even though the user requested that the scan stop, and that
1798 would leave the user stuck with an Wireshark grinding on
1799 until it finishes. Should we just stick them with that? */
1800 for (; framenum <= frames_count; framenum++) {
1801 fdata = frame_data_sequence_find(cf->frames, framenum);
1802 frame_data_reset(fdata);
1806 /* We're done filtering the packets; destroy the progress bar if it
1808 if (progbar != NULL)
1809 destroy_progress_dlg(progbar);
1811 /* Unfreeze the packet list. */
1812 if (!add_to_packet_list)
1813 packet_list_recreate_visible_rows();
1815 /* Compute the time it took to filter the file */
1816 compute_elapsed(cf, &start_time);
1820 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1822 if (selected_frame_num == -1) {
1823 /* The selected frame didn't pass the filter. */
1824 if (selected_frame == NULL) {
1825 /* That's because there *was* no selected frame. Make the first
1826 displayed frame the current frame. */
1827 selected_frame_num = 0;
1829 /* Find the nearest displayed frame to the selected frame (whether
1830 it's before or after that frame) and make that the current frame.
1831 If the next and previous displayed frames are equidistant from the
1832 selected frame, choose the next one. */
1833 g_assert(following_frame == NULL ||
1834 following_frame->num >= selected_frame->num);
1835 g_assert(preceding_frame == NULL ||
1836 preceding_frame->num <= selected_frame->num);
1837 if (following_frame == NULL) {
1838 /* No frame after the selected frame passed the filter, so we
1839 have to select the last displayed frame before the selected
1841 selected_frame_num = preceding_frame_num;
1842 selected_frame = preceding_frame;
1843 } else if (preceding_frame == NULL) {
1844 /* No frame before the selected frame passed the filter, so we
1845 have to select the first displayed frame after the selected
1847 selected_frame_num = following_frame_num;
1848 selected_frame = following_frame;
1850 /* Frames before and after the selected frame passed the filter, so
1851 we'll select the previous frame */
1852 selected_frame_num = preceding_frame_num;
1853 selected_frame = preceding_frame;
1858 if (selected_frame_num == -1) {
1859 /* There are no frames displayed at all. */
1860 cf_unselect_packet(cf);
1862 /* Either the frame that was selected passed the filter, or we've
1863 found the nearest displayed frame to that frame. Select it, make
1864 it the focus row, and make it visible. */
1865 /* Set to invalid to force update of packet list and packet details */
1866 cf->current_row = -1;
1867 if (selected_frame_num == 0) {
1868 packet_list_select_first_row();
1870 if (!packet_list_select_row_from_data(selected_frame)) {
1871 /* We didn't find a row corresponding to this frame.
1872 This means that the frame isn't being displayed currently,
1873 so we can't select it. */
1874 simple_message_box(ESD_TYPE_INFO, NULL,
1875 "The capture file is probably not fully dissected.",
1876 "End of capture exceeded.");
1881 /* Cleanup and release all dfilter resources */
1882 dfilter_free(dfcode);
1887 * Scan trough all frame data and recalculate the ref time
1888 * without rereading the file.
1889 * XXX - do we need a progres bar or is this fast enough?
1892 ref_time_packets(capture_file *cf)
1899 cf->prev_dis = NULL;
1902 for (framenum = 1; framenum <= cf->count; framenum++) {
1903 fdata = frame_data_sequence_find(cf->frames, framenum);
1905 /* just add some value here until we know if it is being displayed or not */
1906 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1912 /* If we don't have the time stamp of the first packet in the
1913 capture, it's because this is the first packet. Save the time
1914 stamp of this packet as the time stamp of the first packet. */
1915 if (cf->ref == NULL)
1917 /* if this frames is marked as a reference time frame, reset
1918 firstsec and firstusec to this frame */
1919 if (fdata->flags.ref_time)
1922 /* If we don't have the time stamp of the previous displayed packet,
1923 it's because this is the first displayed packet. Save the time
1924 stamp of this packet as the time stamp of the previous displayed
1926 if (cf->prev_dis == NULL) {
1927 cf->prev_dis = fdata;
1930 /* Get the time elapsed between the first packet and this packet. */
1931 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1932 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1934 /* If it's greater than the current elapsed time, set the elapsed time
1935 to it (we check for "greater than" so as not to be confused by
1936 time moving backwards). */
1937 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1938 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1939 cf->elapsed_time = rel_ts;
1942 /* If this frame is displayed, get the time elapsed between the
1943 previous displayed packet and this packet. */
1944 if ( fdata->flags.passed_dfilter ) {
1945 fdata->prev_dis_num = cf->prev_dis->num;
1946 cf->prev_dis = fdata;
1952 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1953 /* This frame either passed the display filter list or is marked as
1954 a time reference frame. All time reference frames are displayed
1955 even if they don't pass the display filter */
1956 if (fdata->flags.ref_time) {
1957 /* if this was a TIME REF frame we should reset the cum_bytes field */
1958 cf->cum_bytes = fdata->pkt_len;
1959 fdata->cum_bytes = cf->cum_bytes;
1961 /* increase cum_bytes with this packets length */
1962 cf->cum_bytes += fdata->pkt_len;
1975 process_specified_records(capture_file *cf, packet_range_t *range,
1976 const char *string1, const char *string2, gboolean terminate_is_stop,
1977 gboolean (*callback)(capture_file *, frame_data *,
1978 struct wtap_pkthdr *, const guint8 *, void *),
1979 void *callback_args)
1984 psp_return_t ret = PSP_FINISHED;
1986 progdlg_t *progbar = NULL;
1989 GTimeVal progbar_start_time;
1990 gchar progbar_status_str[100];
1991 int progbar_nextstep;
1992 int progbar_quantum;
1993 range_process_e process_this;
1994 struct wtap_pkthdr phdr;
1996 wtap_phdr_init(&phdr);
1997 ws_buffer_init(&buf, 1500);
1999 /* Update the progress bar when it gets to this value. */
2000 progbar_nextstep = 0;
2001 /* When we reach the value that triggers a progress bar update,
2002 bump that value by this amount. */
2003 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2004 /* Count of packets at which we've looked. */
2006 /* Progress so far. */
2009 cf->stop_flag = FALSE;
2010 g_get_current_time(&progbar_start_time);
2013 packet_range_process_init(range);
2015 /* Iterate through all the packets, printing the packets that
2016 were selected by the current display filter. */
2017 for (framenum = 1; framenum <= cf->count; framenum++) {
2018 fdata = frame_data_sequence_find(cf->frames, framenum);
2020 /* Create the progress bar if necessary.
2021 We check on every iteration of the loop, so that it takes no
2022 longer than the standard time to create it (otherwise, for a
2023 large file, we might take considerably longer than that standard
2024 time in order to get to the next progress bar step). */
2025 if (progbar == NULL)
2026 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2029 &progbar_start_time,
2032 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2033 when we update it, we have to run the GTK+ main loop to get it
2034 to repaint what's pending, and doing so may involve an "ioctl()"
2035 to see if there's any pending input from an X server, and doing
2036 that for every packet can be costly, especially on a big file. */
2037 if (progbar_count >= progbar_nextstep) {
2038 /* let's not divide by zero. I should never be started
2039 * with count == 0, so let's assert that
2041 g_assert(cf->count > 0);
2042 progbar_val = (gfloat) progbar_count / cf->count;
2044 if (progbar != NULL) {
2045 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2046 "%4u of %u packets", progbar_count, cf->count);
2047 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2050 progbar_nextstep += progbar_quantum;
2053 if (cf->stop_flag) {
2054 /* Well, the user decided to abort the operation. Just stop,
2055 and arrange to return PSP_STOPPED to our caller, so they know
2056 it was stopped explicitly. */
2063 if (range != NULL) {
2064 /* do we have to process this packet? */
2065 process_this = packet_range_process_packet(range, fdata);
2066 if (process_this == range_process_next) {
2067 /* this packet uninteresting, continue with next one */
2069 } else if (process_this == range_processing_finished) {
2070 /* all interesting packets processed, stop the loop */
2075 /* Get the packet */
2076 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2077 /* Attempt to get the packet failed. */
2081 /* Process the packet */
2082 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2083 /* Callback failed. We assume it reported the error appropriately. */
2089 /* We're done printing the packets; destroy the progress bar if
2091 if (progbar != NULL)
2092 destroy_progress_dlg(progbar);
2094 wtap_phdr_cleanup(&phdr);
2095 ws_buffer_free(&buf);
2103 } retap_callback_args_t;
2106 retap_packet(capture_file *cf, frame_data *fdata,
2107 struct wtap_pkthdr *phdr, const guint8 *pd,
2110 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2112 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2113 epan_dissect_reset(&args->edt);
2119 cf_retap_packets(capture_file *cf)
2121 packet_range_t range;
2122 retap_callback_args_t callback_args;
2123 gboolean construct_protocol_tree;
2124 gboolean filtering_tap_listeners;
2128 /* Presumably the user closed the capture file. */
2130 return CF_READ_ABORTED;
2133 cf_callback_invoke(cf_cb_file_retap_started, cf);
2135 /* Do we have any tap listeners with filters? */
2136 filtering_tap_listeners = have_filtering_tap_listeners();
2138 tap_flags = union_of_tap_listener_flags();
2140 /* If any tap listeners have filters, or require the protocol tree,
2141 construct the protocol tree. */
2142 construct_protocol_tree = filtering_tap_listeners ||
2143 (tap_flags & TL_REQUIRES_PROTO_TREE);
2145 /* If any tap listeners require the columns, construct them. */
2146 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2148 /* Reset the tap listeners. */
2149 reset_tap_listeners();
2151 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2153 /* Iterate through the list of packets, dissecting all packets and
2154 re-running the taps. */
2155 packet_range_init(&range, cf);
2156 packet_range_process_init(&range);
2158 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2159 "all packets", TRUE, retap_packet,
2162 epan_dissect_cleanup(&callback_args.edt);
2164 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2168 /* Completed successfully. */
2172 /* Well, the user decided to abort the refiltering.
2173 Return CF_READ_ABORTED so our caller knows they did that. */
2174 return CF_READ_ABORTED;
2177 /* Error while retapping. */
2178 return CF_READ_ERROR;
2181 g_assert_not_reached();
2186 print_args_t *print_args;
2187 gboolean print_header_line;
2188 char *header_line_buf;
2189 int header_line_buf_len;
2190 gboolean print_formfeed;
2191 gboolean print_separator;
2195 int num_visible_cols;
2198 } print_callback_args_t;
2201 print_packet(capture_file *cf, frame_data *fdata,
2202 struct wtap_pkthdr *phdr, const guint8 *pd,
2205 print_callback_args_t *args = (print_callback_args_t *)argsp;
2211 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2212 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2213 col_item_t* col_item;
2215 /* Fill in the column information if we're printing the summary
2217 if (args->print_args->print_summary) {
2218 col_custom_prime_edt(&args->edt, &cf->cinfo);
2219 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2220 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2222 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2224 if (args->print_formfeed) {
2225 if (!new_page(args->print_args->stream))
2228 if (args->print_separator) {
2229 if (!print_line(args->print_args->stream, 0, ""))
2235 * We generate bookmarks, if the output format supports them.
2236 * The name is "__frameN__".
2238 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2240 if (args->print_args->print_summary) {
2241 if (!args->print_args->print_col_headings)
2242 args->print_header_line = FALSE;
2243 if (args->print_header_line) {
2244 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2246 args->print_header_line = FALSE; /* we might not need to print any more */
2248 cp = &args->line_buf[0];
2250 for (i = 0; i < args->num_visible_cols; i++) {
2251 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2252 /* Find the length of the string for this column. */
2253 column_len = (int) strlen(col_item->col_data);
2254 if (args->col_widths[i] > column_len)
2255 column_len = args->col_widths[i];
2257 /* Make sure there's room in the line buffer for the column; if not,
2258 double its length. */
2259 line_len += column_len + 1; /* "+1" for space */
2260 if (line_len > args->line_buf_len) {
2261 cp_off = (int) (cp - args->line_buf);
2262 args->line_buf_len = 2 * line_len;
2263 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2264 cp = args->line_buf + cp_off;
2267 /* Right-justify the packet number column. */
2268 if (col_item->col_fmt == COL_NUMBER)
2269 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2271 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2273 if (i != args->num_visible_cols - 1)
2279 * Generate a bookmark, using the summary line as the title.
2281 if (!print_bookmark(args->print_args->stream, bookmark_name,
2285 if (!print_line(args->print_args->stream, 0, args->line_buf))
2289 * Generate a bookmark, using "Frame N" as the title, as we're not
2290 * printing the summary line.
2292 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2293 if (!print_bookmark(args->print_args->stream, bookmark_name,
2296 } /* if (print_summary) */
2298 if (args->print_args->print_dissections != print_dissections_none) {
2299 if (args->print_args->print_summary) {
2300 /* Separate the summary line from the tree with a blank line. */
2301 if (!print_line(args->print_args->stream, 0, ""))
2305 /* Print the information in that tree. */
2306 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2309 /* Print a blank line if we print anything after this (aka more than one packet). */
2310 args->print_separator = TRUE;
2312 /* Print a header line if we print any more packet summaries */
2313 if (args->print_args->print_col_headings)
2314 args->print_header_line = TRUE;
2317 if (args->print_args->print_hex) {
2318 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2319 if (!print_line(args->print_args->stream, 0, ""))
2322 /* Print the full packet data as hex. */
2323 if (!print_hex_data(args->print_args->stream, &args->edt))
2326 /* Print a blank line if we print anything after this (aka more than one packet). */
2327 args->print_separator = TRUE;
2329 /* Print a header line if we print any more packet summaries */
2330 if (args->print_args->print_col_headings)
2331 args->print_header_line = TRUE;
2332 } /* if (args->print_args->print_dissections != print_dissections_none) */
2334 epan_dissect_reset(&args->edt);
2336 /* do we want to have a formfeed between each packet from now on? */
2337 if (args->print_args->print_formfeed) {
2338 args->print_formfeed = TRUE;
2344 epan_dissect_reset(&args->edt);
2349 cf_print_packets(capture_file *cf, print_args_t *print_args)
2351 print_callback_args_t callback_args;
2354 int i, cp_off, column_len, line_len;
2355 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2359 gboolean proto_tree_needed;
2361 callback_args.print_args = print_args;
2362 callback_args.print_header_line = print_args->print_col_headings;
2363 callback_args.header_line_buf = NULL;
2364 callback_args.header_line_buf_len = 256;
2365 callback_args.print_formfeed = FALSE;
2366 callback_args.print_separator = FALSE;
2367 callback_args.line_buf = NULL;
2368 callback_args.line_buf_len = 256;
2369 callback_args.col_widths = NULL;
2370 callback_args.num_visible_cols = 0;
2371 callback_args.visible_cols = NULL;
2373 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2374 destroy_print_stream(print_args->stream);
2375 return CF_PRINT_WRITE_ERROR;
2378 if (print_args->print_summary) {
2379 /* We're printing packet summaries. Allocate the header line buffer
2380 and get the column widths. */
2381 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2383 /* Find the number of visible columns and the last visible column */
2384 for (i = 0; i < prefs.num_cols; i++) {
2386 clp = g_list_nth(prefs.col_list, i);
2387 if (clp == NULL) /* Sanity check, Invalid column requested */
2390 cfmt = (fmt_data *) clp->data;
2391 if (cfmt->visible) {
2393 last_visible_col = i;
2397 /* Find the widths for each of the columns - maximum of the
2398 width of the title and the width of the data - and construct
2399 a buffer with a line containing the column titles. */
2400 callback_args.num_visible_cols = num_visible_col;
2401 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2402 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2403 cp = &callback_args.header_line_buf[0];
2405 visible_col_count = 0;
2406 for (i = 0; i < cf->cinfo.num_cols; i++) {
2408 clp = g_list_nth(prefs.col_list, i);
2409 if (clp == NULL) /* Sanity check, Invalid column requested */
2412 cfmt = (fmt_data *) clp->data;
2413 if (cfmt->visible == FALSE)
2416 /* Save the order of visible columns */
2417 callback_args.visible_cols[visible_col_count] = i;
2419 /* Don't pad the last column. */
2420 if (i == last_visible_col)
2421 callback_args.col_widths[visible_col_count] = 0;
2423 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2424 data_width = get_column_char_width(get_column_format(i));
2425 if (data_width > callback_args.col_widths[visible_col_count])
2426 callback_args.col_widths[visible_col_count] = data_width;
2429 /* Find the length of the string for this column. */
2430 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2431 if (callback_args.col_widths[i] > column_len)
2432 column_len = callback_args.col_widths[visible_col_count];
2434 /* Make sure there's room in the line buffer for the column; if not,
2435 double its length. */
2436 line_len += column_len + 1; /* "+1" for space */
2437 if (line_len > callback_args.header_line_buf_len) {
2438 cp_off = (int) (cp - callback_args.header_line_buf);
2439 callback_args.header_line_buf_len = 2 * line_len;
2440 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2441 callback_args.header_line_buf_len + 1);
2442 cp = callback_args.header_line_buf + cp_off;
2445 /* Right-justify the packet number column. */
2446 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2447 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2449 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2451 if (i != cf->cinfo.num_cols - 1)
2454 visible_col_count++;
2458 /* Now start out the main line buffer with the same length as the
2459 header line buffer. */
2460 callback_args.line_buf_len = callback_args.header_line_buf_len;
2461 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2462 } /* if (print_summary) */
2464 /* Create the protocol tree, and make it visible, if we're printing
2465 the dissection or the hex data.
2466 XXX - do we need it if we're just printing the hex data? */
2468 callback_args.print_args->print_dissections != print_dissections_none ||
2469 callback_args.print_args->print_hex ||
2470 have_custom_cols(&cf->cinfo);
2471 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2473 /* Iterate through the list of packets, printing the packets we were
2475 ret = process_specified_records(cf, &print_args->range, "Printing",
2476 "selected packets", TRUE, print_packet,
2478 epan_dissect_cleanup(&callback_args.edt);
2479 g_free(callback_args.header_line_buf);
2480 g_free(callback_args.line_buf);
2481 g_free(callback_args.col_widths);
2482 g_free(callback_args.visible_cols);
2487 /* Completed successfully. */
2491 /* Well, the user decided to abort the printing.
2493 XXX - note that what got generated before they did that
2494 will get printed if we're piping to a print program; we'd
2495 have to write to a file and then hand that to the print
2496 program to make it actually not print anything. */
2500 /* Error while printing.
2502 XXX - note that what got generated before they did that
2503 will get printed if we're piping to a print program; we'd
2504 have to write to a file and then hand that to the print
2505 program to make it actually not print anything. */
2506 destroy_print_stream(print_args->stream);
2507 return CF_PRINT_WRITE_ERROR;
2510 if (!print_finale(print_args->stream)) {
2511 destroy_print_stream(print_args->stream);
2512 return CF_PRINT_WRITE_ERROR;
2515 if (!destroy_print_stream(print_args->stream))
2516 return CF_PRINT_WRITE_ERROR;
2524 } write_packet_callback_args_t;
2527 write_pdml_packet(capture_file *cf, frame_data *fdata,
2528 struct wtap_pkthdr *phdr, const guint8 *pd,
2531 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2533 /* Create the protocol tree, but don't fill in the column information. */
2534 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2536 /* Write out the information in that tree. */
2537 write_pdml_proto_tree(&args->edt, args->fh);
2539 epan_dissect_reset(&args->edt);
2541 return !ferror(args->fh);
2545 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2547 write_packet_callback_args_t callback_args;
2551 fh = ws_fopen(print_args->file, "w");
2553 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2555 write_pdml_preamble(fh, cf->filename);
2558 return CF_PRINT_WRITE_ERROR;
2561 callback_args.fh = fh;
2562 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2564 /* Iterate through the list of packets, printing the packets we were
2566 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2567 "selected packets", TRUE,
2568 write_pdml_packet, &callback_args);
2570 epan_dissect_cleanup(&callback_args.edt);
2575 /* Completed successfully. */
2579 /* Well, the user decided to abort the printing. */
2583 /* Error while printing. */
2585 return CF_PRINT_WRITE_ERROR;
2588 write_pdml_finale(fh);
2591 return CF_PRINT_WRITE_ERROR;
2594 /* XXX - check for an error */
2601 write_psml_packet(capture_file *cf, frame_data *fdata,
2602 struct wtap_pkthdr *phdr, const guint8 *pd,
2605 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2607 /* Fill in the column information */
2608 col_custom_prime_edt(&args->edt, &cf->cinfo);
2609 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2610 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2612 /* Write out the column information. */
2613 write_psml_columns(&args->edt, args->fh);
2615 epan_dissect_reset(&args->edt);
2617 return !ferror(args->fh);
2621 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2623 write_packet_callback_args_t callback_args;
2627 gboolean proto_tree_needed;
2629 fh = ws_fopen(print_args->file, "w");
2631 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2633 write_psml_preamble(&cf->cinfo, fh);
2636 return CF_PRINT_WRITE_ERROR;
2639 callback_args.fh = fh;
2641 /* Fill in the column information, only create the protocol tree
2642 if having custom columns. */
2643 proto_tree_needed = have_custom_cols(&cf->cinfo);
2644 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2646 /* Iterate through the list of packets, printing the packets we were
2648 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2649 "selected packets", TRUE,
2650 write_psml_packet, &callback_args);
2652 epan_dissect_cleanup(&callback_args.edt);
2657 /* Completed successfully. */
2661 /* Well, the user decided to abort the printing. */
2665 /* Error while printing. */
2667 return CF_PRINT_WRITE_ERROR;
2670 write_psml_finale(fh);
2673 return CF_PRINT_WRITE_ERROR;
2676 /* XXX - check for an error */
2683 write_csv_packet(capture_file *cf, frame_data *fdata,
2684 struct wtap_pkthdr *phdr, const guint8 *pd,
2687 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2689 /* Fill in the column information */
2690 col_custom_prime_edt(&args->edt, &cf->cinfo);
2691 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2692 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2694 /* Write out the column information. */
2695 write_csv_columns(&args->edt, args->fh);
2697 epan_dissect_reset(&args->edt);
2699 return !ferror(args->fh);
2703 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2705 write_packet_callback_args_t callback_args;
2706 gboolean proto_tree_needed;
2710 fh = ws_fopen(print_args->file, "w");
2712 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2714 write_csv_column_titles(&cf->cinfo, fh);
2717 return CF_PRINT_WRITE_ERROR;
2720 callback_args.fh = fh;
2722 /* only create the protocol tree if having custom columns. */
2723 proto_tree_needed = have_custom_cols(&cf->cinfo);
2724 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2726 /* Iterate through the list of packets, printing the packets we were
2728 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2729 "selected packets", TRUE,
2730 write_csv_packet, &callback_args);
2732 epan_dissect_cleanup(&callback_args.edt);
2737 /* Completed successfully. */
2741 /* Well, the user decided to abort the printing. */
2745 /* Error while printing. */
2747 return CF_PRINT_WRITE_ERROR;
2750 /* XXX - check for an error */
2757 carrays_write_packet(capture_file *cf, frame_data *fdata,
2758 struct wtap_pkthdr *phdr,
2759 const guint8 *pd, void *argsp)
2761 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2763 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2764 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2765 epan_dissect_reset(&args->edt);
2767 return !ferror(args->fh);
2771 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2773 write_packet_callback_args_t callback_args;
2777 fh = ws_fopen(print_args->file, "w");
2780 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2784 return CF_PRINT_WRITE_ERROR;
2787 callback_args.fh = fh;
2788 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2790 /* Iterate through the list of packets, printing the packets we were
2792 ret = process_specified_records(cf, &print_args->range,
2794 "selected packets", TRUE,
2795 carrays_write_packet, &callback_args);
2797 epan_dissect_cleanup(&callback_args.edt);
2801 /* Completed successfully. */
2804 /* Well, the user decided to abort the printing. */
2807 /* Error while printing. */
2809 return CF_PRINT_WRITE_ERROR;
2817 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2818 search_direction dir)
2822 mdata.string = string;
2823 mdata.string_len = strlen(string);
2824 return find_packet(cf, match_protocol_tree, &mdata, dir);
2828 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2830 mdata->frame_matched = FALSE;
2831 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2832 mdata->string_len = strlen(mdata->string);
2834 /* Iterate through all the nodes looking for matching text */
2835 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2836 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2840 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2842 match_data *mdata = (match_data *)criterion;
2845 /* Load the frame's data. */
2846 if (!cf_read_record(cf, fdata)) {
2847 /* Attempt to get the packet failed. */
2851 /* Construct the protocol tree, including the displayed text */
2852 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2853 /* We don't need the column information */
2854 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2856 /* Iterate through all the nodes, seeing if they have text that matches. */
2858 mdata->frame_matched = FALSE;
2859 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2860 epan_dissect_cleanup(&edt);
2861 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2865 match_subtree_text(proto_node *node, gpointer data)
2867 match_data *mdata = (match_data *) data;
2868 const gchar *string = mdata->string;
2869 size_t string_len = mdata->string_len;
2870 capture_file *cf = mdata->cf;
2871 field_info *fi = PNODE_FINFO(node);
2872 gchar label_str[ITEM_LABEL_LENGTH];
2879 /* dissection with an invisible proto tree? */
2882 if (mdata->frame_matched) {
2883 /* We already had a match; don't bother doing any more work. */
2887 /* Don't match invisible entries. */
2888 if (PROTO_ITEM_IS_HIDDEN(node))
2891 /* was a free format label produced? */
2893 label_ptr = fi->rep->representation;
2895 /* no, make a generic label */
2896 label_ptr = label_str;
2897 proto_item_fill_label(fi, label_str);
2900 /* Does that label match? */
2901 label_len = strlen(label_ptr);
2902 for (i = 0; i < label_len; i++) {
2903 c_char = label_ptr[i];
2905 c_char = g_ascii_toupper(c_char);
2906 if (c_char == string[c_match]) {
2908 if (c_match == string_len) {
2909 /* No need to look further; we have a match */
2910 mdata->frame_matched = TRUE;
2918 /* Recurse into the subtree, if it exists */
2919 if (node->first_child != NULL)
2920 proto_tree_children_foreach(node, match_subtree_text, mdata);
2924 cf_find_packet_summary_line(capture_file *cf, const char *string,
2925 search_direction dir)
2929 mdata.string = string;
2930 mdata.string_len = strlen(string);
2931 return find_packet(cf, match_summary_line, &mdata, dir);
2935 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2937 match_data *mdata = (match_data *)criterion;
2938 const gchar *string = mdata->string;
2939 size_t string_len = mdata->string_len;
2941 const char *info_column;
2942 size_t info_column_len;
2943 match_result result = MR_NOTMATCHED;
2949 /* Load the frame's data. */
2950 if (!cf_read_record(cf, fdata)) {
2951 /* Attempt to get the packet failed. */
2955 /* Don't bother constructing the protocol tree */
2956 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
2957 /* Get the column information */
2958 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
2961 /* Find the Info column */
2962 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2963 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
2964 /* Found it. See if we match. */
2965 info_column = edt.pi.cinfo->columns[colx].col_data;
2966 info_column_len = strlen(info_column);
2967 for (i = 0; i < info_column_len; i++) {
2968 c_char = info_column[i];
2970 c_char = g_ascii_toupper(c_char);
2971 if (c_char == string[c_match]) {
2973 if (c_match == string_len) {
2974 result = MR_MATCHED;
2983 epan_dissect_cleanup(&edt);
2990 } cbs_t; /* "Counted byte string" */
2994 * The current match_* routines only support ASCII case insensitivity and don't
2995 * convert UTF-8 inputs to UTF-16 for matching.
2997 * We could modify them to use the GLib Unicode routines or the International
2998 * Components for Unicode library but it's not apparent that we could do so
2999 * without consuming a lot more CPU and memory or that searching would be
3000 * significantly better.
3004 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3005 search_direction dir)
3010 info.data_len = string_size;
3012 /* String or hex search? */
3014 /* String search - what type of string? */
3015 switch (cf->scs_type) {
3017 case SCS_NARROW_AND_WIDE:
3018 return find_packet(cf, match_narrow_and_wide, &info, dir);
3021 return find_packet(cf, match_narrow, &info, dir);
3024 return find_packet(cf, match_wide, &info, dir);
3027 g_assert_not_reached();
3031 return find_packet(cf, match_binary, &info, dir);
3035 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3037 cbs_t *info = (cbs_t *)criterion;
3038 const guint8 *ascii_text = info->data;
3039 size_t textlen = info->data_len;
3040 match_result result;
3047 /* Load the frame's data. */
3048 if (!cf_read_record(cf, fdata)) {
3049 /* Attempt to get the packet failed. */
3053 result = MR_NOTMATCHED;
3054 buf_len = fdata->cap_len;
3055 pd = ws_buffer_start_ptr(&cf->buf);
3057 while (i < buf_len) {
3060 c_char = g_ascii_toupper(c_char);
3061 if (c_char != '\0') {
3062 if (c_char == ascii_text[c_match]) {
3064 if (c_match == textlen) {
3065 result = MR_MATCHED;
3066 cf->search_pos = i; /* Save the position of the last character
3067 for highlighting the field. */
3072 g_assert(i>=c_match);
3073 i -= (guint32)c_match;
3083 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3086 cbs_t *info = (cbs_t *)criterion;
3087 const guint8 *ascii_text = info->data;
3088 size_t textlen = info->data_len;
3089 match_result result;
3095 /* Load the frame's data. */
3096 if (!cf_read_record(cf, fdata)) {
3097 /* Attempt to get the packet failed. */
3101 result = MR_NOTMATCHED;
3102 buf_len = fdata->cap_len;
3103 pd = ws_buffer_start_ptr(&cf->buf);
3105 while (i < buf_len) {
3108 c_char = g_ascii_toupper(c_char);
3109 if (c_char == ascii_text[c_match]) {
3111 if (c_match == textlen) {
3112 result = MR_MATCHED;
3113 cf->search_pos = i; /* Save the position of the last character
3114 for highlighting the field. */
3119 g_assert(i>=c_match);
3120 i -= (guint32)c_match;
3130 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3132 cbs_t *info = (cbs_t *)criterion;
3133 const guint8 *ascii_text = info->data;
3134 size_t textlen = info->data_len;
3135 match_result result;
3142 /* Load the frame's data. */
3143 if (!cf_read_record(cf, fdata)) {
3144 /* Attempt to get the packet failed. */
3148 result = MR_NOTMATCHED;
3149 buf_len = fdata->cap_len;
3150 pd = ws_buffer_start_ptr(&cf->buf);
3152 while (i < buf_len) {
3155 c_char = g_ascii_toupper(c_char);
3156 if (c_char == ascii_text[c_match]) {
3158 if (c_match == textlen) {
3159 result = MR_MATCHED;
3160 cf->search_pos = i; /* Save the position of the last character
3161 for highlighting the field. */
3167 g_assert(i>=(c_match*2));
3168 i -= (guint32)c_match*2;
3177 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3179 cbs_t *info = (cbs_t *)criterion;
3180 const guint8 *binary_data = info->data;
3181 size_t datalen = info->data_len;
3182 match_result result;
3188 /* Load the frame's data. */
3189 if (!cf_read_record(cf, fdata)) {
3190 /* Attempt to get the packet failed. */
3194 result = MR_NOTMATCHED;
3195 buf_len = fdata->cap_len;
3196 pd = ws_buffer_start_ptr(&cf->buf);
3198 while (i < buf_len) {
3199 if (pd[i] == binary_data[c_match]) {
3201 if (c_match == datalen) {
3202 result = MR_MATCHED;
3203 cf->search_pos = i; /* Save the position of the last character
3204 for highlighting the field. */
3209 g_assert(i>=c_match);
3210 i -= (guint32)c_match;
3219 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3220 search_direction dir)
3222 return find_packet(cf, match_dfilter, sfcode, dir);
3226 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3227 search_direction dir)
3232 if (!dfilter_compile(filter, &sfcode, NULL)) {
3234 * XXX - this shouldn't happen, as the filter string is machine
3239 if (sfcode == NULL) {
3241 * XXX - this shouldn't happen, as the filter string is machine
3246 result = find_packet(cf, match_dfilter, sfcode, dir);
3247 dfilter_free(sfcode);
3252 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3254 dfilter_t *sfcode = (dfilter_t *)criterion;
3256 match_result result;
3258 /* Load the frame's data. */
3259 if (!cf_read_record(cf, fdata)) {
3260 /* Attempt to get the packet failed. */
3264 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3265 epan_dissect_prime_dfilter(&edt, sfcode);
3266 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3267 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3268 epan_dissect_cleanup(&edt);
3273 cf_find_packet_marked(capture_file *cf, search_direction dir)
3275 return find_packet(cf, match_marked, NULL, dir);
3279 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3281 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3285 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3287 return find_packet(cf, match_time_reference, NULL, dir);
3291 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3293 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3297 find_packet(capture_file *cf,
3298 match_result (*match_function)(capture_file *, frame_data *, void *),
3299 void *criterion, search_direction dir)
3301 frame_data *start_fd;
3304 frame_data *new_fd = NULL;
3305 progdlg_t *progbar = NULL;
3309 GTimeVal start_time;
3310 gchar status_str[100];
3311 int progbar_nextstep;
3312 int progbar_quantum;
3314 match_result result;
3316 start_fd = cf->current_frame;
3317 if (start_fd != NULL) {
3318 /* Iterate through the list of packets, starting at the packet we've
3319 picked, calling a routine to run the filter on the packet, see if
3320 it matches, and stop if so. */
3322 framenum = start_fd->num;
3324 /* Update the progress bar when it gets to this value. */
3325 progbar_nextstep = 0;
3326 /* When we reach the value that triggers a progress bar update,
3327 bump that value by this amount. */
3328 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3329 /* Progress so far. */
3332 cf->stop_flag = FALSE;
3333 g_get_current_time(&start_time);
3335 title = cf->sfilter?cf->sfilter:"";
3337 /* Create the progress bar if necessary.
3338 We check on every iteration of the loop, so that it takes no
3339 longer than the standard time to create it (otherwise, for a
3340 large file, we might take considerably longer than that standard
3341 time in order to get to the next progress bar step). */
3342 if (progbar == NULL)
3343 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3344 FALSE, &cf->stop_flag, &start_time, progbar_val);
3346 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3347 when we update it, we have to run the GTK+ main loop to get it
3348 to repaint what's pending, and doing so may involve an "ioctl()"
3349 to see if there's any pending input from an X server, and doing
3350 that for every packet can be costly, especially on a big file. */
3351 if (count >= progbar_nextstep) {
3352 /* let's not divide by zero. I should never be started
3353 * with count == 0, so let's assert that
3355 g_assert(cf->count > 0);
3357 progbar_val = (gfloat) count / cf->count;
3359 if (progbar != NULL) {
3360 g_snprintf(status_str, sizeof(status_str),
3361 "%4u of %u packets", count, cf->count);
3362 update_progress_dlg(progbar, progbar_val, status_str);
3365 progbar_nextstep += progbar_quantum;
3368 if (cf->stop_flag) {
3369 /* Well, the user decided to abort the search. Go back to the
3370 frame where we started. */
3375 /* Go past the current frame. */
3376 if (dir == SD_BACKWARD) {
3377 /* Go on to the previous frame. */
3378 if (framenum == 1) {
3380 * XXX - other apps have a bit more of a detailed message
3381 * for this, and instead of offering "OK" and "Cancel",
3382 * they offer things such as "Continue" and "Cancel";
3383 * we need an API for popping up alert boxes with
3384 * {Verb} and "Cancel".
3387 if (prefs.gui_find_wrap)
3389 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3390 framenum = cf->count; /* wrap around */
3394 statusbar_push_temporary_msg("Search reached the beginning.");
3395 framenum = start_fd->num; /* stay on previous packet */
3400 /* Go on to the next frame. */
3401 if (framenum == cf->count) {
3402 if (prefs.gui_find_wrap)
3404 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3405 framenum = 1; /* wrap around */
3409 statusbar_push_temporary_msg("Search reached the end.");
3410 framenum = start_fd->num; /* stay on previous packet */
3415 fdata = frame_data_sequence_find(cf->frames, framenum);
3419 /* Is this packet in the display? */
3420 if (fdata->flags.passed_dfilter) {
3421 /* Yes. Does it match the search criterion? */
3422 result = (*match_function)(cf, fdata, criterion);
3423 if (result == MR_ERROR) {
3424 /* Error; our caller has reported the error. Go back to the frame
3425 where we started. */
3428 } else if (result == MR_MATCHED) {
3429 /* Yes. Go to the new frame. */
3435 if (fdata == start_fd) {
3436 /* We're back to the frame we were on originally, and that frame
3437 doesn't match the search filter. The search failed. */
3442 /* We're done scanning the packets; destroy the progress bar if it
3444 if (progbar != NULL)
3445 destroy_progress_dlg(progbar);
3448 if (new_fd != NULL) {
3449 /* Find and select */
3450 cf->search_in_progress = TRUE;
3451 found = packet_list_select_row_from_data(new_fd);
3452 cf->search_in_progress = FALSE;
3453 cf->search_pos = 0; /* Reset the position */
3455 /* We didn't find a row corresponding to this frame.
3456 This means that the frame isn't being displayed currently,
3457 so we can't select it. */
3458 simple_message_box(ESD_TYPE_INFO, NULL,
3459 "The capture file is probably not fully dissected.",
3460 "End of capture exceeded.");
3463 return TRUE; /* success */
3465 return FALSE; /* failure */
3469 cf_goto_frame(capture_file *cf, guint fnumber)
3473 fdata = frame_data_sequence_find(cf->frames, fnumber);
3475 if (fdata == NULL) {
3476 /* we didn't find a packet with that packet number */
3477 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3478 return FALSE; /* we failed to go to that packet */
3480 if (!fdata->flags.passed_dfilter) {
3481 /* that packet currently isn't displayed */
3482 /* XXX - add it to the set of displayed packets? */
3483 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3484 return FALSE; /* we failed to go to that packet */
3487 if (!packet_list_select_row_from_data(fdata)) {
3488 /* We didn't find a row corresponding to this frame.
3489 This means that the frame isn't being displayed currently,
3490 so we can't select it. */
3491 simple_message_box(ESD_TYPE_INFO, NULL,
3492 "The capture file is probably not fully dissected.",
3493 "End of capture exceeded.");
3496 return TRUE; /* we got to that packet */
3500 cf_goto_top_frame(void)
3502 /* Find and select */
3503 packet_list_select_first_row();
3504 return TRUE; /* we got to that packet */
3508 cf_goto_bottom_frame(void)
3510 /* Find and select */
3511 packet_list_select_last_row();
3512 return TRUE; /* we got to that packet */
3516 * Go to frame specified by currently selected protocol tree item.
3519 cf_goto_framenum(capture_file *cf)
3521 header_field_info *hfinfo;
3524 if (cf->finfo_selected) {
3525 hfinfo = cf->finfo_selected->hfinfo;
3527 if (hfinfo->type == FT_FRAMENUM) {
3528 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3530 return cf_goto_frame(cf, framenum);
3537 /* Select the packet on a given row. */
3539 cf_select_packet(capture_file *cf, int row)
3541 epan_dissect_t *old_edt;
3544 /* Get the frame data struct pointer for this frame */
3545 fdata = packet_list_get_row_data(row);
3547 if (fdata == NULL) {
3548 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3549 the first entry is added to it by "real_insert_row()", that row
3550 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3551 our version and the vanilla GTK+ version).
3553 This means that a "select-row" signal is emitted; this causes
3554 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3557 "cf_select_packet()" fetches, above, the data associated with the
3558 row that was selected; however, as "gtk_clist_append()", which
3559 called "real_insert_row()", hasn't yet returned, we haven't yet
3560 associated any data with that row, so we get back a null pointer.
3562 We can't assume that there's only one frame in the frame list,
3563 either, as we may be filtering the display.
3565 We therefore assume that, if "row" is 0, i.e. the first row
3566 is being selected, and "cf->first_displayed" equals
3567 "cf->last_displayed", i.e. there's only one frame being
3568 displayed, that frame is the frame we want.
3570 This means we have to set "cf->first_displayed" and
3571 "cf->last_displayed" before adding the row to the
3572 GtkCList; see the comment in "add_packet_to_packet_list()". */
3574 if (row == 0 && cf->first_displayed == cf->last_displayed)
3575 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3578 /* If fdata _still_ isn't set simply give up. */
3579 if (fdata == NULL) {
3583 /* Get the data in that frame. */
3584 if (!cf_read_record (cf, fdata)) {
3588 /* Record that this frame is the current frame. */
3589 cf->current_frame = fdata;
3590 cf->current_row = row;
3593 /* Create the logical protocol tree. */
3594 /* We don't need the columns here. */
3595 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3597 tap_build_interesting(cf->edt);
3598 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3599 cf->current_frame, NULL);
3601 dfilter_macro_build_ftv_cache(cf->edt->tree);
3603 cf_callback_invoke(cf_cb_packet_selected, cf);
3605 if (old_edt != NULL)
3606 epan_dissect_free(old_edt);
3610 /* Unselect the selected packet, if any. */
3612 cf_unselect_packet(capture_file *cf)
3614 epan_dissect_t *old_edt = cf->edt;
3618 /* No packet is selected. */
3619 cf->current_frame = NULL;
3620 cf->current_row = 0;
3622 cf_callback_invoke(cf_cb_packet_unselected, cf);
3624 /* No protocol tree means no selected field. */
3625 cf_unselect_field(cf);
3627 /* Destroy the epan_dissect_t for the unselected packet. */
3628 if (old_edt != NULL)
3629 epan_dissect_free(old_edt);
3632 /* Unset the selected protocol tree field, if any. */
3634 cf_unselect_field(capture_file *cf)
3636 cf->finfo_selected = NULL;
3638 cf_callback_invoke(cf_cb_field_unselected, cf);
3642 * Mark a particular frame.
3645 cf_mark_frame(capture_file *cf, frame_data *frame)
3647 if (! frame->flags.marked) {
3648 frame->flags.marked = TRUE;
3649 if (cf->count > cf->marked_count)
3655 * Unmark a particular frame.
3658 cf_unmark_frame(capture_file *cf, frame_data *frame)
3660 if (frame->flags.marked) {
3661 frame->flags.marked = FALSE;
3662 if (cf->marked_count > 0)
3668 * Ignore a particular frame.
3671 cf_ignore_frame(capture_file *cf, frame_data *frame)
3673 if (! frame->flags.ignored) {
3674 frame->flags.ignored = TRUE;
3675 if (cf->count > cf->ignored_count)
3676 cf->ignored_count++;
3681 * Un-ignore a particular frame.
3684 cf_unignore_frame(capture_file *cf, frame_data *frame)
3686 if (frame->flags.ignored) {
3687 frame->flags.ignored = FALSE;
3688 if (cf->ignored_count > 0)
3689 cf->ignored_count--;
3694 * Read the comment in SHB block
3698 cf_read_shb_comment(capture_file *cf)
3700 /* Get info from SHB */
3701 return wtap_file_get_shb_comment(cf->wth);
3705 cf_update_capture_comment(capture_file *cf, gchar *comment)
3707 const gchar *shb_comment;
3709 /* Get info from SHB */
3710 shb_comment = wtap_file_get_shb_comment(cf->wth);
3712 /* See if the comment has changed or not */
3714 if (strcmp(shb_comment, comment) == 0) {
3720 /* The comment has changed, let's update it */
3721 wtap_write_shb_comment(cf->wth, comment);
3722 /* Mark the file as having unsaved changes */
3723 cf->unsaved_changes = TRUE;
3727 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3729 if (cf->frames_user_comments)
3730 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3737 cf_get_comment(capture_file *cf, const frame_data *fd)
3741 /* fetch user comment */
3742 if (fd->flags.has_user_comment)
3743 return g_strdup(cf_get_user_packet_comment(cf, fd));
3745 /* fetch phdr comment */
3746 if (fd->flags.has_phdr_comment) {
3747 struct wtap_pkthdr phdr; /* Packet header */
3748 Buffer buf; /* Packet data */
3750 wtap_phdr_init(&phdr);
3751 ws_buffer_init(&buf, 1500);
3753 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3754 { /* XXX, what we can do here? */ }
3756 comment = phdr.opt_comment;
3757 wtap_phdr_cleanup(&phdr);
3758 ws_buffer_free(&buf);
3765 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3767 const frame_data *fdata1 = (const frame_data *) a;
3768 const frame_data *fdata2 = (const frame_data *) b;
3770 return (fdata1->num < fdata2->num) ? -1 :
3771 (fdata1->num > fdata2->num) ? 1 :
3776 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3778 char *pkt_comment = cf_get_comment(cf, fd);
3780 /* Check if the comment has changed */
3781 if (!g_strcmp0(pkt_comment, new_comment)) {
3782 g_free(pkt_comment);
3785 g_free(pkt_comment);
3788 cf->packet_comment_count--;
3791 cf->packet_comment_count++;
3793 fd->flags.has_user_comment = TRUE;
3795 if (!cf->frames_user_comments)
3796 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3798 /* insert new packet comment */
3799 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3801 expert_update_comment_count(cf->packet_comment_count);
3803 /* OK, we have unsaved changes. */
3804 cf->unsaved_changes = TRUE;
3809 * What types of comments does this capture file have?
3812 cf_comment_types(capture_file *cf)
3814 guint32 comment_types = 0;
3816 if (cf_read_shb_comment(cf) != NULL)
3817 comment_types |= WTAP_COMMENT_PER_SECTION;
3818 if (cf->packet_comment_count != 0)
3819 comment_types |= WTAP_COMMENT_PER_PACKET;
3820 return comment_types;
3823 #ifdef WANT_PACKET_EDITOR
3825 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3836 modified_frame_data_free(gpointer data)
3838 modified_frame_data *mfd = (modified_frame_data *)data;
3845 * Give a frame new, edited data.
3848 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3849 struct wtap_pkthdr *phdr, guint8 *pd)
3851 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3856 if (cf->edited_frames == NULL)
3857 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3858 modified_frame_data_free);
3859 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3862 /* Mark the file as having unsaved changes */
3863 cf->unsaved_changes = TRUE;
3871 } save_callback_args_t;
3874 * Save a capture to a file, in a particular format, saving either
3875 * all packets, all currently-displayed packets, or all marked packets.
3877 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3878 * up a message box for the failure.
3881 save_record(capture_file *cf, frame_data *fdata,
3882 struct wtap_pkthdr *phdr, const guint8 *pd,
3885 save_callback_args_t *args = (save_callback_args_t *)argsp;
3886 struct wtap_pkthdr hdr;
3889 gchar *display_basename;
3890 const char *pkt_comment;
3892 if (fdata->flags.has_user_comment)
3893 pkt_comment = cf_get_user_packet_comment(cf, fdata);
3895 pkt_comment = phdr->opt_comment;
3897 /* init the wtap header for saving */
3898 /* TODO: reuse phdr */
3899 /* XXX - these are the only flags that correspond to data that we have
3900 in the frame_data structure and that matter on a per-packet basis.
3902 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3903 and "on the wire" lengths, or it doesn't.
3905 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3908 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3909 from the packet flags. */
3910 hdr.rec_type = phdr->rec_type;
3911 hdr.presence_flags = 0;
3912 if (fdata->flags.has_ts)
3913 hdr.presence_flags |= WTAP_HAS_TS;
3914 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3915 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3916 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
3917 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
3918 hdr.ts.secs = fdata->abs_ts.secs;
3919 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3920 hdr.caplen = phdr->caplen;
3921 hdr.len = phdr->len;
3922 hdr.pkt_encap = fdata->lnk_t;
3924 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
3926 hdr.pack_flags = phdr->pack_flags;
3927 hdr.opt_comment = g_strdup(pkt_comment);
3930 hdr.pseudo_header = phdr->pseudo_header;
3933 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3935 /* and save the packet */
3936 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
3938 /* Wiretap error. */
3941 case WTAP_ERR_UNWRITABLE_ENCAP:
3943 * This is a problem with the particular frame we're writing and
3944 * the file type and subtype we're writing; note that, and report
3945 * the frame number and file type/subtype.
3947 simple_error_message_box(
3948 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3949 fdata->num, wtap_file_type_subtype_string(args->file_type));
3952 case WTAP_ERR_PACKET_TOO_LARGE:
3954 * This is a problem with the particular frame we're writing and
3955 * the file type and subtype we're writing; note that, and report
3956 * the frame number and file type/subtype.
3958 simple_error_message_box(
3959 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
3960 fdata->num, wtap_file_type_subtype_string(args->file_type));
3963 case WTAP_ERR_UNWRITABLE_REC_TYPE:
3965 * This is a problem with the particular record we're writing and
3966 * the file type and subtype we're writing; note that, and report
3967 * the record number and file type/subtype.
3969 simple_error_message_box(
3970 "Record %u has a record type that can't be saved in a \"%s\" file.",
3971 fdata->num, wtap_file_type_subtype_string(args->file_type));
3974 case WTAP_ERR_UNWRITABLE_REC_DATA:
3976 * This is a problem with the particular frame we're writing and
3977 * the file type and subtype we're writing; note that, and report
3978 * the frame number and file type/subtype.
3980 simple_error_message_box(
3981 "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
3982 fdata->num, wtap_file_type_subtype_string(args->file_type),
3983 err_info != NULL ? err_info : "no information supplied");
3988 display_basename = g_filename_display_basename(args->fname);
3989 simple_error_message_box(
3990 "An error occurred while writing to the file \"%s\": %s.",
3991 display_basename, wtap_strerror(err));
3992 g_free(display_basename);
3997 write_failure_alert_box(args->fname, err);
4002 g_free(hdr.opt_comment);
4007 * Can this capture file be written out in any format using Wiretap
4008 * rather than by copying the raw data?
4011 cf_can_write_with_wiretap(capture_file *cf)
4013 /* We don't care whether we support the comments in this file or not;
4014 if we can't, we'll offer the user the option of discarding the
4016 return wtap_dump_can_write(cf->linktypes, 0);
4020 * Should we let the user do a save?
4024 * the file has unsaved changes, and we can save it in some
4025 * format through Wiretap
4029 * the file is a temporary file and has no unsaved changes (so
4030 * that "saving" it just means copying it).
4032 * XXX - we shouldn't allow files to be edited if they can't be saved,
4033 * so cf->unsaved_changes should be true only if the file can be saved.
4035 * We don't care whether we support the comments in this file or not;
4036 * if we can't, we'll offer the user the option of discarding the
4040 cf_can_save(capture_file *cf)
4042 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4043 /* Saved changes, and we can write it out with Wiretap. */
4047 if (cf->is_tempfile && !cf->unsaved_changes) {
4049 * Temporary file with no unsaved changes, so we can just do a
4055 /* Nothing to save. */
4060 * Should we let the user do a "save as"?
4064 * we can save it in some format through Wiretap
4068 * the file is a temporary file and has no unsaved changes (so
4069 * that "saving" it just means copying it).
4071 * XXX - we shouldn't allow files to be edited if they can't be saved,
4072 * so cf->unsaved_changes should be true only if the file can be saved.
4074 * We don't care whether we support the comments in this file or not;
4075 * if we can't, we'll offer the user the option of discarding the
4079 cf_can_save_as(capture_file *cf)
4081 if (wtap_dump_can_write(cf->linktypes, 0)) {
4082 /* We can write it out with Wiretap. */
4086 if (cf->is_tempfile && !cf->unsaved_changes) {
4088 * Temporary file with no unsaved changes, so we can just do a
4094 /* Nothing to save. */
4099 * Does this file have unsaved data?
4102 cf_has_unsaved_data(capture_file *cf)
4105 * If this is a temporary file, or a file with unsaved changes, it
4108 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4112 * Quick scan to find packet offsets.
4114 static cf_read_status_t
4115 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4117 const struct wtap_pkthdr *phdr;
4121 progdlg_t *progbar = NULL;
4124 GTimeVal start_time;
4125 gchar status_str[100];
4126 gint64 progbar_nextstep;
4127 gint64 progbar_quantum;
4132 int displayed_once = 0;
4135 /* Close the old handle. */
4136 wtap_close(cf->wth);
4138 /* Open the new file. */
4139 /* XXX: this will go through all open_routines for a matching one. But right
4140 now rescan_file() is only used when a file is being saved to a different
4141 format than the original, and the user is not given a choice of which
4142 reader to use (only which format to save it in), so doing this makes
4144 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4145 if (cf->wth == NULL) {
4146 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4147 return CF_READ_ERROR;
4150 /* We're scanning a file whose contents should be the same as what
4151 we had before, so we don't discard dissection state etc.. */
4154 /* Set the file name because we need it to set the follow stream filter.
4155 XXX - is that still true? We need it for other reasons, though,
4157 cf->filename = g_strdup(fname);
4159 /* Indicate whether it's a permanent or temporary file. */
4160 cf->is_tempfile = is_tempfile;
4162 /* No user changes yet. */
4163 cf->unsaved_changes = FALSE;
4165 cf->cd_t = wtap_file_type_subtype(cf->wth);
4166 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4168 cf->snap = wtap_snapshot_length(cf->wth);
4169 if (cf->snap == 0) {
4170 /* Snapshot length not known. */
4171 cf->has_snap = FALSE;
4172 cf->snap = WTAP_MAX_PACKET_SIZE;
4174 cf->has_snap = TRUE;
4176 name_ptr = g_filename_display_basename(cf->filename);
4178 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4180 /* Record whether the file is compressed.
4181 XXX - do we know this at open time? */
4182 cf->iscompressed = wtap_iscompressed(cf->wth);
4184 /* Find the size of the file. */
4185 size = wtap_file_size(cf->wth, NULL);
4187 /* Update the progress bar when it gets to this value. */
4188 progbar_nextstep = 0;
4189 /* When we reach the value that triggers a progress bar update,
4190 bump that value by this amount. */
4192 progbar_quantum = size/N_PROGBAR_UPDATES;
4193 if (progbar_quantum < MIN_QUANTUM)
4194 progbar_quantum = MIN_QUANTUM;
4196 progbar_quantum = 0;
4198 cf->stop_flag = FALSE;
4199 g_get_current_time(&start_time);
4202 phdr = wtap_phdr(cf->wth);
4203 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4205 fdata = frame_data_sequence_find(cf->frames, framenum);
4206 fdata->file_off = data_offset;
4209 cf->f_datalen = wtap_read_so_far(cf->wth);
4211 /* Create the progress bar if necessary.
4212 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4214 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4215 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4216 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4217 TRUE, &cf->stop_flag, &start_time, progbar_val);
4220 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4221 when we update it, we have to run the GTK+ main loop to get it
4222 to repaint what's pending, and doing so may involve an "ioctl()"
4223 to see if there's any pending input from an X server, and doing
4224 that for every packet can be costly, especially on a big file. */
4225 if (cf->f_datalen >= progbar_nextstep) {
4226 if (progbar != NULL) {
4227 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4228 /* update the packet bar content on the first run or frequently on very large files */
4230 if (progbar_quantum > 500000 || displayed_once == 0) {
4231 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4233 packets_bar_update();
4236 #endif /* HAVE_LIBPCAP */
4237 update_progress_dlg(progbar, progbar_val, status_str);
4239 progbar_nextstep += progbar_quantum;
4243 if (cf->stop_flag) {
4244 /* Well, the user decided to abort the rescan. Sadly, as this
4245 isn't a reread, recovering is difficult, so we'll just
4246 close the current capture. */
4250 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4251 it's not already there.
4252 XXX - yes, this is O(N), so if every packet had a different
4253 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4254 there are probably going to be a small number of encapsulation types
4256 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4259 /* Free the display name */
4262 /* We're done reading the file; destroy the progress bar if it was created. */
4263 if (progbar != NULL)
4264 destroy_progress_dlg(progbar);
4266 /* We're done reading sequentially through the file. */
4267 cf->state = FILE_READ_DONE;
4269 /* Close the sequential I/O side, to free up memory it requires. */
4270 wtap_sequential_close(cf->wth);
4272 /* compute the time it took to load the file */
4273 compute_elapsed(cf, &start_time);
4275 /* Set the file encapsulation type now; we don't know what it is until
4276 we've looked at all the packets, as we don't know until then whether
4277 there's more than one type (and thus whether it's
4278 WTAP_ENCAP_PER_PACKET). */
4279 cf->lnk_t = wtap_file_encap(cf->wth);
4281 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4283 if (cf->stop_flag) {
4284 /* Our caller will give up at this point. */
4285 return CF_READ_ABORTED;
4289 /* Put up a message box noting that the read failed somewhere along
4290 the line. Don't throw out the stuff we managed to read, though,
4294 case WTAP_ERR_UNSUPPORTED:
4295 simple_error_message_box(
4296 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4297 err_info != NULL ? err_info : "no information supplied");
4301 case WTAP_ERR_SHORT_READ:
4302 simple_error_message_box(
4303 "The capture file appears to have been cut short"
4304 " in the middle of a packet.");
4307 case WTAP_ERR_BAD_FILE:
4308 simple_error_message_box(
4309 "The capture file appears to be damaged or corrupt.\n(%s)",
4310 err_info != NULL ? err_info : "no information supplied");
4314 case WTAP_ERR_DECOMPRESS:
4315 simple_error_message_box(
4316 "The compressed capture file appears to be damaged or corrupt.\n"
4318 err_info != NULL ? err_info : "no information supplied");
4323 simple_error_message_box(
4324 "An error occurred while reading the"
4325 " capture file: %s.", wtap_strerror(*err));
4328 return CF_READ_ERROR;
4334 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4335 gboolean compressed, gboolean discard_comments,
4336 gboolean dont_reopen)
4339 gchar *fname_new = NULL;
4342 addrinfo_lists_t *addr_lists;
4346 gchar *display_basename;
4353 save_callback_args_t callback_args;
4355 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4357 addr_lists = get_addrinfo_list();
4359 if (save_format == cf->cd_t && compressed == cf->iscompressed
4360 && !discard_comments && !cf->unsaved_changes
4361 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4362 /* We're saving in the format it's already in, and we're
4363 not discarding comments, and there are no changes we have
4364 in memory that aren't saved to the file, and we have no name
4365 resolution blocks to write, so we can just move or copy the raw data. */
4367 if (cf->is_tempfile) {
4368 /* The file being saved is a temporary file from a live
4369 capture, so it doesn't need to stay around under that name;
4370 first, try renaming the capture buffer file to the new name.
4371 This acts as a "safe save", in that, if the file already
4372 exists, the existing file will be removed only if the rename
4375 Sadly, on Windows, as we have the current capture file
4376 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4377 (to cause the rename to remove an existing target), as
4378 done by ws_stdio_rename() (ws_rename() is #defined to
4379 be ws_stdio_rename() on Windows) will fail.
4381 According to the MSDN documentation for CreateFile(), if,
4382 when we open a capture file, we were to directly do a CreateFile(),
4383 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4384 convert it to a file descriptor with _open_osfhandle(),
4385 that would allow the file to be renamed out from under us.
4387 However, that doesn't work in practice. Perhaps the problem
4388 is that the process doing the rename is the process that
4389 has the file open. */
4391 if (ws_rename(cf->filename, fname) == 0) {
4392 /* That succeeded - there's no need to copy the source file. */
4393 how_to_save = SAVE_WITH_MOVE;
4395 if (errno == EXDEV) {
4396 /* They're on different file systems, so we have to copy the
4398 how_to_save = SAVE_WITH_COPY;
4400 /* The rename failed, but not because they're on different
4401 file systems - put up an error message. (Or should we
4402 just punt and try to copy? The only reason why I'd
4403 expect the rename to fail and the copy to succeed would
4404 be if we didn't have permission to remove the file from
4405 the temporary directory, and that might be fixable - but
4406 is it worth requiring the user to go off and fix it?) */
4407 cf_rename_failure_alert_box(fname, errno);
4412 how_to_save = SAVE_WITH_COPY;
4415 /* It's a permanent file, so we should copy it, and not remove the
4417 how_to_save = SAVE_WITH_COPY;
4420 if (how_to_save == SAVE_WITH_COPY) {
4421 /* Copy the file, if we haven't moved it. If we're overwriting
4422 an existing file, we do it with a "safe save", by writing
4423 to a new file and, if the write succeeds, renaming the
4424 new file on top of the old file. */
4425 if (file_exists(fname)) {
4426 fname_new = g_strdup_printf("%s~", fname);
4427 if (!copy_file_binary_mode(cf->filename, fname_new))
4430 if (!copy_file_binary_mode(cf->filename, fname))
4435 /* Either we're saving in a different format or we're saving changes,
4436 such as added, modified, or removed comments, that haven't yet
4437 been written to the underlying file; we can't do that by copying
4438 or moving the capture file, we have to do it by writing the packets
4441 wtapng_section_t *shb_hdr = NULL;
4442 wtapng_iface_descriptions_t *idb_inf = NULL;
4443 wtapng_name_res_t *nrb_hdr = NULL;
4446 /* XXX: what free's this shb_hdr? */
4447 shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
4448 idb_inf = wtap_file_get_idb_info(cf->wth);
4449 nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
4451 /* Determine what file encapsulation type we should use. */
4452 encap = wtap_dump_file_encap_type(cf->linktypes);
4454 if (file_exists(fname)) {
4455 /* We're overwriting an existing file; write out to a new file,
4456 and, if that succeeds, rename the new file on top of the
4457 old file. That makes this a "safe save", so that we don't
4458 lose the old file if we have a problem writing out the new
4459 file. (If the existing file is the current capture file,
4460 we *HAVE* to do that, otherwise we're overwriting the file
4461 from which we're reading the packets that we're writing!) */
4462 fname_new = g_strdup_printf("%s~", fname);
4463 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4464 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4466 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4467 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4473 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4477 /* Add address resolution */
4478 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4480 /* Iterate through the list of packets, processing all the packets. */
4481 callback_args.pdh = pdh;
4482 callback_args.fname = fname;
4483 callback_args.file_type = save_format;
4484 switch (process_specified_records(cf, NULL, "Saving", "packets",
4485 TRUE, save_record, &callback_args)) {
4488 /* Completed successfully. */
4492 /* The user decided to abort the saving.
4493 If we're writing to a temporary file, remove it.
4494 XXX - should we do so even if we're not writing to a
4496 wtap_dump_close(pdh, &err);
4497 if (fname_new != NULL)
4498 ws_unlink(fname_new);
4499 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4500 return CF_WRITE_ABORTED;
4503 /* Error while saving.
4504 If we're writing to a temporary file, remove it. */
4505 if (fname_new != NULL)
4506 ws_unlink(fname_new);
4507 wtap_dump_close(pdh, &err);
4511 if (!wtap_dump_close(pdh, &err)) {
4512 cf_close_failure_alert_box(fname, err);
4516 how_to_save = SAVE_WITH_WTAP;
4519 if (fname_new != NULL) {
4520 /* We wrote out to fname_new, and should rename it on top of
4521 fname. fname_new is now closed, so that should be possible even
4522 on Windows. However, on Windows, we first need to close whatever
4523 file descriptors we have open for fname. */
4525 wtap_fdclose(cf->wth);
4527 /* Now do the rename. */
4528 if (ws_rename(fname_new, fname) == -1) {
4529 /* Well, the rename failed. */
4530 cf_rename_failure_alert_box(fname, errno);
4532 /* Attempt to reopen the random file descriptor using the
4533 current file's filename. (At this point, the sequential
4534 file descriptor is closed.) */
4535 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4536 /* Oh, well, we're screwed. */
4537 display_basename = g_filename_display_basename(cf->filename);
4538 simple_error_message_box(
4539 file_open_error_message(err, FALSE), display_basename);
4540 g_free(display_basename);
4547 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4548 cf->unsaved_changes = FALSE;
4551 switch (how_to_save) {
4553 case SAVE_WITH_MOVE:
4554 /* We just moved the file, so the wtap structure refers to the
4555 new file, and all the information other than the filename
4556 and the "is temporary" status applies to the new file; just
4558 g_free(cf->filename);
4559 cf->filename = g_strdup(fname);
4560 cf->is_tempfile = FALSE;
4561 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4564 case SAVE_WITH_COPY:
4565 /* We just copied the file, s all the information other than
4566 the wtap structure, the filename, and the "is temporary"
4567 status applies to the new file; just update that. */
4568 wtap_close(cf->wth);
4569 /* Although we're just "copying" and then opening the copy, it will
4570 try all open_routine readers to open the copy, so we need to
4571 reset the cfile's open_type. */
4572 cf->open_type = WTAP_TYPE_AUTO;
4573 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4574 if (cf->wth == NULL) {
4575 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4578 g_free(cf->filename);
4579 cf->filename = g_strdup(fname);
4580 cf->is_tempfile = FALSE;
4582 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4585 case SAVE_WITH_WTAP:
4586 /* Open and read the file we saved to.
4588 XXX - this is somewhat of a waste; we already have the
4589 packets, all this gets us is updated file type information
4590 (which we could just stuff into "cf"), and having the new
4591 file be the one we have opened and from which we're reading
4592 the data, and it means we have to spend time opening and
4593 reading the file, which could be a significant amount of
4594 time if the file is large.
4596 If the capture-file-writing code were to return the
4597 seek offset of each packet it writes, we could save that
4598 in the frame_data structure for the frame, and just open
4599 the file without reading it again...
4601 ...as long as, for gzipped files, the process of writing
4602 out the file *also* generates the information needed to
4603 support fast random access to the compressed file. */
4604 /* rescan_file will cause us to try all open_routines, so
4605 reset cfile's open_type */
4606 cf->open_type = WTAP_TYPE_AUTO;
4607 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4608 /* The rescan failed; just close the file. Either
4609 a dialog was popped up for the failure, so the
4610 user knows what happened, or they stopped the
4611 rescan, in which case they know what happened. */
4617 /* If we were told to discard the comments, do so. */
4618 if (discard_comments) {
4619 /* Remove SHB comment, if any. */
4620 wtap_write_shb_comment(cf->wth, NULL);
4622 /* remove all user comments */
4623 for (framenum = 1; framenum <= cf->count; framenum++) {
4624 fdata = frame_data_sequence_find(cf->frames, framenum);
4626 fdata->flags.has_phdr_comment = FALSE;
4627 fdata->flags.has_user_comment = FALSE;
4630 if (cf->frames_user_comments) {
4631 g_tree_destroy(cf->frames_user_comments);
4632 cf->frames_user_comments = NULL;
4635 cf->packet_comment_count = 0;
4641 if (fname_new != NULL) {
4642 /* We were trying to write to a temporary file; get rid of it if it
4643 exists. (We don't care whether this fails, as, if it fails,
4644 there's not much we can do about it. I guess if it failed for
4645 a reason other than "it doesn't exist", we could report an
4646 error, so the user knows there's a junk file that they might
4647 want to clean up.) */
4648 ws_unlink(fname_new);
4651 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4652 return CF_WRITE_ERROR;
4656 cf_export_specified_packets(capture_file *cf, const char *fname,
4657 packet_range_t *range, guint save_format,
4658 gboolean compressed)
4660 gchar *fname_new = NULL;
4663 save_callback_args_t callback_args;
4664 wtapng_section_t *shb_hdr = NULL;
4665 wtapng_iface_descriptions_t *idb_inf = NULL;
4666 wtapng_name_res_t *nrb_hdr = NULL;
4669 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4671 packet_range_process_init(range);
4673 /* We're writing out specified packets from the specified capture
4674 file to another file. Even if all captured packets are to be
4675 written, don't special-case the operation - read each packet
4676 and then write it out if it's one of the specified ones. */
4678 /* XXX: what free's this shb_hdr? */
4679 shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
4680 idb_inf = wtap_file_get_idb_info(cf->wth);
4681 nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
4683 /* Determine what file encapsulation type we should use. */
4684 encap = wtap_dump_file_encap_type(cf->linktypes);
4686 if (file_exists(fname)) {
4687 /* We're overwriting an existing file; write out to a new file,
4688 and, if that succeeds, rename the new file on top of the
4689 old file. That makes this a "safe save", so that we don't
4690 lose the old file if we have a problem writing out the new
4691 file. (If the existing file is the current capture file,
4692 we *HAVE* to do that, otherwise we're overwriting the file
4693 from which we're reading the packets that we're writing!) */
4694 fname_new = g_strdup_printf("%s~", fname);
4695 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4696 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4698 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4699 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4705 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4709 /* Add address resolution */
4710 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4712 /* Iterate through the list of packets, processing the packets we were
4715 XXX - we've already called "packet_range_process_init(range)", but
4716 "process_specified_records()" will do it again. Fortunately,
4717 that's harmless in this case, as we haven't done anything to
4718 "range" since we initialized it. */
4719 callback_args.pdh = pdh;
4720 callback_args.fname = fname;
4721 callback_args.file_type = save_format;
4722 switch (process_specified_records(cf, range, "Writing", "specified records",
4723 TRUE, save_record, &callback_args)) {
4726 /* Completed successfully. */
4730 /* The user decided to abort the saving.
4731 If we're writing to a temporary file, remove it.
4732 XXX - should we do so even if we're not writing to a
4734 wtap_dump_close(pdh, &err);
4735 if (fname_new != NULL)
4736 ws_unlink(fname_new);
4737 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4738 return CF_WRITE_ABORTED;
4742 /* Error while saving.
4743 If we're writing to a temporary file, remove it. */
4744 if (fname_new != NULL)
4745 ws_unlink(fname_new);
4746 wtap_dump_close(pdh, &err);
4750 if (!wtap_dump_close(pdh, &err)) {
4751 cf_close_failure_alert_box(fname, err);
4755 if (fname_new != NULL) {
4756 /* We wrote out to fname_new, and should rename it on top of
4757 fname; fname is now closed, so that should be possible even
4758 on Windows. Do the rename. */
4759 if (ws_rename(fname_new, fname) == -1) {
4760 /* Well, the rename failed. */
4761 cf_rename_failure_alert_box(fname, errno);
4766 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4770 if (fname_new != NULL) {
4771 /* We were trying to write to a temporary file; get rid of it if it
4772 exists. (We don't care whether this fails, as, if it fails,
4773 there's not much we can do about it. I guess if it failed for
4774 a reason other than "it doesn't exist", we could report an
4775 error, so the user knows there's a junk file that they might
4776 want to clean up.) */
4777 ws_unlink(fname_new);
4780 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4781 return CF_WRITE_ERROR;
4785 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4786 gboolean for_writing, int file_type)
4788 gchar *display_basename;
4791 /* Wiretap error. */
4792 display_basename = g_filename_display_basename(filename);
4795 case WTAP_ERR_NOT_REGULAR_FILE:
4796 simple_error_message_box(
4797 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4801 case WTAP_ERR_RANDOM_OPEN_PIPE:
4802 /* Seen only when opening a capture file for reading. */
4803 simple_error_message_box(
4804 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4805 "To capture from a pipe or FIFO use wireshark -i -",
4809 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4810 /* Seen only when opening a capture file for reading. */
4811 simple_error_message_box(
4812 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4816 case WTAP_ERR_UNSUPPORTED:
4817 /* Seen only when opening a capture file for reading. */
4818 simple_error_message_box(
4819 "The file \"%s\" contains record data that Wireshark doesn't support.\n"
4822 err_info != NULL ? err_info : "no information supplied");
4826 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4827 /* Seen only when opening a capture file for writing. */
4828 simple_error_message_box(
4829 "The file \"%s\" is a pipe, and %s capture files can't be "
4830 "written to a pipe.",
4831 display_basename, wtap_file_type_subtype_string(file_type));
4834 case WTAP_ERR_UNWRITABLE_FILE_TYPE:
4835 /* Seen only when opening a capture file for writing. */
4836 simple_error_message_box(
4837 "Wireshark doesn't support writing capture files in that format.");
4840 case WTAP_ERR_UNWRITABLE_ENCAP:
4841 /* Seen only when opening a capture file for writing. */
4842 simple_error_message_box("Wireshark can't save this capture in that format.");
4845 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4847 simple_error_message_box(
4848 "Wireshark can't save this capture in that format.");
4850 simple_error_message_box(
4851 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4856 case WTAP_ERR_BAD_FILE:
4857 /* Seen only when opening a capture file for reading. */
4858 simple_error_message_box(
4859 "The file \"%s\" appears to be damaged or corrupt.\n"
4862 err_info != NULL ? err_info : "no information supplied");
4866 case WTAP_ERR_CANT_OPEN:
4868 simple_error_message_box(
4869 "The file \"%s\" could not be created for some unknown reason.",
4872 simple_error_message_box(
4873 "The file \"%s\" could not be opened for some unknown reason.",
4878 case WTAP_ERR_SHORT_READ:
4879 simple_error_message_box(
4880 "The file \"%s\" appears to have been cut short"
4881 " in the middle of a packet or other data.",
4885 case WTAP_ERR_SHORT_WRITE:
4886 simple_error_message_box(
4887 "A full header couldn't be written to the file \"%s\".",
4891 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4892 simple_error_message_box(
4893 "This file type cannot be written as a compressed file.");
4896 case WTAP_ERR_DECOMPRESS:
4897 simple_error_message_box(
4898 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4899 "(%s)", display_basename,
4900 err_info != NULL ? err_info : "no information supplied");
4905 simple_error_message_box(
4906 "The file \"%s\" could not be %s: %s.",
4908 for_writing ? "created" : "opened",
4909 wtap_strerror(err));
4912 g_free(display_basename);
4915 open_failure_alert_box(filename, err, for_writing);
4920 * XXX - whether we mention the source pathname, the target pathname,
4921 * or both depends on the error and on what we find if we look for
4922 * one or both of them.
4925 cf_rename_failure_alert_box(const char *filename, int err)
4927 gchar *display_basename;
4929 display_basename = g_filename_display_basename(filename);
4933 /* XXX - should check whether the source exists and, if not,
4934 report it as the problem and, if so, report the destination
4936 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4941 /* XXX - if we're doing a rename after a safe save, we should
4942 probably say something else. */
4943 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4948 /* XXX - this should probably mention both the source and destination
4950 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4951 display_basename, wtap_strerror(err));
4954 g_free(display_basename);
4957 /* Check for write errors - if the file is being written to an NFS server,
4958 a write error may not show up until the file is closed, as NFS clients
4959 might not send writes to the server until the "write()" call finishes,
4960 so that the write may fail on the server but the "write()" may succeed. */
4962 cf_close_failure_alert_box(const char *filename, int err)
4964 gchar *display_basename;
4967 /* Wiretap error. */
4968 display_basename = g_filename_display_basename(filename);
4971 case WTAP_ERR_CANT_CLOSE:
4972 simple_error_message_box(
4973 "The file \"%s\" couldn't be closed for some unknown reason.",
4977 case WTAP_ERR_SHORT_WRITE:
4978 simple_error_message_box(
4979 "Not all the packets could be written to the file \"%s\".",
4984 simple_error_message_box(
4985 "An error occurred while closing the file \"%s\": %s.",
4986 display_basename, wtap_strerror(err));
4989 g_free(display_basename);
4992 We assume that a close error from the OS is really a write error. */
4993 write_failure_alert_box(filename, err);
4997 /* Reload the current capture file. */
4999 cf_reload(capture_file *cf) {
5001 gboolean is_tempfile;
5004 /* If the file could be opened, "cf_open()" calls "cf_close()"
5005 to get rid of state for the old capture file before filling in state
5006 for the new capture file. "cf_close()" will remove the file if
5007 it's a temporary file; we don't want that to happen (for one thing,
5008 it'd prevent subsequent reopens from working). Remember whether it's
5009 a temporary file, mark it as not being a temporary file, and then
5010 reopen it as the type of file it was.
5012 Also, "cf_close()" will free "cf->filename", so we must make
5013 a copy of it first. */
5014 filename = g_strdup(cf->filename);
5015 is_tempfile = cf->is_tempfile;
5016 cf->is_tempfile = FALSE;
5017 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5018 switch (cf_read(cf, TRUE)) {
5022 /* Just because we got an error, that doesn't mean we were unable
5023 to read any of the file; we handle what we could get from the
5027 case CF_READ_ABORTED:
5028 /* The user bailed out of re-reading the capture file; the
5029 capture file has been closed - just free the capture file name
5030 string and return (without changing the last containing
5036 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5037 Instead, the file was left open, so we should restore "cf->is_tempfile"
5040 XXX - change the menu? Presumably "cf_open()" will do that;
5041 make sure it does! */
5042 cf->is_tempfile = is_tempfile;
5044 /* "cf_open()" made a copy of the file name we handed it, so
5045 we should free up our copy. */
5055 * indent-tabs-mode: nil
5058 * ex: set shiftwidth=2 tabstop=8 expandtab:
5059 * :indentSize=2:tabSize=8:noTabs=true: