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.
42 #include <wsutil/tempfile.h>
43 #include <wsutil/file_util.h>
44 #include <wsutil/filesystem.h>
45 #include <wsutil/ws_version_info.h>
47 #include <wiretap/merge.h>
49 #include <epan/exceptions.h>
50 #include <epan/epan-int.h>
51 #include <epan/epan.h>
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include <epan/expert.h>
56 #include <epan/prefs.h>
57 #include <epan/dfilter/dfilter.h>
58 #include <epan/epan_dissect.h>
60 #include <epan/dissectors/packet-data.h>
61 #include <epan/dissectors/packet-ber.h>
62 #include <epan/timestamp.h>
63 #include <epan/dfilter/dfilter-macro.h>
64 #include <epan/strutil.h>
65 #include <epan/addr_resolv.h>
68 #include "color_filters.h"
72 #include "frame_tvbuff.h"
74 #include "ui/alert_box.h"
75 #include "ui/simple_dialog.h"
76 #include "ui/main_statusbar.h"
77 #include "ui/progress_dlg.h"
78 #include "ui/ui_util.h"
80 /* Needed for addrinfo */
81 #ifdef HAVE_SYS_TYPES_H
82 # include <sys/types.h>
85 #ifdef HAVE_SYS_SOCKET_H
86 #include <sys/socket.h>
89 #ifdef HAVE_NETINET_IN_H
90 # include <netinet/in.h>
97 #ifdef HAVE_WINSOCK2_H
98 # include <winsock2.h>
101 #if defined(_WIN32) && defined(INET6)
102 # include <ws2tcpip.h>
106 gboolean auto_scroll_live;
109 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
110 column_info *cinfo, gint64 offset);
112 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
119 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
121 static void match_subtree_text(proto_node *node, gpointer data);
122 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
124 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
126 static match_result match_narrow(capture_file *cf, frame_data *fdata,
128 static match_result match_wide(capture_file *cf, frame_data *fdata,
130 static match_result match_binary(capture_file *cf, frame_data *fdata,
132 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
134 static match_result match_marked(capture_file *cf, frame_data *fdata,
136 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
138 static gboolean find_packet(capture_file *cf,
139 match_result (*match_function)(capture_file *, frame_data *, void *),
140 void *criterion, search_direction dir);
142 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
144 static void cf_open_failure_alert_box(const char *filename, int err,
145 gchar *err_info, gboolean for_writing,
147 static void cf_rename_failure_alert_box(const char *filename, int err);
148 static void cf_close_failure_alert_box(const char *filename, int err);
149 static void ref_time_packets(capture_file *cf);
150 /* Update the progress bar this many times when reading a file. */
151 #define N_PROGBAR_UPDATES 100
152 /* We read around 200k/100ms don't update the progress bar more often than that */
153 #define MIN_QUANTUM 200000
154 #define MIN_NUMBER_OF_PACKET 1500
157 * We could probably use g_signal_...() instead of the callbacks below but that
158 * would require linking our CLI programs to libgobject and creating an object
159 * instance for the signals.
162 cf_callback_t cb_fct;
164 } cf_callback_data_t;
166 static GList *cf_callbacks = NULL;
169 cf_callback_invoke(int event, gpointer data)
171 cf_callback_data_t *cb;
172 GList *cb_item = cf_callbacks;
174 /* there should be at least one interested */
175 g_assert(cb_item != NULL);
177 while (cb_item != NULL) {
178 cb = (cf_callback_data_t *)cb_item->data;
179 cb->cb_fct(event, data, cb->user_data);
180 cb_item = g_list_next(cb_item);
186 cf_callback_add(cf_callback_t func, gpointer user_data)
188 cf_callback_data_t *cb;
190 cb = g_new(cf_callback_data_t,1);
192 cb->user_data = user_data;
194 cf_callbacks = g_list_prepend(cf_callbacks, cb);
198 cf_callback_remove(cf_callback_t func)
200 cf_callback_data_t *cb;
201 GList *cb_item = cf_callbacks;
203 while (cb_item != NULL) {
204 cb = (cf_callback_data_t *)cb_item->data;
205 if (cb->cb_fct == func) {
206 cf_callbacks = g_list_remove(cf_callbacks, cb);
210 cb_item = g_list_next(cb_item);
213 g_assert_not_reached();
217 cf_timestamp_auto_precision(capture_file *cf)
221 /* don't try to get the file's precision if none is opened */
222 if (cf->state == FILE_CLOSED) {
226 /* Set the column widths of those columns that show the time in
227 "command-line-specified" format. */
228 for (i = 0; i < cf->cinfo.num_cols; i++) {
229 if (col_has_time_fmt(&cf->cinfo, i)) {
230 packet_list_resize_column(i);
236 cf_get_computed_elapsed(capture_file *cf)
238 return cf->computed_elapsed;
242 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
245 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
250 g_get_current_time(&time_now);
252 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
253 time_now.tv_usec - start_time->tv_usec;
255 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
258 static const nstime_t *
259 ws_get_frame_ts(void *data, guint32 frame_num)
261 capture_file *cf = (capture_file *) data;
263 if (cf->prev_dis && cf->prev_dis->num == frame_num)
264 return &cf->prev_dis->abs_ts;
266 if (cf->prev_cap && cf->prev_cap->num == frame_num)
267 return &cf->prev_cap->abs_ts;
270 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
272 return (fd) ? &fd->abs_ts : NULL;
279 ws_get_user_comment(void *data, const frame_data *fd)
281 capture_file *cf = (capture_file *) data;
283 return cf_get_user_packet_comment(cf, fd);
287 ws_epan_new(capture_file *cf)
289 epan_t *epan = epan_new();
292 epan->get_frame_ts = ws_get_frame_ts;
293 epan->get_interface_name = cap_file_get_interface_name;
294 epan->get_user_comment = ws_get_user_comment;
300 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
305 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
309 /* The open succeeded. Close whatever capture file we had open,
310 and fill in the information for this file. */
313 /* Initialize the packet header. */
314 wtap_phdr_init(&cf->phdr);
316 /* XXX - we really want to initialize this after we've read all
317 the packets, so we know how much we'll ultimately need. */
318 ws_buffer_init(&cf->buf, 1500);
320 /* Create new epan session for dissection.
321 * (The old one was freed in cf_close().)
323 cf->epan = ws_epan_new(cf);
325 /* We're about to start reading the file. */
326 cf->state = FILE_READ_IN_PROGRESS;
331 /* Set the file name because we need it to set the follow stream filter.
332 XXX - is that still true? We need it for other reasons, though,
334 cf->filename = g_strdup(fname);
336 /* Indicate whether it's a permanent or temporary file. */
337 cf->is_tempfile = is_tempfile;
339 /* No user changes yet. */
340 cf->unsaved_changes = FALSE;
342 cf->computed_elapsed = 0;
344 cf->cd_t = wtap_file_type_subtype(cf->wth);
345 cf->open_type = type;
346 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
348 cf->packet_comment_count = 0;
349 cf->displayed_count = 0;
350 cf->marked_count = 0;
351 cf->ignored_count = 0;
352 cf->ref_time_count = 0;
353 cf->drops_known = FALSE;
355 cf->snap = wtap_snapshot_length(cf->wth);
357 /* Snapshot length not known. */
358 cf->has_snap = FALSE;
359 cf->snap = WTAP_MAX_PACKET_SIZE;
363 /* Allocate a frame_data_sequence for the frames in this file */
364 cf->frames = new_frame_data_sequence();
366 nstime_set_zero(&cf->elapsed_time);
372 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
373 cf_timestamp_auto_precision(cf);
375 packet_list_queue_draw();
376 cf_callback_invoke(cf_cb_file_opened, cf);
378 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
379 /* tell the BER dissector the file name */
380 ber_set_filename(cf->filename);
383 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
384 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
389 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
394 * Add an encapsulation type to cf->linktypes.
397 cf_add_encapsulation_type(capture_file *cf, int encap)
401 for (i = 0; i < cf->linktypes->len; i++) {
402 if (g_array_index(cf->linktypes, gint, i) == encap)
403 return; /* it's already there */
405 /* It's not already there - add it. */
406 g_array_append_val(cf->linktypes, encap);
409 /* Reset everything to a pristine state */
411 cf_close(capture_file *cf)
413 if (cf->state == FILE_CLOSED)
414 return; /* Nothing to do */
416 /* Die if we're in the middle of reading a file. */
417 g_assert(cf->state != FILE_READ_IN_PROGRESS);
419 cf_callback_invoke(cf_cb_file_closing, cf);
421 /* close things, if not already closed before */
422 color_filters_cleanup();
428 /* We have no file open... */
429 if (cf->filename != NULL) {
430 /* If it's a temporary file, remove it. */
432 ws_unlink(cf->filename);
433 g_free(cf->filename);
436 /* ...which means we have no changes to that file to save. */
437 cf->unsaved_changes = FALSE;
439 /* no open_routine type */
440 cf->open_type = WTAP_TYPE_AUTO;
442 /* Clean up the packet header. */
443 wtap_phdr_cleanup(&cf->phdr);
445 /* Free up the packet buffer. */
446 ws_buffer_free(&cf->buf);
448 dfilter_free(cf->rfcode);
450 if (cf->frames != NULL) {
451 free_frame_data_sequence(cf->frames);
454 #ifdef WANT_PACKET_EDITOR
455 if (cf->edited_frames) {
456 g_tree_destroy(cf->edited_frames);
457 cf->edited_frames = NULL;
460 if (cf->frames_user_comments) {
461 g_tree_destroy(cf->frames_user_comments);
462 cf->frames_user_comments = NULL;
464 cf_unselect_packet(cf); /* nothing to select */
465 cf->first_displayed = 0;
466 cf->last_displayed = 0;
468 /* No frames, no frame selected, no field in that frame selected. */
470 cf->current_frame = 0;
472 cf->finfo_selected = NULL;
474 /* No frame link-layer types, either. */
475 if (cf->linktypes != NULL) {
476 g_array_free(cf->linktypes, TRUE);
477 cf->linktypes = NULL;
480 /* Clear the packet list. */
481 packet_list_freeze();
486 nstime_set_zero(&cf->elapsed_time);
488 reset_tap_listeners();
493 /* We have no file open. */
494 cf->state = FILE_CLOSED;
496 cf_callback_invoke(cf_cb_file_closed, cf);
500 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
504 progbar_val = (gfloat) file_pos / (gfloat) size;
505 if (progbar_val > 1.0) {
507 /* The file probably grew while we were reading it.
508 * Update file size, and try again.
510 size = wtap_file_size(cf->wth, NULL);
513 progbar_val = (gfloat) file_pos / (gfloat) size;
515 /* If it's still > 1, either "wtap_file_size()" failed (in which
516 * case there's not much we can do about it), or the file
517 * *shrank* (in which case there's not much we can do about
518 * it); just clip the progress value at 1.0.
520 if (progbar_val > 1.0f)
524 g_snprintf(status_str, status_size,
525 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
526 file_pos / 1024, size / 1024);
532 cf_read(capture_file *cf, gboolean reloading)
537 progdlg_t *progbar = NULL;
542 volatile gboolean create_proto_tree;
546 /* Compile the current display filter.
547 * We assume this will not fail since cf->dfilter is only set in
548 * cf_filter IFF the filter was valid.
550 compiled = dfilter_compile(cf->dfilter, &dfcode);
551 g_assert(!cf->dfilter || (compiled && dfcode));
553 /* Get the union of the flags for all tap listeners. */
554 tap_flags = union_of_tap_listener_flags();
556 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
558 reset_tap_listeners();
560 name_ptr = g_filename_display_basename(cf->filename);
563 cf_callback_invoke(cf_cb_file_reload_started, cf);
565 cf_callback_invoke(cf_cb_file_read_started, cf);
567 /* Record whether the file is compressed.
568 XXX - do we know this at open time? */
569 cf->iscompressed = wtap_iscompressed(cf->wth);
571 /* The packet list window will be empty until the file is completly loaded */
572 packet_list_freeze();
575 g_get_current_time(&start_time);
577 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
581 int displayed_once = 0;
589 gint64 progbar_quantum;
590 gint64 progbar_nextstep;
592 gchar status_str[100];
596 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
598 /* Find the size of the file. */
599 size = wtap_file_size(cf->wth, NULL);
601 /* Update the progress bar when it gets to this value. */
602 progbar_nextstep = 0;
603 /* When we reach the value that triggers a progress bar update,
604 bump that value by this amount. */
606 progbar_quantum = size/N_PROGBAR_UPDATES;
607 if (progbar_quantum < MIN_QUANTUM)
608 progbar_quantum = MIN_QUANTUM;
612 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
615 file_pos = wtap_read_so_far(cf->wth);
617 /* Create the progress bar if necessary.
618 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
620 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
621 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
623 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
624 TRUE, &stop_flag, &start_time, progbar_val);
626 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
627 TRUE, &stop_flag, &start_time, progbar_val);
630 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
631 when we update it, we have to run the GTK+ main loop to get it
632 to repaint what's pending, and doing so may involve an "ioctl()"
633 to see if there's any pending input from an X server, and doing
634 that for every packet can be costly, especially on a big file. */
635 if (file_pos >= progbar_nextstep) {
636 if (progbar != NULL) {
637 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
638 /* update the packet bar content on the first run or frequently on very large files */
640 if (progbar_quantum > 500000 || displayed_once == 0) {
641 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
643 packets_bar_update();
646 #endif /* HAVE_LIBPCAP */
647 update_progress_dlg(progbar, progbar_val, status_str);
649 progbar_nextstep += progbar_quantum;
654 /* Well, the user decided to abort the read. He/She will be warned and
655 it might be enough for him/her to work with the already loaded
657 This is especially true for very large capture files, where you don't
658 want to wait loading the whole file (which may last minutes or even
659 hours even on fast machines) just to see that it was the wrong file. */
662 read_packet(cf, dfcode, &edt, cinfo, data_offset);
665 CATCH(OutOfMemoryError) {
666 simple_message_box(ESD_TYPE_ERROR, NULL,
667 "More information and workarounds can be found at\n"
668 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
669 "Sorry, but Wireshark has run out of memory and has to terminate now.");
671 /* Could we close the current capture and free up memory from that? */
673 /* we have to terminate, as we cannot recover from the memory error */
679 /* Free the display name */
682 /* Cleanup and release all dfilter resources */
683 if (dfcode != NULL) {
684 dfilter_free(dfcode);
687 epan_dissect_cleanup(&edt);
689 /* We're done reading the file; destroy the progress bar if it was created. */
691 destroy_progress_dlg(progbar);
693 /* We're done reading sequentially through the file. */
694 cf->state = FILE_READ_DONE;
696 /* Close the sequential I/O side, to free up memory it requires. */
697 wtap_sequential_close(cf->wth);
699 /* Allow the protocol dissectors to free up memory that they
700 * don't need after the sequential run-through of the packets. */
701 postseq_cleanup_all_protocols();
703 /* compute the time it took to load the file */
704 compute_elapsed(cf, &start_time);
706 /* Set the file encapsulation type now; we don't know what it is until
707 we've looked at all the packets, as we don't know until then whether
708 there's more than one type (and thus whether it's
709 WTAP_ENCAP_PER_PACKET). */
710 cf->lnk_t = wtap_file_encap(cf->wth);
712 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
717 cf_callback_invoke(cf_cb_file_reload_finished, cf);
719 cf_callback_invoke(cf_cb_file_read_finished, cf);
721 /* If we have any displayed packets to select, select the first of those
722 packets by making the first row the selected row. */
723 if (cf->first_displayed != 0) {
724 packet_list_select_first_row();
728 simple_message_box(ESD_TYPE_WARN, NULL,
729 "The remaining packets in the file were discarded.\n"
731 "As a lot of packets from the original file will be missing,\n"
732 "remember to be careful when saving the current content to a file.\n",
733 "File loading was cancelled.");
734 return CF_READ_ERROR;
738 /* Put up a message box noting that the read failed somewhere along
739 the line. Don't throw out the stuff we managed to read, though,
743 case WTAP_ERR_UNSUPPORTED:
744 simple_error_message_box(
745 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
750 case WTAP_ERR_UNWRITABLE_ENCAP:
751 simple_error_message_box(
752 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
757 case WTAP_ERR_SHORT_READ:
758 simple_error_message_box(
759 "The capture file appears to have been cut short"
760 " in the middle of a packet.");
763 case WTAP_ERR_BAD_FILE:
764 simple_error_message_box(
765 "The capture file appears to be damaged or corrupt.\n(%s)",
770 case WTAP_ERR_DECOMPRESS:
771 simple_error_message_box(
772 "The compressed capture file appears to be damaged or corrupt.\n"
778 simple_error_message_box(
779 "An error occurred while reading the"
780 " capture file: %s.", wtap_strerror(err));
783 return CF_READ_ERROR;
790 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
793 volatile int newly_displayed_packets = 0;
796 gboolean create_proto_tree;
800 /* Compile the current display filter.
801 * We assume this will not fail since cf->dfilter is only set in
802 * cf_filter IFF the filter was valid.
804 compiled = dfilter_compile(cf->dfilter, &dfcode);
805 g_assert(!cf->dfilter || (compiled && dfcode));
807 /* Get the union of the flags for all tap listeners. */
808 tap_flags = union_of_tap_listener_flags();
810 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
814 packet_list_check_end();
815 /* Don't freeze/thaw the list when doing live capture */
816 /*packet_list_freeze();*/
818 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
820 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
823 gint64 data_offset = 0;
826 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
828 while (to_read != 0) {
829 wtap_cleareof(cf->wth);
830 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
833 if (cf->state == FILE_READ_ABORTED) {
834 /* Well, the user decided to exit Wireshark. Break out of the
835 loop, and let the code below (which is called even if there
836 aren't any packets left to read) exit. */
839 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
840 newly_displayed_packets++;
845 CATCH(OutOfMemoryError) {
846 simple_message_box(ESD_TYPE_ERROR, NULL,
847 "More information and workarounds can be found at\n"
848 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
849 "Sorry, but Wireshark has run out of memory and has to terminate now.");
851 /* Could we close the current capture and free up memory from that? */
852 return CF_READ_ABORTED;
854 /* we have to terminate, as we cannot recover from the memory error */
860 /* Update the file encapsulation; it might have changed based on the
861 packets we've read. */
862 cf->lnk_t = wtap_file_encap(cf->wth);
864 /* Cleanup and release all dfilter resources */
865 if (dfcode != NULL) {
866 dfilter_free(dfcode);
869 epan_dissect_cleanup(&edt);
871 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
872 cf->count, cf->state, *err);*/
874 /* Don't freeze/thaw the list when doing live capture */
875 /*packet_list_thaw();*/
876 /* With the new packet list the first packet
877 * isn't automatically selected.
879 if (!cf->current_frame)
880 packet_list_select_first_row();
882 /* moving to the end of the packet list - if the user requested so and
883 we have some new packets. */
884 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
885 packet_list_moveto_end();
887 if (cf->state == FILE_READ_ABORTED) {
888 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
889 so that our caller can kill off the capture child process;
890 this will cause an EOF on the pipe from the child, so
891 "cf_finish_tail()" will be called, and it will clean up
893 return CF_READ_ABORTED;
894 } else if (*err != 0) {
895 /* We got an error reading the capture file.
896 XXX - pop up a dialog box instead? */
897 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
898 wtap_strerror(*err), err_info, cf->filename);
901 return CF_READ_ERROR;
907 cf_fake_continue_tail(capture_file *cf) {
908 cf->state = FILE_READ_DONE;
912 cf_finish_tail(capture_file *cf, int *err)
919 gboolean create_proto_tree;
923 /* Compile the current display filter.
924 * We assume this will not fail since cf->dfilter is only set in
925 * cf_filter IFF the filter was valid.
927 compiled = dfilter_compile(cf->dfilter, &dfcode);
928 g_assert(!cf->dfilter || (compiled && dfcode));
930 /* Get the union of the flags for all tap listeners. */
931 tap_flags = union_of_tap_listener_flags();
932 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
934 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
936 if (cf->wth == NULL) {
938 return CF_READ_ERROR;
941 packet_list_check_end();
942 /* Don't freeze/thaw the list when doing live capture */
943 /*packet_list_freeze();*/
945 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
947 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
948 if (cf->state == FILE_READ_ABORTED) {
949 /* Well, the user decided to abort the read. Break out of the
950 loop, and let the code below (which is called even if there
951 aren't any packets left to read) exit. */
954 read_packet(cf, dfcode, &edt, cinfo, data_offset);
957 /* Cleanup and release all dfilter resources */
958 if (dfcode != NULL) {
959 dfilter_free(dfcode);
962 epan_dissect_cleanup(&edt);
964 /* Don't freeze/thaw the list when doing live capture */
965 /*packet_list_thaw();*/
967 if (cf->state == FILE_READ_ABORTED) {
968 /* Well, the user decided to abort the read. We're only called
969 when the child capture process closes the pipe to us (meaning
970 it's probably exited), so we can just close the capture
971 file; we return CF_READ_ABORTED so our caller can do whatever
972 is appropriate when that happens. */
974 return CF_READ_ABORTED;
977 if (auto_scroll_live && cf->count != 0)
978 packet_list_moveto_end();
980 /* We're done reading sequentially through the file. */
981 cf->state = FILE_READ_DONE;
983 /* We're done reading sequentially through the file; close the
984 sequential I/O side, to free up memory it requires. */
985 wtap_sequential_close(cf->wth);
987 /* Allow the protocol dissectors to free up memory that they
988 * don't need after the sequential run-through of the packets. */
989 postseq_cleanup_all_protocols();
991 /* Update the file encapsulation; it might have changed based on the
992 packets we've read. */
993 cf->lnk_t = wtap_file_encap(cf->wth);
995 /* Update the details in the file-set dialog, as the capture file
996 * has likely grown since we first stat-ed it */
997 fileset_update_file(cf->filename);
1000 /* We got an error reading the capture file.
1001 XXX - pop up a dialog box? */
1003 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
1004 wtap_strerror(*err), err_info, cf->filename);
1006 return CF_READ_ERROR;
1011 #endif /* HAVE_LIBPCAP */
1014 cf_get_display_name(capture_file *cf)
1018 /* Return a name to use in displays */
1019 if (!cf->is_tempfile) {
1020 /* Get the last component of the file name, and use that. */
1022 displayname = g_filename_display_basename(cf->filename);
1024 displayname=g_strdup("(No file)");
1027 /* The file we read is a temporary file from a live capture or
1028 a merge operation; we don't mention its name, but, if it's
1029 from a capture, give the source of the capture. */
1031 displayname = g_strdup(cf->source);
1033 displayname = g_strdup("(Untitled)");
1039 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1045 cf->source = g_strdup(source);
1047 cf->source = g_strdup("");
1051 const gchar *cf_get_tempfile_source(capture_file *cf) {
1059 /* XXX - use a macro instead? */
1061 cf_get_packet_count(capture_file *cf)
1066 /* XXX - use a macro instead? */
1068 cf_set_packet_count(capture_file *cf, int packet_count)
1070 cf->count = packet_count;
1073 /* XXX - use a macro instead? */
1075 cf_is_tempfile(capture_file *cf)
1077 return cf->is_tempfile;
1080 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1082 cf->is_tempfile = is_tempfile;
1086 /* XXX - use a macro instead? */
1087 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1089 cf->drops_known = drops_known;
1092 /* XXX - use a macro instead? */
1093 void cf_set_drops(capture_file *cf, guint32 drops)
1098 /* XXX - use a macro instead? */
1099 gboolean cf_get_drops_known(capture_file *cf)
1101 return cf->drops_known;
1104 /* XXX - use a macro instead? */
1105 guint32 cf_get_drops(capture_file *cf)
1110 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1112 cf->rfcode = rfcode;
1116 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1117 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1118 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1122 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1123 &cf->ref, cf->prev_dis);
1124 cf->prev_cap = fdata;
1126 if (dfcode != NULL) {
1127 epan_dissect_prime_dfilter(edt, dfcode);
1130 /* Dissect the frame. */
1131 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1133 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1134 if (dfcode != NULL) {
1135 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1137 if (fdata->flags.passed_dfilter) {
1138 /* This frame passed the display filter but it may depend on other
1139 * (potentially not displayed) frames. Find those frames and mark them
1142 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1145 fdata->flags.passed_dfilter = 1;
1147 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1148 cf->displayed_count++;
1150 if (add_to_packet_list) {
1151 /* We fill the needed columns from new_packet_list */
1152 row = packet_list_append(cinfo, fdata);
1155 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1157 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1158 cf->prev_dis = fdata;
1160 /* If we haven't yet seen the first frame, this is it.
1162 XXX - we must do this before we add the row to the display,
1163 as, if the display's GtkCList's selection mode is
1164 GTK_SELECTION_BROWSE, when the first entry is added to it,
1165 "cf_select_packet()" will be called, and it will fetch the row
1166 data for the 0th row, and will get a null pointer rather than
1167 "fdata", as "gtk_clist_append()" won't yet have returned and
1168 thus "gtk_clist_set_row_data()" won't yet have been called.
1170 We thus need to leave behind bread crumbs so that
1171 "cf_select_packet()" can find this frame. See the comment
1172 in "cf_select_packet()". */
1173 if (cf->first_displayed == 0)
1174 cf->first_displayed = fdata->num;
1176 /* This is the last frame we've seen so far. */
1177 cf->last_displayed = fdata->num;
1180 epan_dissect_reset(edt);
1184 /* read in a new packet */
1185 /* returns the row of the new packet in the packet list or -1 if not displayed */
1187 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1188 column_info *cinfo, gint64 offset)
1190 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1191 const guint8 *buf = wtap_buf_ptr(cf->wth);
1198 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1199 it's not already there.
1200 XXX - yes, this is O(N), so if every packet had a different
1201 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1202 there are probably going to be a small number of encapsulation types
1204 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1206 /* The frame number of this packet is one more than the count of
1207 frames in the file so far. */
1208 framenum = cf->count + 1;
1210 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1214 epan_dissect_t rf_edt;
1216 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1217 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1218 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1219 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1220 epan_dissect_cleanup(&rf_edt);
1224 /* This does a shallow copy of fdlocal, which is good enough. */
1225 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1228 if (phdr->opt_comment != NULL)
1229 cf->packet_comment_count++;
1230 cf->f_datalen = offset + fdlocal.cap_len;
1232 if (!cf->redissecting) {
1233 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1234 cinfo, phdr, buf, TRUE);
1242 cf_merge_files(char **out_filenamep, int in_file_count,
1243 char *const *in_filenames, int file_type, gboolean do_append)
1245 merge_in_file_t *in_files, *in_file;
1250 int open_err, read_err, write_err, close_err;
1254 gboolean got_read_error = FALSE, got_write_error = FALSE;
1256 progdlg_t *progbar = NULL;
1258 gint64 f_len, file_pos;
1260 GTimeVal start_time;
1261 gchar status_str[100];
1262 gint64 progbar_nextstep;
1263 gint64 progbar_quantum;
1264 gchar *display_basename;
1265 int selected_frame_type;
1266 gboolean fake_interface_ids = FALSE;
1268 /* open the input files */
1269 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1270 &open_err, &err_info, &err_fileno)) {
1272 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1277 if (*out_filenamep != NULL) {
1278 out_filename = *out_filenamep;
1279 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1283 out_fd = create_tempfile(&tmpname, "wireshark");
1286 out_filename = g_strdup(tmpname);
1287 *out_filenamep = out_filename;
1291 merge_close_in_files(in_file_count, in_files);
1293 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1297 selected_frame_type = merge_select_frame_type(in_file_count, in_files);
1299 /* If we are trying to merge a number of libpcap files with different encapsulation types
1300 * change the output file type to pcapng and create SHB and IDB:s for the new file use the
1301 * interface index stored in in_files per file to change the phdr before writing the datablock.
1302 * XXX should it be an option to convert to pcapng?
1304 * We need something similar when merging pcapng files possibly with an option to say
1305 * the same interface(s) used in all in files. SHBs comments should be merged together.
1307 if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP)) {
1308 /* Write output in pcapng format */
1309 wtapng_section_t *shb_hdr;
1310 wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
1311 wtapng_if_descr_t int_data, *file_int_data;
1312 GString *comment_gstr;
1314 fake_interface_ids = TRUE;
1315 /* Create SHB info */
1316 shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
1317 comment_gstr = g_string_new("");
1318 g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
1319 g_string_append_printf(comment_gstr, "File created by merging: \n");
1320 file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1322 for (i = 0; i < in_file_count; i++) {
1323 g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
1325 shb_hdr->section_length = -1;
1327 shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
1328 shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */
1329 /* description of the hardware used to create this section. */
1330 shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */
1331 /* of the operating system used to create this section. */
1332 shb_hdr->shb_user_appl = g_strdup("Wireshark"); /* NULL if not available, UTF-8 string containing the name */
1333 /* of the application used to create this section. */
1335 /* create fake IDB info */
1336 idb_inf = g_new(wtapng_iface_descriptions_t,1);
1337 /* TODO make this the number of DIFFERENT encapsulation types
1338 * check that snaplength is the same too?
1340 idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1342 for (i = 0; i < in_file_count; i++) {
1343 idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
1344 /* read the interface data from the in file to our combined interfca data */
1345 file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
1346 int_data.wtap_encap = file_int_data->wtap_encap;
1347 int_data.time_units_per_second = file_int_data->time_units_per_second;
1348 int_data.link_type = file_int_data->link_type;
1349 int_data.snap_len = file_int_data->snap_len;
1350 int_data.if_name = g_strdup(file_int_data->if_name);
1351 int_data.opt_comment = NULL;
1352 int_data.if_description = NULL;
1353 int_data.if_speed = 0;
1354 int_data.if_tsresol = 6;
1355 int_data.if_filter_str = NULL;
1356 int_data.bpf_filter_len = 0;
1357 int_data.if_filter_bpf_bytes = NULL;
1358 int_data.if_os = NULL;
1359 int_data.if_fcslen = -1;
1360 int_data.num_stat_entries = 0; /* Number of ISB:s */
1361 int_data.interface_statistics = NULL;
1363 g_array_append_val(idb_inf->interface_data, int_data);
1364 g_free(idb_inf_merge_file);
1366 /* Set fake interface Id in per file data */
1367 in_files[i].interface_id = i;
1370 pdh = wtap_dump_fdopen_ng(out_fd, file_type,
1371 selected_frame_type,
1372 merge_max_snapshot_length(in_file_count, in_files),
1373 FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
1377 merge_close_in_files(in_file_count, in_files);
1379 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1386 pdh = wtap_dump_fdopen(out_fd, file_type,
1387 selected_frame_type,
1388 merge_max_snapshot_length(in_file_count, in_files),
1389 FALSE /* compressed */, &open_err);
1392 merge_close_in_files(in_file_count, in_files);
1394 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1400 /* Get the sum of the sizes of all the files. */
1402 for (i = 0; i < in_file_count; i++)
1403 f_len += in_files[i].size;
1405 /* Update the progress bar when it gets to this value. */
1406 progbar_nextstep = 0;
1407 /* When we reach the value that triggers a progress bar update,
1408 bump that value by this amount. */
1409 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1410 /* Progress so far. */
1414 g_get_current_time(&start_time);
1416 /* do the merge (or append) */
1419 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1422 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1424 if (in_file == NULL) {
1429 if (read_err != 0) {
1430 /* I/O error reading from in_file */
1431 got_read_error = TRUE;
1435 /* Get the sum of the data offsets in all of the files. */
1437 for (i = 0; i < in_file_count; i++)
1438 data_offset += in_files[i].data_offset;
1440 /* Create the progress bar if necessary.
1441 We check on every iteration of the loop, so that it takes no
1442 longer than the standard time to create it (otherwise, for a
1443 large file, we might take considerably longer than that standard
1444 time in order to get to the next progress bar step). */
1445 if (progbar == NULL) {
1446 progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1447 FALSE, &stop_flag, &start_time, progbar_val);
1450 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1451 when we update it, we have to run the GTK+ main loop to get it
1452 to repaint what's pending, and doing so may involve an "ioctl()"
1453 to see if there's any pending input from an X server, and doing
1454 that for every packet can be costly, especially on a big file. */
1455 if (data_offset >= progbar_nextstep) {
1456 /* Get the sum of the seek positions in all of the files. */
1458 for (i = 0; i < in_file_count; i++)
1459 file_pos += wtap_read_so_far(in_files[i].wth);
1460 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1461 if (progbar_val > 1.0f) {
1462 /* Some file probably grew while we were reading it.
1463 That "shouldn't happen", so we'll just clip the progress
1467 if (progbar != NULL) {
1468 g_snprintf(status_str, sizeof(status_str),
1469 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1470 file_pos / 1024, f_len / 1024);
1471 update_progress_dlg(progbar, progbar_val, status_str);
1473 progbar_nextstep += progbar_quantum;
1477 /* Well, the user decided to abort the merge. */
1481 /* If we have WTAP_ENCAP_PER_PACKET and the infiles are of type
1482 * WTAP_FILE_TYPE_SUBTYPE_PCAP, we need to set the interface id
1483 * in the paket header = the interface index we used in the IDBs
1484 * interface description for this file(encapsulation type).
1486 if (fake_interface_ids) {
1487 struct wtap_pkthdr *phdr;
1489 phdr = wtap_phdr(in_file->wth);
1490 phdr->interface_id = in_file->interface_id;
1491 phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
1493 if (!wtap_dump(pdh, wtap_phdr(in_file->wth),
1494 wtap_buf_ptr(in_file->wth), &write_err)) {
1495 got_write_error = TRUE;
1500 /* We're done merging the files; destroy the progress bar if it was created. */
1501 if (progbar != NULL)
1502 destroy_progress_dlg(progbar);
1504 merge_close_in_files(in_file_count, in_files);
1505 if (!got_write_error) {
1506 if (!wtap_dump_close(pdh, &write_err))
1507 got_write_error = TRUE;
1510 * We already got a write error; no need to report another
1511 * write error on close.
1513 * Don't overwrite the earlier write error.
1515 (void)wtap_dump_close(pdh, &close_err);
1518 if (got_read_error) {
1520 * Find the file on which we got the error, and report the error.
1522 for (i = 0; i < in_file_count; i++) {
1523 if (in_files[i].state == GOT_ERROR) {
1524 /* Put up a message box noting that a read failed somewhere along
1526 display_basename = g_filename_display_basename(in_files[i].filename);
1529 case WTAP_ERR_UNWRITABLE_ENCAP:
1530 simple_error_message_box(
1531 "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1532 display_basename, err_info);
1536 case WTAP_ERR_SHORT_READ:
1537 simple_error_message_box(
1538 "The capture file %s appears to have been cut short"
1539 " in the middle of a packet.", display_basename);
1542 case WTAP_ERR_BAD_FILE:
1543 simple_error_message_box(
1544 "The capture file %s appears to be damaged or corrupt.\n(%s)",
1545 display_basename, err_info);
1549 case WTAP_ERR_DECOMPRESS:
1550 simple_error_message_box(
1551 "The compressed capture file %s appears to be damaged or corrupt.\n"
1552 "(%s)", display_basename, err_info);
1557 simple_error_message_box(
1558 "An error occurred while reading the"
1559 " capture file %s: %s.",
1560 display_basename, wtap_strerror(read_err));
1563 g_free(display_basename);
1568 if (got_write_error) {
1569 /* Put up an alert box for the write error. */
1570 if (write_err < 0) {
1571 /* Wiretap error. */
1572 switch (write_err) {
1574 case WTAP_ERR_UNWRITABLE_ENCAP:
1576 * This is a problem with the particular frame we're writing and
1577 * the file type and subtype we're writing; note that, and report
1578 * the frame number and file type/subtype.
1580 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1581 simple_error_message_box(
1582 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1583 in_file ? in_file->packet_num : 0, display_basename,
1584 wtap_file_type_subtype_string(file_type));
1585 g_free(display_basename);
1588 case WTAP_ERR_PACKET_TOO_LARGE:
1590 * This is a problem with the particular frame we're writing and
1591 * the file type and subtype we're writing; note that, and report
1592 * the frame number and file type/subtype.
1594 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1595 simple_error_message_box(
1596 "Frame %u of \"%s\" is too large for a \"%s\" file.",
1597 in_file ? in_file->packet_num : 0, display_basename,
1598 wtap_file_type_subtype_string(file_type));
1599 g_free(display_basename);
1603 display_basename = g_filename_display_basename(out_filename);
1604 simple_error_message_box(
1605 "An error occurred while writing to the file \"%s\": %s.",
1606 out_filename, wtap_strerror(write_err));
1607 g_free(display_basename);
1612 write_failure_alert_box(out_filename, write_err);
1616 if (got_read_error || got_write_error || stop_flag) {
1617 /* Callers aren't expected to treat an error or an explicit abort
1618 differently - we put up error dialogs ourselves, so they don't
1626 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1628 const char *filter_new = dftext ? dftext : "";
1629 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1631 GTimeVal start_time;
1633 /* if new filter equals old one, do nothing unless told to do so */
1634 if (!force && strcmp(filter_new, filter_old) == 0) {
1640 if (dftext == NULL) {
1641 /* The new filter is an empty filter (i.e., display all packets).
1642 * so leave dfcode==NULL
1646 * We have a filter; make a copy of it (as we'll be saving it),
1647 * and try to compile it.
1649 dftext = g_strdup(dftext);
1650 if (!dfilter_compile(dftext, &dfcode)) {
1651 /* The attempt failed; report an error. */
1652 simple_message_box(ESD_TYPE_ERROR, NULL,
1653 "See the help for a description of the display filter syntax.",
1654 "\"%s\" isn't a valid display filter: %s",
1655 dftext, dfilter_error_msg);
1661 if (dfcode == NULL) {
1662 /* Yes - free the filter text, and set it to null. */
1668 /* We have a valid filter. Replace the current filter. */
1669 g_free(cf->dfilter);
1670 cf->dfilter = dftext;
1671 g_get_current_time(&start_time);
1674 /* Now rescan the packet list, applying the new filter, but not
1675 throwing away information constructed on a previous pass. */
1676 if (dftext == NULL) {
1677 rescan_packets(cf, "Resetting", "Filter", FALSE);
1679 rescan_packets(cf, "Filtering", dftext, FALSE);
1682 /* Cleanup and release all dfilter resources */
1683 dfilter_free(dfcode);
1689 cf_reftime_packets(capture_file *cf)
1691 ref_time_packets(cf);
1695 cf_redissect_packets(capture_file *cf)
1697 if (cf->state != FILE_CLOSED) {
1698 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1703 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1704 struct wtap_pkthdr *phdr, Buffer *buf)
1708 gchar *display_basename;
1710 #ifdef WANT_PACKET_EDITOR
1711 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1712 if (G_UNLIKELY(fdata->file_off == -1)) {
1713 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1716 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1720 *phdr = frame->phdr;
1721 ws_buffer_assure_space(buf, frame->phdr.caplen);
1722 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1727 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1728 display_basename = g_filename_display_basename(cf->filename);
1731 case WTAP_ERR_UNWRITABLE_ENCAP:
1732 simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1733 display_basename, err_info);
1737 case WTAP_ERR_BAD_FILE:
1738 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1739 display_basename, wtap_strerror(err), err_info);
1744 simple_error_message_box(
1745 "An error occurred while reading from the file \"%s\": %s.",
1746 display_basename, wtap_strerror(err));
1749 g_free(display_basename);
1756 cf_read_record(capture_file *cf, frame_data *fdata)
1758 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1761 /* Rescan the list of packets, reconstructing the CList.
1763 "action" describes why we're doing this; it's used in the progress
1766 "action_item" describes what we're doing; it's used in the progress
1769 "redissect" is TRUE if we need to make the dissectors reconstruct
1770 any state information they have (because a preference that affects
1771 some dissector has changed, meaning some dissector might construct
1772 its state differently from the way it was constructed the last time). */
1774 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1776 /* Rescan packets new packet list */
1779 progdlg_t *progbar = NULL;
1782 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1783 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1784 gboolean selected_frame_seen;
1786 GTimeVal start_time;
1787 gchar status_str[100];
1788 int progbar_nextstep;
1789 int progbar_quantum;
1793 gboolean create_proto_tree;
1795 gboolean add_to_packet_list = FALSE;
1797 guint32 frames_count;
1799 /* Compile the current display filter.
1800 * We assume this will not fail since cf->dfilter is only set in
1801 * cf_filter IFF the filter was valid.
1803 compiled = dfilter_compile(cf->dfilter, &dfcode);
1804 g_assert(!cf->dfilter || (compiled && dfcode));
1806 /* Get the union of the flags for all tap listeners. */
1807 tap_flags = union_of_tap_listener_flags();
1808 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1810 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1812 reset_tap_listeners();
1813 /* Which frame, if any, is the currently selected frame?
1814 XXX - should the selected frame or the focus frame be the "current"
1815 frame, that frame being the one from which "Find Frame" searches
1817 selected_frame = cf->current_frame;
1819 /* Mark frame num as not found */
1820 selected_frame_num = -1;
1822 /* Freeze the packet list while we redo it, so we don't get any
1823 screen updates while it happens. */
1824 packet_list_freeze();
1827 /* We need to re-initialize all the state information that protocols
1828 keep, because some preference that controls a dissector has changed,
1829 which might cause the state information to be constructed differently
1830 by that dissector. */
1832 /* We might receive new packets while redissecting, and we don't
1833 want to dissect those before their time. */
1834 cf->redissecting = TRUE;
1836 /* 'reset' dissection session */
1837 epan_free(cf->epan);
1838 cf->epan = ws_epan_new(cf);
1839 cf->cinfo.epan = cf->epan;
1841 /* We need to redissect the packets so we have to discard our old
1842 * packet list store. */
1843 packet_list_clear();
1844 add_to_packet_list = TRUE;
1847 /* We don't yet know which will be the first and last frames displayed. */
1848 cf->first_displayed = 0;
1849 cf->last_displayed = 0;
1851 /* We currently don't display any packets */
1852 cf->displayed_count = 0;
1854 /* Iterate through the list of frames. Call a routine for each frame
1855 to check whether it should be displayed and, if so, add it to
1856 the display list. */
1858 cf->prev_dis = NULL;
1859 cf->prev_cap = NULL;
1862 /* Update the progress bar when it gets to this value. */
1863 progbar_nextstep = 0;
1864 /* When we reach the value that triggers a progress bar update,
1865 bump that value by this amount. */
1866 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1867 /* Count of packets at which we've looked. */
1869 /* Progress so far. */
1873 g_get_current_time(&start_time);
1875 /* no previous row yet */
1876 prev_frame_num = -1;
1879 preceding_frame_num = -1;
1880 preceding_frame = NULL;
1881 following_frame_num = -1;
1882 following_frame = NULL;
1884 selected_frame_seen = FALSE;
1886 frames_count = cf->count;
1888 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1890 for (framenum = 1; framenum <= frames_count; framenum++) {
1891 fdata = frame_data_sequence_find(cf->frames, framenum);
1893 /* Create the progress bar if necessary.
1894 We check on every iteration of the loop, so that it takes no
1895 longer than the standard time to create it (otherwise, for a
1896 large file, we might take considerably longer than that standard
1897 time in order to get to the next progress bar step). */
1898 if (progbar == NULL)
1899 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1900 &stop_flag, &start_time,
1903 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1904 when we update it, we have to run the GTK+ main loop to get it
1905 to repaint what's pending, and doing so may involve an "ioctl()"
1906 to see if there's any pending input from an X server, and doing
1907 that for every packet can be costly, especially on a big file. */
1908 if (count >= progbar_nextstep) {
1909 /* let's not divide by zero. I should never be started
1910 * with count == 0, so let's assert that
1912 g_assert(cf->count > 0);
1913 progbar_val = (gfloat) count / frames_count;
1915 if (progbar != NULL) {
1916 g_snprintf(status_str, sizeof(status_str),
1917 "%4u of %u frames", count, frames_count);
1918 update_progress_dlg(progbar, progbar_val, status_str);
1921 progbar_nextstep += progbar_quantum;
1925 /* Well, the user decided to abort the filtering. Just stop.
1927 XXX - go back to the previous filter? Users probably just
1928 want not to wait for a filtering operation to finish;
1929 unless we cancel by having no filter, reverting to the
1930 previous filter will probably be even more expensive than
1931 continuing the filtering, as it involves going back to the
1932 beginning and filtering, and even with no filter we currently
1933 have to re-generate the entire clist, which is also expensive.
1935 I'm not sure what Network Monitor does, but it doesn't appear
1936 to give you an unfiltered display if you cancel. */
1943 /* Since all state for the frame was destroyed, mark the frame
1944 * as not visited, free the GSList referring to the state
1945 * data (the per-frame data itself was freed by
1946 * "init_dissection()"), and null out the GSList pointer. */
1947 frame_data_reset(fdata);
1948 frames_count = cf->count;
1951 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1952 fdata->flags.dependent_of_displayed = 0;
1954 if (!cf_read_record(cf, fdata))
1955 break; /* error reading the frame */
1957 /* If the previous frame is displayed, and we haven't yet seen the
1958 selected frame, remember that frame - it's the closest one we've
1959 yet seen before the selected frame. */
1960 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1961 preceding_frame_num = prev_frame_num;
1962 preceding_frame = prev_frame;
1965 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1967 ws_buffer_start_ptr(&cf->buf),
1968 add_to_packet_list);
1970 /* If this frame is displayed, and this is the first frame we've
1971 seen displayed after the selected frame, remember this frame -
1972 it's the closest one we've yet seen at or after the selected
1974 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1975 following_frame_num = fdata->num;
1976 following_frame = fdata;
1978 if (fdata == selected_frame) {
1979 selected_frame_seen = TRUE;
1980 if (fdata->flags.passed_dfilter)
1981 selected_frame_num = fdata->num;
1984 /* Remember this frame - it'll be the previous frame
1985 on the next pass through the loop. */
1986 prev_frame_num = fdata->num;
1990 epan_dissect_cleanup(&edt);
1992 /* We are done redissecting the packet list. */
1993 cf->redissecting = FALSE;
1996 frames_count = cf->count;
1997 /* Clear out what remains of the visited flags and per-frame data
2000 XXX - that may cause various forms of bogosity when dissecting
2001 these frames, as they won't have been seen by this sequential
2002 pass, but the only alternative I see is to keep scanning them
2003 even though the user requested that the scan stop, and that
2004 would leave the user stuck with an Wireshark grinding on
2005 until it finishes. Should we just stick them with that? */
2006 for (; framenum <= frames_count; framenum++) {
2007 fdata = frame_data_sequence_find(cf->frames, framenum);
2008 frame_data_reset(fdata);
2012 /* We're done filtering the packets; destroy the progress bar if it
2014 if (progbar != NULL)
2015 destroy_progress_dlg(progbar);
2017 /* Unfreeze the packet list. */
2018 if (!add_to_packet_list)
2019 packet_list_recreate_visible_rows();
2021 /* Compute the time it took to filter the file */
2022 compute_elapsed(cf, &start_time);
2026 if (selected_frame_num == -1) {
2027 /* The selected frame didn't pass the filter. */
2028 if (selected_frame == NULL) {
2029 /* That's because there *was* no selected frame. Make the first
2030 displayed frame the current frame. */
2031 selected_frame_num = 0;
2033 /* Find the nearest displayed frame to the selected frame (whether
2034 it's before or after that frame) and make that the current frame.
2035 If the next and previous displayed frames are equidistant from the
2036 selected frame, choose the next one. */
2037 g_assert(following_frame == NULL ||
2038 following_frame->num >= selected_frame->num);
2039 g_assert(preceding_frame == NULL ||
2040 preceding_frame->num <= selected_frame->num);
2041 if (following_frame == NULL) {
2042 /* No frame after the selected frame passed the filter, so we
2043 have to select the last displayed frame before the selected
2045 selected_frame_num = preceding_frame_num;
2046 selected_frame = preceding_frame;
2047 } else if (preceding_frame == NULL) {
2048 /* No frame before the selected frame passed the filter, so we
2049 have to select the first displayed frame after the selected
2051 selected_frame_num = following_frame_num;
2052 selected_frame = following_frame;
2054 /* Frames before and after the selected frame passed the filter, so
2055 we'll select the previous frame */
2056 selected_frame_num = preceding_frame_num;
2057 selected_frame = preceding_frame;
2062 if (selected_frame_num == -1) {
2063 /* There are no frames displayed at all. */
2064 cf_unselect_packet(cf);
2066 /* Either the frame that was selected passed the filter, or we've
2067 found the nearest displayed frame to that frame. Select it, make
2068 it the focus row, and make it visible. */
2069 /* Set to invalid to force update of packet list and packet details */
2070 cf->current_row = -1;
2071 if (selected_frame_num == 0) {
2072 packet_list_select_first_row();
2074 if (!packet_list_select_row_from_data(selected_frame)) {
2075 /* We didn't find a row corresponding to this frame.
2076 This means that the frame isn't being displayed currently,
2077 so we can't select it. */
2078 simple_message_box(ESD_TYPE_INFO, NULL,
2079 "The capture file is probably not fully dissected.",
2080 "End of capture exceeded.");
2085 /* Cleanup and release all dfilter resources */
2086 dfilter_free(dfcode);
2091 * Scan trough all frame data and recalculate the ref time
2092 * without rereading the file.
2093 * XXX - do we need a progres bar or is this fast enough?
2096 ref_time_packets(capture_file *cf)
2103 cf->prev_dis = NULL;
2106 for (framenum = 1; framenum <= cf->count; framenum++) {
2107 fdata = frame_data_sequence_find(cf->frames, framenum);
2109 /* just add some value here until we know if it is being displayed or not */
2110 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
2116 /* If we don't have the time stamp of the first packet in the
2117 capture, it's because this is the first packet. Save the time
2118 stamp of this packet as the time stamp of the first packet. */
2119 if (cf->ref == NULL)
2121 /* if this frames is marked as a reference time frame, reset
2122 firstsec and firstusec to this frame */
2123 if (fdata->flags.ref_time)
2126 /* If we don't have the time stamp of the previous displayed packet,
2127 it's because this is the first displayed packet. Save the time
2128 stamp of this packet as the time stamp of the previous displayed
2130 if (cf->prev_dis == NULL) {
2131 cf->prev_dis = fdata;
2134 /* Get the time elapsed between the first packet and this packet. */
2135 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
2136 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
2138 /* If it's greater than the current elapsed time, set the elapsed time
2139 to it (we check for "greater than" so as not to be confused by
2140 time moving backwards). */
2141 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2142 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2143 cf->elapsed_time = rel_ts;
2146 /* If this frame is displayed, get the time elapsed between the
2147 previous displayed packet and this packet. */
2148 if ( fdata->flags.passed_dfilter ) {
2149 fdata->prev_dis_num = cf->prev_dis->num;
2150 cf->prev_dis = fdata;
2156 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2157 /* This frame either passed the display filter list or is marked as
2158 a time reference frame. All time reference frames are displayed
2159 even if they don't pass the display filter */
2160 if (fdata->flags.ref_time) {
2161 /* if this was a TIME REF frame we should reset the cum_bytes field */
2162 cf->cum_bytes = fdata->pkt_len;
2163 fdata->cum_bytes = cf->cum_bytes;
2165 /* increase cum_bytes with this packets length */
2166 cf->cum_bytes += fdata->pkt_len;
2179 process_specified_records(capture_file *cf, packet_range_t *range,
2180 const char *string1, const char *string2, gboolean terminate_is_stop,
2181 gboolean (*callback)(capture_file *, frame_data *,
2182 struct wtap_pkthdr *, const guint8 *, void *),
2183 void *callback_args)
2188 psp_return_t ret = PSP_FINISHED;
2190 progdlg_t *progbar = NULL;
2193 gboolean progbar_stop_flag;
2194 GTimeVal progbar_start_time;
2195 gchar progbar_status_str[100];
2196 int progbar_nextstep;
2197 int progbar_quantum;
2198 range_process_e process_this;
2199 struct wtap_pkthdr phdr;
2201 wtap_phdr_init(&phdr);
2202 ws_buffer_init(&buf, 1500);
2204 /* Update the progress bar when it gets to this value. */
2205 progbar_nextstep = 0;
2206 /* When we reach the value that triggers a progress bar update,
2207 bump that value by this amount. */
2208 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2209 /* Count of packets at which we've looked. */
2211 /* Progress so far. */
2214 progbar_stop_flag = FALSE;
2215 g_get_current_time(&progbar_start_time);
2218 packet_range_process_init(range);
2220 /* Iterate through all the packets, printing the packets that
2221 were selected by the current display filter. */
2222 for (framenum = 1; framenum <= cf->count; framenum++) {
2223 fdata = frame_data_sequence_find(cf->frames, framenum);
2225 /* Create the progress bar if necessary.
2226 We check on every iteration of the loop, so that it takes no
2227 longer than the standard time to create it (otherwise, for a
2228 large file, we might take considerably longer than that standard
2229 time in order to get to the next progress bar step). */
2230 if (progbar == NULL)
2231 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2234 &progbar_start_time,
2237 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2238 when we update it, we have to run the GTK+ main loop to get it
2239 to repaint what's pending, and doing so may involve an "ioctl()"
2240 to see if there's any pending input from an X server, and doing
2241 that for every packet can be costly, especially on a big file. */
2242 if (progbar_count >= progbar_nextstep) {
2243 /* let's not divide by zero. I should never be started
2244 * with count == 0, so let's assert that
2246 g_assert(cf->count > 0);
2247 progbar_val = (gfloat) progbar_count / cf->count;
2249 if (progbar != NULL) {
2250 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2251 "%4u of %u packets", progbar_count, cf->count);
2252 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2255 progbar_nextstep += progbar_quantum;
2258 if (progbar_stop_flag) {
2259 /* Well, the user decided to abort the operation. Just stop,
2260 and arrange to return PSP_STOPPED to our caller, so they know
2261 it was stopped explicitly. */
2268 if (range != NULL) {
2269 /* do we have to process this packet? */
2270 process_this = packet_range_process_packet(range, fdata);
2271 if (process_this == range_process_next) {
2272 /* this packet uninteresting, continue with next one */
2274 } else if (process_this == range_processing_finished) {
2275 /* all interesting packets processed, stop the loop */
2280 /* Get the packet */
2281 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2282 /* Attempt to get the packet failed. */
2286 /* Process the packet */
2287 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2288 /* Callback failed. We assume it reported the error appropriately. */
2294 /* We're done printing the packets; destroy the progress bar if
2296 if (progbar != NULL)
2297 destroy_progress_dlg(progbar);
2299 wtap_phdr_cleanup(&phdr);
2300 ws_buffer_free(&buf);
2308 } retap_callback_args_t;
2311 retap_packet(capture_file *cf, frame_data *fdata,
2312 struct wtap_pkthdr *phdr, const guint8 *pd,
2315 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2317 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2318 epan_dissect_reset(&args->edt);
2324 cf_retap_packets(capture_file *cf)
2326 packet_range_t range;
2327 retap_callback_args_t callback_args;
2328 gboolean construct_protocol_tree;
2329 gboolean filtering_tap_listeners;
2333 /* Presumably the user closed the capture file. */
2335 return CF_READ_ABORTED;
2338 /* Do we have any tap listeners with filters? */
2339 filtering_tap_listeners = have_filtering_tap_listeners();
2341 tap_flags = union_of_tap_listener_flags();
2343 /* If any tap listeners have filters, or require the protocol tree,
2344 construct the protocol tree. */
2345 construct_protocol_tree = filtering_tap_listeners ||
2346 (tap_flags & TL_REQUIRES_PROTO_TREE);
2348 /* If any tap listeners require the columns, construct them. */
2349 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2351 /* Reset the tap listeners. */
2352 reset_tap_listeners();
2354 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2356 /* Iterate through the list of packets, dissecting all packets and
2357 re-running the taps. */
2358 packet_range_init(&range, cf);
2359 packet_range_process_init(&range);
2361 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2362 "all packets", TRUE, retap_packet,
2365 epan_dissect_cleanup(&callback_args.edt);
2369 /* Completed successfully. */
2373 /* Well, the user decided to abort the refiltering.
2374 Return CF_READ_ABORTED so our caller knows they did that. */
2375 return CF_READ_ABORTED;
2378 /* Error while retapping. */
2379 return CF_READ_ERROR;
2382 g_assert_not_reached();
2387 print_args_t *print_args;
2388 gboolean print_header_line;
2389 char *header_line_buf;
2390 int header_line_buf_len;
2391 gboolean print_formfeed;
2392 gboolean print_separator;
2396 int num_visible_cols;
2399 } print_callback_args_t;
2402 print_packet(capture_file *cf, frame_data *fdata,
2403 struct wtap_pkthdr *phdr, const guint8 *pd,
2406 print_callback_args_t *args = (print_callback_args_t *)argsp;
2412 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2413 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2415 /* Fill in the column information if we're printing the summary
2417 if (args->print_args->print_summary) {
2418 col_custom_prime_edt(&args->edt, &cf->cinfo);
2419 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2420 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2422 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2424 if (args->print_formfeed) {
2425 if (!new_page(args->print_args->stream))
2428 if (args->print_separator) {
2429 if (!print_line(args->print_args->stream, 0, ""))
2435 * We generate bookmarks, if the output format supports them.
2436 * The name is "__frameN__".
2438 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2440 if (args->print_args->print_summary) {
2441 if (!args->print_args->print_col_headings)
2442 args->print_header_line = FALSE;
2443 if (args->print_header_line) {
2444 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2446 args->print_header_line = FALSE; /* we might not need to print any more */
2448 cp = &args->line_buf[0];
2450 for (i = 0; i < args->num_visible_cols; i++) {
2451 /* Find the length of the string for this column. */
2452 column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
2453 if (args->col_widths[i] > column_len)
2454 column_len = args->col_widths[i];
2456 /* Make sure there's room in the line buffer for the column; if not,
2457 double its length. */
2458 line_len += column_len + 1; /* "+1" for space */
2459 if (line_len > args->line_buf_len) {
2460 cp_off = (int) (cp - args->line_buf);
2461 args->line_buf_len = 2 * line_len;
2462 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2463 cp = args->line_buf + cp_off;
2466 /* Right-justify the packet number column. */
2467 if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
2468 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2470 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2472 if (i != args->num_visible_cols - 1)
2478 * Generate a bookmark, using the summary line as the title.
2480 if (!print_bookmark(args->print_args->stream, bookmark_name,
2484 if (!print_line(args->print_args->stream, 0, args->line_buf))
2488 * Generate a bookmark, using "Frame N" as the title, as we're not
2489 * printing the summary line.
2491 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2492 if (!print_bookmark(args->print_args->stream, bookmark_name,
2495 } /* if (print_summary) */
2497 if (args->print_args->print_dissections != print_dissections_none) {
2498 if (args->print_args->print_summary) {
2499 /* Separate the summary line from the tree with a blank line. */
2500 if (!print_line(args->print_args->stream, 0, ""))
2504 /* Print the information in that tree. */
2505 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2508 /* Print a blank line if we print anything after this (aka more than one packet). */
2509 args->print_separator = TRUE;
2511 /* Print a header line if we print any more packet summaries */
2512 if (args->print_args->print_col_headings)
2513 args->print_header_line = TRUE;
2516 if (args->print_args->print_hex) {
2517 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2518 if (!print_line(args->print_args->stream, 0, ""))
2521 /* Print the full packet data as hex. */
2522 if (!print_hex_data(args->print_args->stream, &args->edt))
2525 /* Print a blank line if we print anything after this (aka more than one packet). */
2526 args->print_separator = TRUE;
2528 /* Print a header line if we print any more packet summaries */
2529 if (args->print_args->print_col_headings)
2530 args->print_header_line = TRUE;
2531 } /* if (args->print_args->print_dissections != print_dissections_none) */
2533 epan_dissect_reset(&args->edt);
2535 /* do we want to have a formfeed between each packet from now on? */
2536 if (args->print_args->print_formfeed) {
2537 args->print_formfeed = TRUE;
2543 epan_dissect_reset(&args->edt);
2548 cf_print_packets(capture_file *cf, print_args_t *print_args)
2550 print_callback_args_t callback_args;
2553 int i, cp_off, column_len, line_len;
2554 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2558 gboolean proto_tree_needed;
2560 callback_args.print_args = print_args;
2561 callback_args.print_header_line = print_args->print_col_headings;
2562 callback_args.header_line_buf = NULL;
2563 callback_args.header_line_buf_len = 256;
2564 callback_args.print_formfeed = FALSE;
2565 callback_args.print_separator = FALSE;
2566 callback_args.line_buf = NULL;
2567 callback_args.line_buf_len = 256;
2568 callback_args.col_widths = NULL;
2569 callback_args.num_visible_cols = 0;
2570 callback_args.visible_cols = NULL;
2572 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2573 destroy_print_stream(print_args->stream);
2574 return CF_PRINT_WRITE_ERROR;
2577 if (print_args->print_summary) {
2578 /* We're printing packet summaries. Allocate the header line buffer
2579 and get the column widths. */
2580 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2582 /* Find the number of visible columns and the last visible column */
2583 for (i = 0; i < prefs.num_cols; i++) {
2585 clp = g_list_nth(prefs.col_list, i);
2586 if (clp == NULL) /* Sanity check, Invalid column requested */
2589 cfmt = (fmt_data *) clp->data;
2590 if (cfmt->visible) {
2592 last_visible_col = i;
2596 /* Find the widths for each of the columns - maximum of the
2597 width of the title and the width of the data - and construct
2598 a buffer with a line containing the column titles. */
2599 callback_args.num_visible_cols = num_visible_col;
2600 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2601 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2602 cp = &callback_args.header_line_buf[0];
2604 visible_col_count = 0;
2605 for (i = 0; i < cf->cinfo.num_cols; i++) {
2607 clp = g_list_nth(prefs.col_list, i);
2608 if (clp == NULL) /* Sanity check, Invalid column requested */
2611 cfmt = (fmt_data *) clp->data;
2612 if (cfmt->visible == FALSE)
2615 /* Save the order of visible columns */
2616 callback_args.visible_cols[visible_col_count] = i;
2618 /* Don't pad the last column. */
2619 if (i == last_visible_col)
2620 callback_args.col_widths[visible_col_count] = 0;
2622 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
2623 data_width = get_column_char_width(get_column_format(i));
2624 if (data_width > callback_args.col_widths[visible_col_count])
2625 callback_args.col_widths[visible_col_count] = data_width;
2628 /* Find the length of the string for this column. */
2629 column_len = (int) strlen(cf->cinfo.col_title[i]);
2630 if (callback_args.col_widths[i] > column_len)
2631 column_len = callback_args.col_widths[visible_col_count];
2633 /* Make sure there's room in the line buffer for the column; if not,
2634 double its length. */
2635 line_len += column_len + 1; /* "+1" for space */
2636 if (line_len > callback_args.header_line_buf_len) {
2637 cp_off = (int) (cp - callback_args.header_line_buf);
2638 callback_args.header_line_buf_len = 2 * line_len;
2639 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2640 callback_args.header_line_buf_len + 1);
2641 cp = callback_args.header_line_buf + cp_off;
2644 /* Right-justify the packet number column. */
2645 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2646 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2648 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2650 if (i != cf->cinfo.num_cols - 1)
2653 visible_col_count++;
2657 /* Now start out the main line buffer with the same length as the
2658 header line buffer. */
2659 callback_args.line_buf_len = callback_args.header_line_buf_len;
2660 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2661 } /* if (print_summary) */
2663 /* Create the protocol tree, and make it visible, if we're printing
2664 the dissection or the hex data.
2665 XXX - do we need it if we're just printing the hex data? */
2667 callback_args.print_args->print_dissections != print_dissections_none ||
2668 callback_args.print_args->print_hex ||
2669 have_custom_cols(&cf->cinfo);
2670 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2672 /* Iterate through the list of packets, printing the packets we were
2674 ret = process_specified_records(cf, &print_args->range, "Printing",
2675 "selected packets", TRUE, print_packet,
2677 epan_dissect_cleanup(&callback_args.edt);
2678 g_free(callback_args.header_line_buf);
2679 g_free(callback_args.line_buf);
2680 g_free(callback_args.col_widths);
2681 g_free(callback_args.visible_cols);
2686 /* Completed successfully. */
2690 /* Well, the user decided to abort the printing.
2692 XXX - note that what got generated before they did that
2693 will get printed if we're piping to a print program; we'd
2694 have to write to a file and then hand that to the print
2695 program to make it actually not print anything. */
2699 /* Error while printing.
2701 XXX - note that what got generated before they did that
2702 will get printed if we're piping to a print program; we'd
2703 have to write to a file and then hand that to the print
2704 program to make it actually not print anything. */
2705 destroy_print_stream(print_args->stream);
2706 return CF_PRINT_WRITE_ERROR;
2709 if (!print_finale(print_args->stream)) {
2710 destroy_print_stream(print_args->stream);
2711 return CF_PRINT_WRITE_ERROR;
2714 if (!destroy_print_stream(print_args->stream))
2715 return CF_PRINT_WRITE_ERROR;
2723 } write_packet_callback_args_t;
2726 write_pdml_packet(capture_file *cf, frame_data *fdata,
2727 struct wtap_pkthdr *phdr, const guint8 *pd,
2730 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2732 /* Create the protocol tree, but don't fill in the column information. */
2733 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2735 /* Write out the information in that tree. */
2736 write_pdml_proto_tree(&args->edt, args->fh);
2738 epan_dissect_reset(&args->edt);
2740 return !ferror(args->fh);
2744 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2746 write_packet_callback_args_t callback_args;
2750 fh = ws_fopen(print_args->file, "w");
2752 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2754 write_pdml_preamble(fh, cf->filename);
2757 return CF_PRINT_WRITE_ERROR;
2760 callback_args.fh = fh;
2761 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2763 /* Iterate through the list of packets, printing the packets we were
2765 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2766 "selected packets", TRUE,
2767 write_pdml_packet, &callback_args);
2769 epan_dissect_cleanup(&callback_args.edt);
2774 /* Completed successfully. */
2778 /* Well, the user decided to abort the printing. */
2782 /* Error while printing. */
2784 return CF_PRINT_WRITE_ERROR;
2787 write_pdml_finale(fh);
2790 return CF_PRINT_WRITE_ERROR;
2793 /* XXX - check for an error */
2800 write_psml_packet(capture_file *cf, frame_data *fdata,
2801 struct wtap_pkthdr *phdr, const guint8 *pd,
2804 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2806 /* Fill in the column information */
2807 col_custom_prime_edt(&args->edt, &cf->cinfo);
2808 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2809 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2811 /* Write out the column information. */
2812 write_psml_columns(&args->edt, args->fh);
2814 epan_dissect_reset(&args->edt);
2816 return !ferror(args->fh);
2820 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2822 write_packet_callback_args_t callback_args;
2826 gboolean proto_tree_needed;
2828 fh = ws_fopen(print_args->file, "w");
2830 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2832 write_psml_preamble(&cf->cinfo, fh);
2835 return CF_PRINT_WRITE_ERROR;
2838 callback_args.fh = fh;
2840 /* Fill in the column information, only create the protocol tree
2841 if having custom columns. */
2842 proto_tree_needed = have_custom_cols(&cf->cinfo);
2843 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2845 /* Iterate through the list of packets, printing the packets we were
2847 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2848 "selected packets", TRUE,
2849 write_psml_packet, &callback_args);
2851 epan_dissect_cleanup(&callback_args.edt);
2856 /* Completed successfully. */
2860 /* Well, the user decided to abort the printing. */
2864 /* Error while printing. */
2866 return CF_PRINT_WRITE_ERROR;
2869 write_psml_finale(fh);
2872 return CF_PRINT_WRITE_ERROR;
2875 /* XXX - check for an error */
2882 write_csv_packet(capture_file *cf, frame_data *fdata,
2883 struct wtap_pkthdr *phdr, const guint8 *pd,
2886 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2888 /* Fill in the column information */
2889 col_custom_prime_edt(&args->edt, &cf->cinfo);
2890 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2891 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2893 /* Write out the column information. */
2894 write_csv_columns(&args->edt, args->fh);
2896 epan_dissect_reset(&args->edt);
2898 return !ferror(args->fh);
2902 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2904 write_packet_callback_args_t callback_args;
2905 gboolean proto_tree_needed;
2909 fh = ws_fopen(print_args->file, "w");
2911 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2913 write_csv_column_titles(&cf->cinfo, fh);
2916 return CF_PRINT_WRITE_ERROR;
2919 callback_args.fh = fh;
2921 /* only create the protocol tree if having custom columns. */
2922 proto_tree_needed = have_custom_cols(&cf->cinfo);
2923 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2925 /* Iterate through the list of packets, printing the packets we were
2927 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2928 "selected packets", TRUE,
2929 write_csv_packet, &callback_args);
2931 epan_dissect_cleanup(&callback_args.edt);
2936 /* Completed successfully. */
2940 /* Well, the user decided to abort the printing. */
2944 /* Error while printing. */
2946 return CF_PRINT_WRITE_ERROR;
2949 /* XXX - check for an error */
2956 carrays_write_packet(capture_file *cf, frame_data *fdata,
2957 struct wtap_pkthdr *phdr,
2958 const guint8 *pd, void *argsp)
2960 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2962 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2963 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2964 epan_dissect_reset(&args->edt);
2966 return !ferror(args->fh);
2970 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2972 write_packet_callback_args_t callback_args;
2976 fh = ws_fopen(print_args->file, "w");
2979 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2983 return CF_PRINT_WRITE_ERROR;
2986 callback_args.fh = fh;
2987 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2989 /* Iterate through the list of packets, printing the packets we were
2991 ret = process_specified_records(cf, &print_args->range,
2993 "selected packets", TRUE,
2994 carrays_write_packet, &callback_args);
2996 epan_dissect_cleanup(&callback_args.edt);
3000 /* Completed successfully. */
3003 /* Well, the user decided to abort the printing. */
3006 /* Error while printing. */
3008 return CF_PRINT_WRITE_ERROR;
3016 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3017 search_direction dir)
3021 mdata.string = string;
3022 mdata.string_len = strlen(string);
3023 return find_packet(cf, match_protocol_tree, &mdata, dir);
3027 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3029 mdata->frame_matched = FALSE;
3030 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3031 mdata->string_len = strlen(mdata->string);
3033 /* Iterate through all the nodes looking for matching text */
3034 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3035 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3039 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3041 match_data *mdata = (match_data *)criterion;
3044 /* Load the frame's data. */
3045 if (!cf_read_record(cf, fdata)) {
3046 /* Attempt to get the packet failed. */
3050 /* Construct the protocol tree, including the displayed text */
3051 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3052 /* We don't need the column information */
3053 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3055 /* Iterate through all the nodes, seeing if they have text that matches. */
3057 mdata->frame_matched = FALSE;
3058 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3059 epan_dissect_cleanup(&edt);
3060 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3064 match_subtree_text(proto_node *node, gpointer data)
3066 match_data *mdata = (match_data *) data;
3067 const gchar *string = mdata->string;
3068 size_t string_len = mdata->string_len;
3069 capture_file *cf = mdata->cf;
3070 field_info *fi = PNODE_FINFO(node);
3071 gchar label_str[ITEM_LABEL_LENGTH];
3078 /* dissection with an invisible proto tree? */
3081 if (mdata->frame_matched) {
3082 /* We already had a match; don't bother doing any more work. */
3086 /* Don't match invisible entries. */
3087 if (PROTO_ITEM_IS_HIDDEN(node))
3090 /* was a free format label produced? */
3092 label_ptr = fi->rep->representation;
3094 /* no, make a generic label */
3095 label_ptr = label_str;
3096 proto_item_fill_label(fi, label_str);
3099 /* Does that label match? */
3100 label_len = strlen(label_ptr);
3101 for (i = 0; i < label_len; i++) {
3102 c_char = label_ptr[i];
3104 c_char = toupper(c_char);
3105 if (c_char == string[c_match]) {
3107 if (c_match == string_len) {
3108 /* No need to look further; we have a match */
3109 mdata->frame_matched = TRUE;
3117 /* Recurse into the subtree, if it exists */
3118 if (node->first_child != NULL)
3119 proto_tree_children_foreach(node, match_subtree_text, mdata);
3123 cf_find_packet_summary_line(capture_file *cf, const char *string,
3124 search_direction dir)
3128 mdata.string = string;
3129 mdata.string_len = strlen(string);
3130 return find_packet(cf, match_summary_line, &mdata, dir);
3134 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3136 match_data *mdata = (match_data *)criterion;
3137 const gchar *string = mdata->string;
3138 size_t string_len = mdata->string_len;
3140 const char *info_column;
3141 size_t info_column_len;
3142 match_result result = MR_NOTMATCHED;
3148 /* Load the frame's data. */
3149 if (!cf_read_record(cf, fdata)) {
3150 /* Attempt to get the packet failed. */
3154 /* Don't bother constructing the protocol tree */
3155 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3156 /* Get the column information */
3157 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3160 /* Find the Info column */
3161 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3162 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3163 /* Found it. See if we match. */
3164 info_column = edt.pi.cinfo->col_data[colx];
3165 info_column_len = strlen(info_column);
3166 for (i = 0; i < info_column_len; i++) {
3167 c_char = info_column[i];
3169 c_char = toupper(c_char);
3170 if (c_char == string[c_match]) {
3172 if (c_match == string_len) {
3173 result = MR_MATCHED;
3182 epan_dissect_cleanup(&edt);
3189 } cbs_t; /* "Counted byte string" */
3193 * The current match_* routines only support ASCII case insensitivity and don't
3194 * convert UTF-8 inputs to UTF-16 for matching.
3196 * We could modify them to use the GLib Unicode routines or the International
3197 * Components for Unicode library but it's not apparent that we could do so
3198 * without consuming a lot more CPU and memory or that searching would be
3199 * significantly better.
3203 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3204 search_direction dir)
3209 info.data_len = string_size;
3211 /* String or hex search? */
3213 /* String search - what type of string? */
3214 switch (cf->scs_type) {
3216 case SCS_NARROW_AND_WIDE:
3217 return find_packet(cf, match_narrow_and_wide, &info, dir);
3220 return find_packet(cf, match_narrow, &info, dir);
3223 return find_packet(cf, match_wide, &info, dir);
3226 g_assert_not_reached();
3230 return find_packet(cf, match_binary, &info, dir);
3234 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3236 cbs_t *info = (cbs_t *)criterion;
3237 const guint8 *ascii_text = info->data;
3238 size_t textlen = info->data_len;
3239 match_result result;
3246 /* Load the frame's data. */
3247 if (!cf_read_record(cf, fdata)) {
3248 /* Attempt to get the packet failed. */
3252 result = MR_NOTMATCHED;
3253 buf_len = fdata->cap_len;
3254 pd = ws_buffer_start_ptr(&cf->buf);
3256 while (i < buf_len) {
3259 c_char = toupper(c_char);
3260 if (c_char != '\0') {
3261 if (c_char == ascii_text[c_match]) {
3263 if (c_match == textlen) {
3264 result = MR_MATCHED;
3265 cf->search_pos = i; /* Save the position of the last character
3266 for highlighting the field. */
3271 g_assert(i>=c_match);
3272 i -= (guint32)c_match;
3282 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3285 cbs_t *info = (cbs_t *)criterion;
3286 const guint8 *ascii_text = info->data;
3287 size_t textlen = info->data_len;
3288 match_result result;
3294 /* Load the frame's data. */
3295 if (!cf_read_record(cf, fdata)) {
3296 /* Attempt to get the packet failed. */
3300 result = MR_NOTMATCHED;
3301 buf_len = fdata->cap_len;
3302 pd = ws_buffer_start_ptr(&cf->buf);
3304 while (i < buf_len) {
3307 c_char = toupper(c_char);
3308 if (c_char == ascii_text[c_match]) {
3310 if (c_match == textlen) {
3311 result = MR_MATCHED;
3312 cf->search_pos = i; /* Save the position of the last character
3313 for highlighting the field. */
3318 g_assert(i>=c_match);
3319 i -= (guint32)c_match;
3329 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3331 cbs_t *info = (cbs_t *)criterion;
3332 const guint8 *ascii_text = info->data;
3333 size_t textlen = info->data_len;
3334 match_result result;
3341 /* Load the frame's data. */
3342 if (!cf_read_record(cf, fdata)) {
3343 /* Attempt to get the packet failed. */
3347 result = MR_NOTMATCHED;
3348 buf_len = fdata->cap_len;
3349 pd = ws_buffer_start_ptr(&cf->buf);
3351 while (i < buf_len) {
3354 c_char = toupper(c_char);
3355 if (c_char == ascii_text[c_match]) {
3357 if (c_match == textlen) {
3358 result = MR_MATCHED;
3359 cf->search_pos = i; /* Save the position of the last character
3360 for highlighting the field. */
3366 g_assert(i>=(c_match*2));
3367 i -= (guint32)c_match*2;
3376 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3378 cbs_t *info = (cbs_t *)criterion;
3379 const guint8 *binary_data = info->data;
3380 size_t datalen = info->data_len;
3381 match_result result;
3387 /* Load the frame's data. */
3388 if (!cf_read_record(cf, fdata)) {
3389 /* Attempt to get the packet failed. */
3393 result = MR_NOTMATCHED;
3394 buf_len = fdata->cap_len;
3395 pd = ws_buffer_start_ptr(&cf->buf);
3397 while (i < buf_len) {
3398 if (pd[i] == binary_data[c_match]) {
3400 if (c_match == datalen) {
3401 result = MR_MATCHED;
3402 cf->search_pos = i; /* Save the position of the last character
3403 for highlighting the field. */
3408 g_assert(i>=c_match);
3409 i -= (guint32)c_match;
3418 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3419 search_direction dir)
3421 return find_packet(cf, match_dfilter, sfcode, dir);
3425 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3426 search_direction dir)
3431 if (!dfilter_compile(filter, &sfcode)) {
3433 * XXX - this shouldn't happen, as the filter string is machine
3438 if (sfcode == NULL) {
3440 * XXX - this shouldn't happen, as the filter string is machine
3445 result = find_packet(cf, match_dfilter, sfcode, dir);
3446 dfilter_free(sfcode);
3451 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3453 dfilter_t *sfcode = (dfilter_t *)criterion;
3455 match_result result;
3457 /* Load the frame's data. */
3458 if (!cf_read_record(cf, fdata)) {
3459 /* Attempt to get the packet failed. */
3463 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3464 epan_dissect_prime_dfilter(&edt, sfcode);
3465 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3466 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3467 epan_dissect_cleanup(&edt);
3472 cf_find_packet_marked(capture_file *cf, search_direction dir)
3474 return find_packet(cf, match_marked, NULL, dir);
3478 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3480 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3484 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3486 return find_packet(cf, match_time_reference, NULL, dir);
3490 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3492 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3496 find_packet(capture_file *cf,
3497 match_result (*match_function)(capture_file *, frame_data *, void *),
3498 void *criterion, search_direction dir)
3500 frame_data *start_fd;
3503 frame_data *new_fd = NULL;
3504 progdlg_t *progbar = NULL;
3509 GTimeVal start_time;
3510 gchar status_str[100];
3511 int progbar_nextstep;
3512 int progbar_quantum;
3514 match_result result;
3516 start_fd = cf->current_frame;
3517 if (start_fd != NULL) {
3518 /* Iterate through the list of packets, starting at the packet we've
3519 picked, calling a routine to run the filter on the packet, see if
3520 it matches, and stop if so. */
3522 framenum = start_fd->num;
3524 /* Update the progress bar when it gets to this value. */
3525 progbar_nextstep = 0;
3526 /* When we reach the value that triggers a progress bar update,
3527 bump that value by this amount. */
3528 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3529 /* Progress so far. */
3533 g_get_current_time(&start_time);
3535 title = cf->sfilter?cf->sfilter:"";
3537 /* Create the progress bar if necessary.
3538 We check on every iteration of the loop, so that it takes no
3539 longer than the standard time to create it (otherwise, for a
3540 large file, we might take considerably longer than that standard
3541 time in order to get to the next progress bar step). */
3542 if (progbar == NULL)
3543 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3544 FALSE, &stop_flag, &start_time, progbar_val);
3546 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3547 when we update it, we have to run the GTK+ main loop to get it
3548 to repaint what's pending, and doing so may involve an "ioctl()"
3549 to see if there's any pending input from an X server, and doing
3550 that for every packet can be costly, especially on a big file. */
3551 if (count >= progbar_nextstep) {
3552 /* let's not divide by zero. I should never be started
3553 * with count == 0, so let's assert that
3555 g_assert(cf->count > 0);
3557 progbar_val = (gfloat) count / cf->count;
3559 if (progbar != NULL) {
3560 g_snprintf(status_str, sizeof(status_str),
3561 "%4u of %u packets", count, cf->count);
3562 update_progress_dlg(progbar, progbar_val, status_str);
3565 progbar_nextstep += progbar_quantum;
3569 /* Well, the user decided to abort the search. Go back to the
3570 frame where we started. */
3575 /* Go past the current frame. */
3576 if (dir == SD_BACKWARD) {
3577 /* Go on to the previous frame. */
3578 if (framenum == 1) {
3580 * XXX - other apps have a bit more of a detailed message
3581 * for this, and instead of offering "OK" and "Cancel",
3582 * they offer things such as "Continue" and "Cancel";
3583 * we need an API for popping up alert boxes with
3584 * {Verb} and "Cancel".
3587 if (prefs.gui_find_wrap)
3589 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3590 framenum = cf->count; /* wrap around */
3594 statusbar_push_temporary_msg("Search reached the beginning.");
3595 framenum = start_fd->num; /* stay on previous packet */
3600 /* Go on to the next frame. */
3601 if (framenum == cf->count) {
3602 if (prefs.gui_find_wrap)
3604 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3605 framenum = 1; /* wrap around */
3609 statusbar_push_temporary_msg("Search reached the end.");
3610 framenum = start_fd->num; /* stay on previous packet */
3615 fdata = frame_data_sequence_find(cf->frames, framenum);
3619 /* Is this packet in the display? */
3620 if (fdata->flags.passed_dfilter) {
3621 /* Yes. Does it match the search criterion? */
3622 result = (*match_function)(cf, fdata, criterion);
3623 if (result == MR_ERROR) {
3624 /* Error; our caller has reported the error. Go back to the frame
3625 where we started. */
3628 } else if (result == MR_MATCHED) {
3629 /* Yes. Go to the new frame. */
3635 if (fdata == start_fd) {
3636 /* We're back to the frame we were on originally, and that frame
3637 doesn't match the search filter. The search failed. */
3642 /* We're done scanning the packets; destroy the progress bar if it
3644 if (progbar != NULL)
3645 destroy_progress_dlg(progbar);
3648 if (new_fd != NULL) {
3649 /* Find and select */
3650 cf->search_in_progress = TRUE;
3651 found = packet_list_select_row_from_data(new_fd);
3652 cf->search_in_progress = FALSE;
3653 cf->search_pos = 0; /* Reset the position */
3655 /* We didn't find a row corresponding to this frame.
3656 This means that the frame isn't being displayed currently,
3657 so we can't select it. */
3658 simple_message_box(ESD_TYPE_INFO, NULL,
3659 "The capture file is probably not fully dissected.",
3660 "End of capture exceeded.");
3663 return TRUE; /* success */
3665 return FALSE; /* failure */
3669 cf_goto_frame(capture_file *cf, guint fnumber)
3673 fdata = frame_data_sequence_find(cf->frames, fnumber);
3675 if (fdata == NULL) {
3676 /* we didn't find a packet with that packet number */
3677 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3678 return FALSE; /* we failed to go to that packet */
3680 if (!fdata->flags.passed_dfilter) {
3681 /* that packet currently isn't displayed */
3682 /* XXX - add it to the set of displayed packets? */
3683 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3684 return FALSE; /* we failed to go to that packet */
3687 if (!packet_list_select_row_from_data(fdata)) {
3688 /* We didn't find a row corresponding to this frame.
3689 This means that the frame isn't being displayed currently,
3690 so we can't select it. */
3691 simple_message_box(ESD_TYPE_INFO, NULL,
3692 "The capture file is probably not fully dissected.",
3693 "End of capture exceeded.");
3696 return TRUE; /* we got to that packet */
3700 cf_goto_top_frame(void)
3702 /* Find and select */
3703 packet_list_select_first_row();
3704 return TRUE; /* we got to that packet */
3708 cf_goto_bottom_frame(void)
3710 /* Find and select */
3711 packet_list_select_last_row();
3712 return TRUE; /* we got to that packet */
3716 * Go to frame specified by currently selected protocol tree item.
3719 cf_goto_framenum(capture_file *cf)
3721 header_field_info *hfinfo;
3724 if (cf->finfo_selected) {
3725 hfinfo = cf->finfo_selected->hfinfo;
3727 if (hfinfo->type == FT_FRAMENUM) {
3728 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3730 return cf_goto_frame(cf, framenum);
3737 /* Select the packet on a given row. */
3739 cf_select_packet(capture_file *cf, int row)
3741 epan_dissect_t *old_edt;
3744 /* Get the frame data struct pointer for this frame */
3745 fdata = packet_list_get_row_data(row);
3747 if (fdata == NULL) {
3748 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3749 the first entry is added to it by "real_insert_row()", that row
3750 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3751 our version and the vanilla GTK+ version).
3753 This means that a "select-row" signal is emitted; this causes
3754 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3757 "cf_select_packet()" fetches, above, the data associated with the
3758 row that was selected; however, as "gtk_clist_append()", which
3759 called "real_insert_row()", hasn't yet returned, we haven't yet
3760 associated any data with that row, so we get back a null pointer.
3762 We can't assume that there's only one frame in the frame list,
3763 either, as we may be filtering the display.
3765 We therefore assume that, if "row" is 0, i.e. the first row
3766 is being selected, and "cf->first_displayed" equals
3767 "cf->last_displayed", i.e. there's only one frame being
3768 displayed, that frame is the frame we want.
3770 This means we have to set "cf->first_displayed" and
3771 "cf->last_displayed" before adding the row to the
3772 GtkCList; see the comment in "add_packet_to_packet_list()". */
3774 if (row == 0 && cf->first_displayed == cf->last_displayed)
3775 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3778 /* If fdata _still_ isn't set simply give up. */
3779 if (fdata == NULL) {
3783 /* Get the data in that frame. */
3784 if (!cf_read_record (cf, fdata)) {
3788 /* Record that this frame is the current frame. */
3789 cf->current_frame = fdata;
3790 cf->current_row = row;
3793 /* Create the logical protocol tree. */
3794 /* We don't need the columns here. */
3795 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3797 tap_build_interesting(cf->edt);
3798 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3799 cf->current_frame, NULL);
3801 dfilter_macro_build_ftv_cache(cf->edt->tree);
3803 cf_callback_invoke(cf_cb_packet_selected, cf);
3805 if (old_edt != NULL)
3806 epan_dissect_free(old_edt);
3810 /* Unselect the selected packet, if any. */
3812 cf_unselect_packet(capture_file *cf)
3814 epan_dissect_t *old_edt = cf->edt;
3818 /* No packet is selected. */
3819 cf->current_frame = NULL;
3820 cf->current_row = 0;
3822 cf_callback_invoke(cf_cb_packet_unselected, cf);
3824 /* No protocol tree means no selected field. */
3825 cf_unselect_field(cf);
3827 /* Destroy the epan_dissect_t for the unselected packet. */
3828 if (old_edt != NULL)
3829 epan_dissect_free(old_edt);
3832 /* Unset the selected protocol tree field, if any. */
3834 cf_unselect_field(capture_file *cf)
3836 cf->finfo_selected = NULL;
3838 cf_callback_invoke(cf_cb_field_unselected, cf);
3842 * Mark a particular frame.
3845 cf_mark_frame(capture_file *cf, frame_data *frame)
3847 if (! frame->flags.marked) {
3848 frame->flags.marked = TRUE;
3849 if (cf->count > cf->marked_count)
3855 * Unmark a particular frame.
3858 cf_unmark_frame(capture_file *cf, frame_data *frame)
3860 if (frame->flags.marked) {
3861 frame->flags.marked = FALSE;
3862 if (cf->marked_count > 0)
3868 * Ignore a particular frame.
3871 cf_ignore_frame(capture_file *cf, frame_data *frame)
3873 if (! frame->flags.ignored) {
3874 frame->flags.ignored = TRUE;
3875 if (cf->count > cf->ignored_count)
3876 cf->ignored_count++;
3881 * Un-ignore a particular frame.
3884 cf_unignore_frame(capture_file *cf, frame_data *frame)
3886 if (frame->flags.ignored) {
3887 frame->flags.ignored = FALSE;
3888 if (cf->ignored_count > 0)
3889 cf->ignored_count--;
3894 * Read the comment in SHB block
3898 cf_read_shb_comment(capture_file *cf)
3900 wtapng_section_t *shb_inf;
3901 const gchar *temp_str;
3903 /* Get info from SHB */
3904 shb_inf = wtap_file_get_shb_info(cf->wth);
3905 if (shb_inf == NULL)
3907 temp_str = shb_inf->opt_comment;
3915 cf_update_capture_comment(capture_file *cf, gchar *comment)
3917 wtapng_section_t *shb_inf;
3919 /* Get info from SHB */
3920 shb_inf = wtap_file_get_shb_info(cf->wth);
3922 /* See if the comment has changed or not */
3923 if (shb_inf && shb_inf->opt_comment) {
3924 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3933 /* The comment has changed, let's update it */
3934 wtap_write_shb_comment(cf->wth, comment);
3935 /* Mark the file as having unsaved changes */
3936 cf->unsaved_changes = TRUE;
3940 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3942 if (cf->frames_user_comments)
3943 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3950 cf_get_comment(capture_file *cf, const frame_data *fd)
3954 /* fetch user comment */
3955 if (fd->flags.has_user_comment)
3956 return g_strdup(cf_get_user_packet_comment(cf, fd));
3958 /* fetch phdr comment */
3959 if (fd->flags.has_phdr_comment) {
3960 struct wtap_pkthdr phdr; /* Packet header */
3961 Buffer buf; /* Packet data */
3963 wtap_phdr_init(&phdr);
3964 ws_buffer_init(&buf, 1500);
3966 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3967 { /* XXX, what we can do here? */ }
3969 comment = phdr.opt_comment;
3970 wtap_phdr_cleanup(&phdr);
3971 ws_buffer_free(&buf);
3978 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3980 const frame_data *fdata1 = (const frame_data *) a;
3981 const frame_data *fdata2 = (const frame_data *) b;
3983 return (fdata1->num < fdata2->num) ? -1 :
3984 (fdata1->num > fdata2->num) ? 1 :
3989 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3991 char *pkt_comment = cf_get_comment(cf, fd);
3993 /* Check if the comment has changed */
3994 if (!g_strcmp0(pkt_comment, new_comment)) {
3995 g_free(pkt_comment);
3998 g_free(pkt_comment);
4001 cf->packet_comment_count--;
4004 cf->packet_comment_count++;
4006 fd->flags.has_user_comment = TRUE;
4008 if (!cf->frames_user_comments)
4009 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
4011 /* insert new packet comment */
4012 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
4014 expert_update_comment_count(cf->packet_comment_count);
4016 /* OK, we have unsaved changes. */
4017 cf->unsaved_changes = TRUE;
4022 * What types of comments does this capture file have?
4025 cf_comment_types(capture_file *cf)
4027 guint32 comment_types = 0;
4029 if (cf_read_shb_comment(cf) != NULL)
4030 comment_types |= WTAP_COMMENT_PER_SECTION;
4031 if (cf->packet_comment_count != 0)
4032 comment_types |= WTAP_COMMENT_PER_PACKET;
4033 return comment_types;
4036 #ifdef WANT_PACKET_EDITOR
4038 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
4049 modified_frame_data_free(gpointer data)
4051 modified_frame_data *mfd = (modified_frame_data *)data;
4058 * Give a frame new, edited data.
4061 cf_set_frame_edited(capture_file *cf, frame_data *fd,
4062 struct wtap_pkthdr *phdr, guint8 *pd)
4064 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
4069 if (cf->edited_frames == NULL)
4070 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
4071 modified_frame_data_free);
4072 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
4075 /* Mark the file as having unsaved changes */
4076 cf->unsaved_changes = TRUE;
4084 } save_callback_args_t;
4087 * Save a capture to a file, in a particular format, saving either
4088 * all packets, all currently-displayed packets, or all marked packets.
4090 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4091 * up a message box for the failure.
4094 save_record(capture_file *cf, frame_data *fdata,
4095 struct wtap_pkthdr *phdr, const guint8 *pd,
4098 save_callback_args_t *args = (save_callback_args_t *)argsp;
4099 struct wtap_pkthdr hdr;
4101 gchar *display_basename;
4102 const char *pkt_comment;
4104 if (fdata->flags.has_user_comment)
4105 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4107 pkt_comment = phdr->opt_comment;
4109 /* init the wtap header for saving */
4110 /* TODO: reuse phdr */
4111 /* XXX - these are the only flags that correspond to data that we have
4112 in the frame_data structure and that matter on a per-packet basis.
4114 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4115 and "on the wire" lengths, or it doesn't.
4117 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4120 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4121 from the packet flags. */
4122 hdr.rec_type = phdr->rec_type;
4123 hdr.presence_flags = 0;
4124 if (fdata->flags.has_ts)
4125 hdr.presence_flags |= WTAP_HAS_TS;
4126 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4127 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4128 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4129 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4130 hdr.ts.secs = fdata->abs_ts.secs;
4131 hdr.ts.nsecs = fdata->abs_ts.nsecs;
4132 hdr.caplen = phdr->caplen;
4133 hdr.len = phdr->len;
4134 hdr.pkt_encap = fdata->lnk_t;
4136 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4138 hdr.pack_flags = phdr->pack_flags;
4139 hdr.opt_comment = g_strdup(pkt_comment);
4142 hdr.pseudo_header = phdr->pseudo_header;
4145 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4147 /* and save the packet */
4148 if (!wtap_dump(args->pdh, &hdr, pd, &err)) {
4150 /* Wiretap error. */
4153 case WTAP_ERR_UNWRITABLE_ENCAP:
4155 * This is a problem with the particular frame we're writing and
4156 * the file type and subtype we're writing; note that, and report
4157 * the frame number and file type/subtype.
4159 simple_error_message_box(
4160 "Frame %u has a network type that can't be saved in a \"%s\" file.",
4161 fdata->num, wtap_file_type_subtype_string(args->file_type));
4164 case WTAP_ERR_PACKET_TOO_LARGE:
4166 * This is a problem with the particular frame we're writing and
4167 * the file type and subtype we're writing; note that, and report
4168 * the frame number and file type/subtype.
4170 simple_error_message_box(
4171 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
4172 fdata->num, wtap_file_type_subtype_string(args->file_type));
4176 display_basename = g_filename_display_basename(args->fname);
4177 simple_error_message_box(
4178 "An error occurred while writing to the file \"%s\": %s.",
4179 display_basename, wtap_strerror(err));
4180 g_free(display_basename);
4185 write_failure_alert_box(args->fname, err);
4190 g_free(hdr.opt_comment);
4195 * Can this capture file be written out in any format using Wiretap
4196 * rather than by copying the raw data?
4199 cf_can_write_with_wiretap(capture_file *cf)
4201 /* We don't care whether we support the comments in this file or not;
4202 if we can't, we'll offer the user the option of discarding the
4204 return wtap_dump_can_write(cf->linktypes, 0);
4208 * Should we let the user do a save?
4212 * the file has unsaved changes, and we can save it in some
4213 * format through Wiretap
4217 * the file is a temporary file and has no unsaved changes (so
4218 * that "saving" it just means copying it).
4220 * XXX - we shouldn't allow files to be edited if they can't be saved,
4221 * so cf->unsaved_changes should be true only if the file can be saved.
4223 * We don't care whether we support the comments in this file or not;
4224 * if we can't, we'll offer the user the option of discarding the
4228 cf_can_save(capture_file *cf)
4230 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4231 /* Saved changes, and we can write it out with Wiretap. */
4235 if (cf->is_tempfile && !cf->unsaved_changes) {
4237 * Temporary file with no unsaved changes, so we can just do a
4243 /* Nothing to save. */
4248 * Should we let the user do a "save as"?
4252 * we can save it in some format through Wiretap
4256 * the file is a temporary file and has no unsaved changes (so
4257 * that "saving" it just means copying it).
4259 * XXX - we shouldn't allow files to be edited if they can't be saved,
4260 * so cf->unsaved_changes should be true only if the file can be saved.
4262 * We don't care whether we support the comments in this file or not;
4263 * if we can't, we'll offer the user the option of discarding the
4267 cf_can_save_as(capture_file *cf)
4269 if (wtap_dump_can_write(cf->linktypes, 0)) {
4270 /* We can write it out with Wiretap. */
4274 if (cf->is_tempfile && !cf->unsaved_changes) {
4276 * Temporary file with no unsaved changes, so we can just do a
4282 /* Nothing to save. */
4287 * Does this file have unsaved data?
4290 cf_has_unsaved_data(capture_file *cf)
4293 * If this is a temporary file, or a file with unsaved changes, it
4296 return cf->is_tempfile || cf->unsaved_changes;
4300 * Quick scan to find packet offsets.
4302 static cf_read_status_t
4303 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4305 const struct wtap_pkthdr *phdr;
4310 progdlg_t *progbar = NULL;
4314 GTimeVal start_time;
4315 gchar status_str[100];
4316 gint64 progbar_nextstep;
4317 gint64 progbar_quantum;
4322 int displayed_once = 0;
4325 /* Close the old handle. */
4326 wtap_close(cf->wth);
4328 /* Open the new file. */
4329 /* XXX: this will go through all open_routines for a matching one. But right
4330 now rescan_file() is only used when a file is being saved to a different
4331 format than the original, and the user is not given a choice of which
4332 reader to use (only which format to save it in), so doing this makes
4334 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4335 if (cf->wth == NULL) {
4336 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4337 return CF_READ_ERROR;
4340 /* We're scanning a file whose contents should be the same as what
4341 we had before, so we don't discard dissection state etc.. */
4344 /* Set the file name because we need it to set the follow stream filter.
4345 XXX - is that still true? We need it for other reasons, though,
4347 cf->filename = g_strdup(fname);
4349 /* Indicate whether it's a permanent or temporary file. */
4350 cf->is_tempfile = is_tempfile;
4352 /* No user changes yet. */
4353 cf->unsaved_changes = FALSE;
4355 cf->cd_t = wtap_file_type_subtype(cf->wth);
4356 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4358 cf->snap = wtap_snapshot_length(cf->wth);
4359 if (cf->snap == 0) {
4360 /* Snapshot length not known. */
4361 cf->has_snap = FALSE;
4362 cf->snap = WTAP_MAX_PACKET_SIZE;
4364 cf->has_snap = TRUE;
4366 name_ptr = g_filename_display_basename(cf->filename);
4368 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4370 /* Record whether the file is compressed.
4371 XXX - do we know this at open time? */
4372 cf->iscompressed = wtap_iscompressed(cf->wth);
4374 /* Find the size of the file. */
4375 size = wtap_file_size(cf->wth, NULL);
4377 /* Update the progress bar when it gets to this value. */
4378 progbar_nextstep = 0;
4379 /* When we reach the value that triggers a progress bar update,
4380 bump that value by this amount. */
4382 progbar_quantum = size/N_PROGBAR_UPDATES;
4383 if (progbar_quantum < MIN_QUANTUM)
4384 progbar_quantum = MIN_QUANTUM;
4386 progbar_quantum = 0;
4389 g_get_current_time(&start_time);
4392 phdr = wtap_phdr(cf->wth);
4393 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4395 fdata = frame_data_sequence_find(cf->frames, framenum);
4396 fdata->file_off = data_offset;
4399 file_pos = wtap_read_so_far(cf->wth);
4401 /* Create the progress bar if necessary.
4402 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4404 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4405 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4406 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4407 TRUE, &stop_flag, &start_time, progbar_val);
4410 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4411 when we update it, we have to run the GTK+ main loop to get it
4412 to repaint what's pending, and doing so may involve an "ioctl()"
4413 to see if there's any pending input from an X server, and doing
4414 that for every packet can be costly, especially on a big file. */
4415 if (file_pos >= progbar_nextstep) {
4416 if (progbar != NULL) {
4417 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4418 /* update the packet bar content on the first run or frequently on very large files */
4420 if (progbar_quantum > 500000 || displayed_once == 0) {
4421 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4423 packets_bar_update();
4426 #endif /* HAVE_LIBPCAP */
4427 update_progress_dlg(progbar, progbar_val, status_str);
4429 progbar_nextstep += progbar_quantum;
4434 /* Well, the user decided to abort the rescan. Sadly, as this
4435 isn't a reread, recovering is difficult, so we'll just
4436 close the current capture. */
4440 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4441 it's not already there.
4442 XXX - yes, this is O(N), so if every packet had a different
4443 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4444 there are probably going to be a small number of encapsulation types
4446 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4449 /* Free the display name */
4452 /* We're done reading the file; destroy the progress bar if it was created. */
4453 if (progbar != NULL)
4454 destroy_progress_dlg(progbar);
4456 /* We're done reading sequentially through the file. */
4457 cf->state = FILE_READ_DONE;
4459 /* Close the sequential I/O side, to free up memory it requires. */
4460 wtap_sequential_close(cf->wth);
4462 /* compute the time it took to load the file */
4463 compute_elapsed(cf, &start_time);
4465 /* Set the file encapsulation type now; we don't know what it is until
4466 we've looked at all the packets, as we don't know until then whether
4467 there's more than one type (and thus whether it's
4468 WTAP_ENCAP_PER_PACKET). */
4469 cf->lnk_t = wtap_file_encap(cf->wth);
4471 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4474 /* Our caller will give up at this point. */
4475 return CF_READ_ABORTED;
4479 /* Put up a message box noting that the read failed somewhere along
4480 the line. Don't throw out the stuff we managed to read, though,
4484 case WTAP_ERR_UNSUPPORTED:
4485 simple_error_message_box(
4486 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4491 case WTAP_ERR_UNWRITABLE_ENCAP:
4492 simple_error_message_box(
4493 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
4498 case WTAP_ERR_SHORT_READ:
4499 simple_error_message_box(
4500 "The capture file appears to have been cut short"
4501 " in the middle of a packet.");
4504 case WTAP_ERR_BAD_FILE:
4505 simple_error_message_box(
4506 "The capture file appears to be damaged or corrupt.\n(%s)",
4511 case WTAP_ERR_DECOMPRESS:
4512 simple_error_message_box(
4513 "The compressed capture file appears to be damaged or corrupt.\n"
4519 simple_error_message_box(
4520 "An error occurred while reading the"
4521 " capture file: %s.", wtap_strerror(*err));
4524 return CF_READ_ERROR;
4530 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4531 gboolean compressed, gboolean discard_comments,
4532 gboolean dont_reopen)
4535 gchar *fname_new = NULL;
4538 addrinfo_lists_t *addr_lists;
4542 gchar *display_basename;
4549 save_callback_args_t callback_args;
4551 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4553 addr_lists = get_addrinfo_list();
4555 if (save_format == cf->cd_t && compressed == cf->iscompressed
4556 && !discard_comments && !cf->unsaved_changes
4557 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4558 /* We're saving in the format it's already in, and we're
4559 not discarding comments, and there are no changes we have
4560 in memory that aren't saved to the file, and we have no name
4561 resolution blocks to write, so we can just move or copy the raw data. */
4563 if (cf->is_tempfile) {
4564 /* The file being saved is a temporary file from a live
4565 capture, so it doesn't need to stay around under that name;
4566 first, try renaming the capture buffer file to the new name.
4567 This acts as a "safe save", in that, if the file already
4568 exists, the existing file will be removed only if the rename
4571 Sadly, on Windows, as we have the current capture file
4572 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4573 (to cause the rename to remove an existing target), as
4574 done by ws_stdio_rename() (ws_rename() is #defined to
4575 be ws_stdio_rename() on Windows) will fail.
4577 According to the MSDN documentation for CreateFile(), if,
4578 when we open a capture file, we were to directly do a CreateFile(),
4579 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4580 convert it to a file descriptor with _open_osfhandle(),
4581 that would allow the file to be renamed out from under us.
4583 However, that doesn't work in practice. Perhaps the problem
4584 is that the process doing the rename is the process that
4585 has the file open. */
4587 if (ws_rename(cf->filename, fname) == 0) {
4588 /* That succeeded - there's no need to copy the source file. */
4589 how_to_save = SAVE_WITH_MOVE;
4591 if (errno == EXDEV) {
4592 /* They're on different file systems, so we have to copy the
4594 how_to_save = SAVE_WITH_COPY;
4596 /* The rename failed, but not because they're on different
4597 file systems - put up an error message. (Or should we
4598 just punt and try to copy? The only reason why I'd
4599 expect the rename to fail and the copy to succeed would
4600 be if we didn't have permission to remove the file from
4601 the temporary directory, and that might be fixable - but
4602 is it worth requiring the user to go off and fix it?) */
4603 cf_rename_failure_alert_box(fname, errno);
4608 how_to_save = SAVE_WITH_COPY;
4611 /* It's a permanent file, so we should copy it, and not remove the
4613 how_to_save = SAVE_WITH_COPY;
4616 if (how_to_save == SAVE_WITH_COPY) {
4617 /* Copy the file, if we haven't moved it. If we're overwriting
4618 an existing file, we do it with a "safe save", by writing
4619 to a new file and, if the write succeeds, renaming the
4620 new file on top of the old file. */
4621 if (file_exists(fname)) {
4622 fname_new = g_strdup_printf("%s~", fname);
4623 if (!copy_file_binary_mode(cf->filename, fname_new))
4626 if (!copy_file_binary_mode(cf->filename, fname))
4631 /* Either we're saving in a different format or we're saving changes,
4632 such as added, modified, or removed comments, that haven't yet
4633 been written to the underlying file; we can't do that by copying
4634 or moving the capture file, we have to do it by writing the packets
4637 wtapng_section_t *shb_hdr = NULL;
4638 wtapng_iface_descriptions_t *idb_inf = NULL;
4641 shb_hdr = wtap_file_get_shb_info(cf->wth);
4642 idb_inf = wtap_file_get_idb_info(cf->wth);
4644 /* Determine what file encapsulation type we should use. */
4645 encap = wtap_dump_file_encap_type(cf->linktypes);
4647 if (file_exists(fname)) {
4648 /* We're overwriting an existing file; write out to a new file,
4649 and, if that succeeds, rename the new file on top of the
4650 old file. That makes this a "safe save", so that we don't
4651 lose the old file if we have a problem writing out the new
4652 file. (If the existing file is the current capture file,
4653 we *HAVE* to do that, otherwise we're overwriting the file
4654 from which we're reading the packets that we're writing!) */
4655 fname_new = g_strdup_printf("%s~", fname);
4656 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4657 compressed, shb_hdr, idb_inf, &err);
4659 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4660 compressed, shb_hdr, idb_inf, &err);
4666 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4670 /* Add address resolution */
4671 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4673 /* Iterate through the list of packets, processing all the packets. */
4674 callback_args.pdh = pdh;
4675 callback_args.fname = fname;
4676 callback_args.file_type = save_format;
4677 switch (process_specified_records(cf, NULL, "Saving", "packets",
4678 TRUE, save_record, &callback_args)) {
4681 /* Completed successfully. */
4685 /* The user decided to abort the saving.
4686 If we're writing to a temporary file, remove it.
4687 XXX - should we do so even if we're not writing to a
4689 wtap_dump_close(pdh, &err);
4690 if (fname_new != NULL)
4691 ws_unlink(fname_new);
4692 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4693 return CF_WRITE_ABORTED;
4696 /* Error while saving.
4697 If we're writing to a temporary file, remove it. */
4698 if (fname_new != NULL)
4699 ws_unlink(fname_new);
4700 wtap_dump_close(pdh, &err);
4704 if (!wtap_dump_close(pdh, &err)) {
4705 cf_close_failure_alert_box(fname, err);
4709 how_to_save = SAVE_WITH_WTAP;
4712 if (fname_new != NULL) {
4713 /* We wrote out to fname_new, and should rename it on top of
4714 fname. fname_new is now closed, so that should be possible even
4715 on Windows. However, on Windows, we first need to close whatever
4716 file descriptors we have open for fname. */
4718 wtap_fdclose(cf->wth);
4720 /* Now do the rename. */
4721 if (ws_rename(fname_new, fname) == -1) {
4722 /* Well, the rename failed. */
4723 cf_rename_failure_alert_box(fname, errno);
4725 /* Attempt to reopen the random file descriptor using the
4726 current file's filename. (At this point, the sequential
4727 file descriptor is closed.) */
4728 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4729 /* Oh, well, we're screwed. */
4730 display_basename = g_filename_display_basename(cf->filename);
4731 simple_error_message_box(
4732 file_open_error_message(err, FALSE), display_basename);
4733 g_free(display_basename);
4740 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4741 cf->unsaved_changes = FALSE;
4744 switch (how_to_save) {
4746 case SAVE_WITH_MOVE:
4747 /* We just moved the file, so the wtap structure refers to the
4748 new file, and all the information other than the filename
4749 and the "is temporary" status applies to the new file; just
4751 g_free(cf->filename);
4752 cf->filename = g_strdup(fname);
4753 cf->is_tempfile = FALSE;
4754 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4757 case SAVE_WITH_COPY:
4758 /* We just copied the file, s all the information other than
4759 the wtap structure, the filename, and the "is temporary"
4760 status applies to the new file; just update that. */
4761 wtap_close(cf->wth);
4762 /* Although we're just "copying" and then opening the copy, it will
4763 try all open_routine readers to open the copy, so we need to
4764 reset the cfile's open_type. */
4765 cf->open_type = WTAP_TYPE_AUTO;
4766 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4767 if (cf->wth == NULL) {
4768 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4771 g_free(cf->filename);
4772 cf->filename = g_strdup(fname);
4773 cf->is_tempfile = FALSE;
4775 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4778 case SAVE_WITH_WTAP:
4779 /* Open and read the file we saved to.
4781 XXX - this is somewhat of a waste; we already have the
4782 packets, all this gets us is updated file type information
4783 (which we could just stuff into "cf"), and having the new
4784 file be the one we have opened and from which we're reading
4785 the data, and it means we have to spend time opening and
4786 reading the file, which could be a significant amount of
4787 time if the file is large.
4789 If the capture-file-writing code were to return the
4790 seek offset of each packet it writes, we could save that
4791 in the frame_data structure for the frame, and just open
4792 the file without reading it again...
4794 ...as long as, for gzipped files, the process of writing
4795 out the file *also* generates the information needed to
4796 support fast random access to the compressed file. */
4797 /* rescan_file will cause us to try all open_routines, so
4798 reset cfile's open_type */
4799 cf->open_type = WTAP_TYPE_AUTO;
4800 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4801 /* The rescan failed; just close the file. Either
4802 a dialog was popped up for the failure, so the
4803 user knows what happened, or they stopped the
4804 rescan, in which case they know what happened. */
4810 /* If we were told to discard the comments, do so. */
4811 if (discard_comments) {
4812 /* Remove SHB comment, if any. */
4813 wtap_write_shb_comment(cf->wth, NULL);
4815 /* remove all user comments */
4816 for (framenum = 1; framenum <= cf->count; framenum++) {
4817 fdata = frame_data_sequence_find(cf->frames, framenum);
4819 fdata->flags.has_phdr_comment = FALSE;
4820 fdata->flags.has_user_comment = FALSE;
4823 if (cf->frames_user_comments) {
4824 g_tree_destroy(cf->frames_user_comments);
4825 cf->frames_user_comments = NULL;
4828 cf->packet_comment_count = 0;
4834 if (fname_new != NULL) {
4835 /* We were trying to write to a temporary file; get rid of it if it
4836 exists. (We don't care whether this fails, as, if it fails,
4837 there's not much we can do about it. I guess if it failed for
4838 a reason other than "it doesn't exist", we could report an
4839 error, so the user knows there's a junk file that they might
4840 want to clean up.) */
4841 ws_unlink(fname_new);
4844 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4845 return CF_WRITE_ERROR;
4849 cf_export_specified_packets(capture_file *cf, const char *fname,
4850 packet_range_t *range, guint save_format,
4851 gboolean compressed)
4853 gchar *fname_new = NULL;
4856 save_callback_args_t callback_args;
4857 wtapng_section_t *shb_hdr;
4858 wtapng_iface_descriptions_t *idb_inf;
4861 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4863 packet_range_process_init(range);
4865 /* We're writing out specified packets from the specified capture
4866 file to another file. Even if all captured packets are to be
4867 written, don't special-case the operation - read each packet
4868 and then write it out if it's one of the specified ones. */
4870 shb_hdr = wtap_file_get_shb_info(cf->wth);
4871 idb_inf = wtap_file_get_idb_info(cf->wth);
4873 /* Determine what file encapsulation type we should use. */
4874 encap = wtap_dump_file_encap_type(cf->linktypes);
4876 if (file_exists(fname)) {
4877 /* We're overwriting an existing file; write out to a new file,
4878 and, if that succeeds, rename the new file on top of the
4879 old file. That makes this a "safe save", so that we don't
4880 lose the old file if we have a problem writing out the new
4881 file. (If the existing file is the current capture file,
4882 we *HAVE* to do that, otherwise we're overwriting the file
4883 from which we're reading the packets that we're writing!) */
4884 fname_new = g_strdup_printf("%s~", fname);
4885 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4886 compressed, shb_hdr, idb_inf, &err);
4888 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4889 compressed, shb_hdr, idb_inf, &err);
4895 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4899 /* Add address resolution */
4900 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4902 /* Iterate through the list of packets, processing the packets we were
4905 XXX - we've already called "packet_range_process_init(range)", but
4906 "process_specified_records()" will do it again. Fortunately,
4907 that's harmless in this case, as we haven't done anything to
4908 "range" since we initialized it. */
4909 callback_args.pdh = pdh;
4910 callback_args.fname = fname;
4911 callback_args.file_type = save_format;
4912 switch (process_specified_records(cf, range, "Writing", "specified records",
4913 TRUE, save_record, &callback_args)) {
4916 /* Completed successfully. */
4920 /* The user decided to abort the saving.
4921 If we're writing to a temporary file, remove it.
4922 XXX - should we do so even if we're not writing to a
4924 wtap_dump_close(pdh, &err);
4925 if (fname_new != NULL)
4926 ws_unlink(fname_new);
4927 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4928 return CF_WRITE_ABORTED;
4932 /* Error while saving.
4933 If we're writing to a temporary file, remove it. */
4934 if (fname_new != NULL)
4935 ws_unlink(fname_new);
4936 wtap_dump_close(pdh, &err);
4940 if (!wtap_dump_close(pdh, &err)) {
4941 cf_close_failure_alert_box(fname, err);
4945 if (fname_new != NULL) {
4946 /* We wrote out to fname_new, and should rename it on top of
4947 fname; fname is now closed, so that should be possible even
4948 on Windows. Do the rename. */
4949 if (ws_rename(fname_new, fname) == -1) {
4950 /* Well, the rename failed. */
4951 cf_rename_failure_alert_box(fname, errno);
4956 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4960 if (fname_new != NULL) {
4961 /* We were trying to write to a temporary file; get rid of it if it
4962 exists. (We don't care whether this fails, as, if it fails,
4963 there's not much we can do about it. I guess if it failed for
4964 a reason other than "it doesn't exist", we could report an
4965 error, so the user knows there's a junk file that they might
4966 want to clean up.) */
4967 ws_unlink(fname_new);
4970 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4971 return CF_WRITE_ERROR;
4975 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4976 gboolean for_writing, int file_type)
4978 gchar *display_basename;
4981 /* Wiretap error. */
4982 display_basename = g_filename_display_basename(filename);
4985 case WTAP_ERR_NOT_REGULAR_FILE:
4986 simple_error_message_box(
4987 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4991 case WTAP_ERR_RANDOM_OPEN_PIPE:
4992 /* Seen only when opening a capture file for reading. */
4993 simple_error_message_box(
4994 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4995 "To capture from a pipe or FIFO use wireshark -i -",
4999 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
5000 /* Seen only when opening a capture file for reading. */
5001 simple_error_message_box(
5002 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
5006 case WTAP_ERR_UNSUPPORTED:
5007 /* Seen only when opening a capture file for reading. */
5008 simple_error_message_box(
5009 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
5011 display_basename, err_info);
5015 case WTAP_ERR_CANT_WRITE_TO_PIPE:
5016 /* Seen only when opening a capture file for writing. */
5017 simple_error_message_box(
5018 "The file \"%s\" is a pipe, and %s capture files can't be "
5019 "written to a pipe.",
5020 display_basename, wtap_file_type_subtype_string(file_type));
5023 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
5024 /* Seen only when opening a capture file for writing. */
5025 simple_error_message_box(
5026 "Wireshark doesn't support writing capture files in that format.");
5029 case WTAP_ERR_UNWRITABLE_ENCAP:
5031 simple_error_message_box("Wireshark can't save this capture in that format.");
5033 simple_error_message_box(
5034 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
5036 display_basename, err_info);
5041 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
5043 simple_error_message_box(
5044 "Wireshark can't save this capture in that format.");
5046 simple_error_message_box(
5047 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
5052 case WTAP_ERR_BAD_FILE:
5053 /* Seen only when opening a capture file for reading. */
5054 simple_error_message_box(
5055 "The file \"%s\" appears to be damaged or corrupt.\n"
5057 display_basename, err_info);
5061 case WTAP_ERR_CANT_OPEN:
5063 simple_error_message_box(
5064 "The file \"%s\" could not be created for some unknown reason.",
5067 simple_error_message_box(
5068 "The file \"%s\" could not be opened for some unknown reason.",
5073 case WTAP_ERR_SHORT_READ:
5074 simple_error_message_box(
5075 "The file \"%s\" appears to have been cut short"
5076 " in the middle of a packet or other data.",
5080 case WTAP_ERR_SHORT_WRITE:
5081 simple_error_message_box(
5082 "A full header couldn't be written to the file \"%s\".",
5086 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
5087 simple_error_message_box(
5088 "This file type cannot be written as a compressed file.");
5091 case WTAP_ERR_DECOMPRESS:
5092 simple_error_message_box(
5093 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
5094 "(%s)", display_basename, err_info);
5099 simple_error_message_box(
5100 "The file \"%s\" could not be %s: %s.",
5102 for_writing ? "created" : "opened",
5103 wtap_strerror(err));
5106 g_free(display_basename);
5109 open_failure_alert_box(filename, err, for_writing);
5114 * XXX - whether we mention the source pathname, the target pathname,
5115 * or both depends on the error and on what we find if we look for
5116 * one or both of them.
5119 cf_rename_failure_alert_box(const char *filename, int err)
5121 gchar *display_basename;
5123 display_basename = g_filename_display_basename(filename);
5127 /* XXX - should check whether the source exists and, if not,
5128 report it as the problem and, if so, report the destination
5130 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
5135 /* XXX - if we're doing a rename after a safe save, we should
5136 probably say something else. */
5137 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
5142 /* XXX - this should probably mention both the source and destination
5144 simple_error_message_box("The file \"%s\" could not be moved: %s.",
5145 display_basename, wtap_strerror(err));
5148 g_free(display_basename);
5151 /* Check for write errors - if the file is being written to an NFS server,
5152 a write error may not show up until the file is closed, as NFS clients
5153 might not send writes to the server until the "write()" call finishes,
5154 so that the write may fail on the server but the "write()" may succeed. */
5156 cf_close_failure_alert_box(const char *filename, int err)
5158 gchar *display_basename;
5161 /* Wiretap error. */
5162 display_basename = g_filename_display_basename(filename);
5165 case WTAP_ERR_CANT_CLOSE:
5166 simple_error_message_box(
5167 "The file \"%s\" couldn't be closed for some unknown reason.",
5171 case WTAP_ERR_SHORT_WRITE:
5172 simple_error_message_box(
5173 "Not all the packets could be written to the file \"%s\".",
5178 simple_error_message_box(
5179 "An error occurred while closing the file \"%s\": %s.",
5180 display_basename, wtap_strerror(err));
5183 g_free(display_basename);
5186 We assume that a close error from the OS is really a write error. */
5187 write_failure_alert_box(filename, err);
5191 /* Reload the current capture file. */
5193 cf_reload(capture_file *cf) {
5195 gboolean is_tempfile;
5198 /* If the file could be opened, "cf_open()" calls "cf_close()"
5199 to get rid of state for the old capture file before filling in state
5200 for the new capture file. "cf_close()" will remove the file if
5201 it's a temporary file; we don't want that to happen (for one thing,
5202 it'd prevent subsequent reopens from working). Remember whether it's
5203 a temporary file, mark it as not being a temporary file, and then
5204 reopen it as the type of file it was.
5206 Also, "cf_close()" will free "cf->filename", so we must make
5207 a copy of it first. */
5208 filename = g_strdup(cf->filename);
5209 is_tempfile = cf->is_tempfile;
5210 cf->is_tempfile = FALSE;
5211 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5212 switch (cf_read(cf, TRUE)) {
5216 /* Just because we got an error, that doesn't mean we were unable
5217 to read any of the file; we handle what we could get from the
5221 case CF_READ_ABORTED:
5222 /* The user bailed out of re-reading the capture file; the
5223 capture file has been closed - just free the capture file name
5224 string and return (without changing the last containing
5230 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5231 Instead, the file was left open, so we should restore "cf->is_tempfile"
5234 XXX - change the menu? Presumably "cf_open()" will do that;
5235 make sure it does! */
5236 cf->is_tempfile = is_tempfile;
5238 /* "cf_open()" made a copy of the file name we handed it, so
5239 we should free up our copy. */
5249 * indent-tabs-mode: nil
5252 * ex: set shiftwidth=2 tabstop=8 expandtab:
5253 * :indentSize=2:tabSize=8:noTabs=true: