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>
46 #include <wiretap/merge.h>
48 #include <epan/exceptions.h>
49 #include <epan/epan-int.h>
50 #include <epan/epan.h>
51 #include <epan/column.h>
52 #include <epan/packet.h>
53 #include <epan/column-utils.h>
54 #include <epan/expert.h>
55 #include <epan/prefs.h>
56 #include <epan/dfilter/dfilter.h>
57 #include <epan/epan_dissect.h>
59 #include <epan/dissectors/packet-data.h>
60 #include <epan/dissectors/packet-ber.h>
61 #include <epan/timestamp.h>
62 #include <epan/dfilter/dfilter-macro.h>
63 #include <epan/strutil.h>
64 #include <epan/addr_resolv.h>
67 #include "color_filters.h"
71 #include "frame_tvbuff.h"
73 #include "ui/alert_box.h"
74 #include "ui/simple_dialog.h"
75 #include "ui/main_statusbar.h"
76 #include "ui/progress_dlg.h"
77 #include "ui/ui_util.h"
79 #include "version_info.h"
81 /* Needed for addrinfo */
82 #ifdef HAVE_SYS_TYPES_H
83 # include <sys/types.h>
86 #ifdef HAVE_SYS_SOCKET_H
87 #include <sys/socket.h>
90 #ifdef HAVE_NETINET_IN_H
91 # include <netinet/in.h>
98 #ifdef HAVE_WINSOCK2_H
99 # include <winsock2.h>
102 #if defined(_WIN32) && defined(INET6)
103 # include <ws2tcpip.h>
107 gboolean auto_scroll_live;
110 static void cf_reset_state(capture_file *cf);
112 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
113 column_info *cinfo, gint64 offset);
115 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
122 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
124 static void match_subtree_text(proto_node *node, gpointer data);
125 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
127 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
129 static match_result match_narrow(capture_file *cf, frame_data *fdata,
131 static match_result match_wide(capture_file *cf, frame_data *fdata,
133 static match_result match_binary(capture_file *cf, frame_data *fdata,
135 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
137 static match_result match_marked(capture_file *cf, frame_data *fdata,
139 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
141 static gboolean find_packet(capture_file *cf,
142 match_result (*match_function)(capture_file *, frame_data *, void *),
143 void *criterion, search_direction dir);
145 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
147 static void cf_open_failure_alert_box(const char *filename, int err,
148 gchar *err_info, gboolean for_writing,
150 static void cf_rename_failure_alert_box(const char *filename, int err);
151 static void cf_close_failure_alert_box(const char *filename, int err);
152 static void ref_time_packets(capture_file *cf);
153 /* Update the progress bar this many times when reading a file. */
154 #define N_PROGBAR_UPDATES 100
155 /* We read around 200k/100ms don't update the progress bar more often than that */
156 #define MIN_QUANTUM 200000
157 #define MIN_NUMBER_OF_PACKET 1500
160 * We could probably use g_signal_...() instead of the callbacks below but that
161 * would require linking our CLI programs to libgobject and creating an object
162 * instance for the signals.
165 cf_callback_t cb_fct;
167 } cf_callback_data_t;
169 static GList *cf_callbacks = NULL;
172 cf_callback_invoke(int event, gpointer data)
174 cf_callback_data_t *cb;
175 GList *cb_item = cf_callbacks;
177 /* there should be at least one interested */
178 g_assert(cb_item != NULL);
180 while (cb_item != NULL) {
181 cb = (cf_callback_data_t *)cb_item->data;
182 cb->cb_fct(event, data, cb->user_data);
183 cb_item = g_list_next(cb_item);
189 cf_callback_add(cf_callback_t func, gpointer user_data)
191 cf_callback_data_t *cb;
193 cb = g_new(cf_callback_data_t,1);
195 cb->user_data = user_data;
197 cf_callbacks = g_list_prepend(cf_callbacks, cb);
201 cf_callback_remove(cf_callback_t func)
203 cf_callback_data_t *cb;
204 GList *cb_item = cf_callbacks;
206 while (cb_item != NULL) {
207 cb = (cf_callback_data_t *)cb_item->data;
208 if (cb->cb_fct == func) {
209 cf_callbacks = g_list_remove(cf_callbacks, cb);
213 cb_item = g_list_next(cb_item);
216 g_assert_not_reached();
220 cf_timestamp_auto_precision(capture_file *cf)
223 int prec = timestamp_get_precision();
226 /* don't try to get the file's precision if none is opened */
227 if (cf->state == FILE_CLOSED) {
231 /* if we are in auto mode, set precision of current file */
232 if (prec == TS_PREC_AUTO ||
233 prec == TS_PREC_AUTO_SEC ||
234 prec == TS_PREC_AUTO_DSEC ||
235 prec == TS_PREC_AUTO_CSEC ||
236 prec == TS_PREC_AUTO_MSEC ||
237 prec == TS_PREC_AUTO_USEC ||
238 prec == TS_PREC_AUTO_NSEC)
240 switch(wtap_file_tsprecision(cf->wth)) {
241 case(WTAP_FILE_TSPREC_SEC):
242 timestamp_set_precision(TS_PREC_AUTO_SEC);
244 case(WTAP_FILE_TSPREC_DSEC):
245 timestamp_set_precision(TS_PREC_AUTO_DSEC);
247 case(WTAP_FILE_TSPREC_CSEC):
248 timestamp_set_precision(TS_PREC_AUTO_CSEC);
250 case(WTAP_FILE_TSPREC_MSEC):
251 timestamp_set_precision(TS_PREC_AUTO_MSEC);
253 case(WTAP_FILE_TSPREC_USEC):
254 timestamp_set_precision(TS_PREC_AUTO_USEC);
256 case(WTAP_FILE_TSPREC_NSEC):
257 timestamp_set_precision(TS_PREC_AUTO_NSEC);
260 g_assert_not_reached();
263 /* Set the column widths of those columns that show the time in
264 "command-line-specified" format. */
265 for (i = 0; i < cf->cinfo.num_cols; i++) {
266 if (col_has_time_fmt(&cf->cinfo, i)) {
267 packet_list_resize_column(i);
273 cf_get_computed_elapsed(capture_file *cf)
275 return cf->computed_elapsed;
279 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
282 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
287 g_get_current_time(&time_now);
289 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
290 time_now.tv_usec - start_time->tv_usec;
292 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
295 static const nstime_t *
296 ws_get_frame_ts(void *data, guint32 frame_num)
298 capture_file *cf = (capture_file *) data;
300 if (cf->prev_dis && cf->prev_dis->num == frame_num)
301 return &cf->prev_dis->abs_ts;
303 if (cf->prev_cap && cf->prev_cap->num == frame_num)
304 return &cf->prev_cap->abs_ts;
307 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
309 return (fd) ? &fd->abs_ts : NULL;
316 ws_get_user_comment(void *data, const frame_data *fd)
318 capture_file *cf = (capture_file *) data;
320 return cf_get_user_packet_comment(cf, fd);
324 ws_epan_new(capture_file *cf)
326 epan_t *epan = epan_new();
329 epan->get_frame_ts = ws_get_frame_ts;
330 epan->get_interface_name = cap_file_get_interface_name;
331 epan->get_user_comment = ws_get_user_comment;
337 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
342 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
346 /* The open succeeded. Close whatever capture file we had open,
347 and fill in the information for this file. */
350 /* XXX - we really want to initialize this after we've read all
351 the packets, so we know how much we'll ultimately need. */
352 buffer_init(&cf->buf, 1500);
354 /* Create new epan session for dissection.
355 * (The old one was freed in cf_close().)
357 cf->epan = ws_epan_new(cf);
359 /* We're about to start reading the file. */
360 cf->state = FILE_READ_IN_PROGRESS;
365 /* Set the file name because we need it to set the follow stream filter.
366 XXX - is that still true? We need it for other reasons, though,
368 cf->filename = g_strdup(fname);
370 /* Indicate whether it's a permanent or temporary file. */
371 cf->is_tempfile = is_tempfile;
373 /* No user changes yet. */
374 cf->unsaved_changes = FALSE;
376 cf->computed_elapsed = 0;
378 cf->cd_t = wtap_file_type_subtype(cf->wth);
379 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
381 cf->packet_comment_count = 0;
382 cf->displayed_count = 0;
383 cf->marked_count = 0;
384 cf->ignored_count = 0;
385 cf->ref_time_count = 0;
386 cf->drops_known = FALSE;
388 cf->snap = wtap_snapshot_length(cf->wth);
390 /* Snapshot length not known. */
391 cf->has_snap = FALSE;
392 cf->snap = WTAP_MAX_PACKET_SIZE;
396 /* Allocate a frame_data_sequence for the frames in this file */
397 cf->frames = new_frame_data_sequence();
399 nstime_set_zero(&cf->elapsed_time);
405 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
406 cf_timestamp_auto_precision(cf);
408 packet_list_queue_draw();
409 cf_callback_invoke(cf_cb_file_opened, cf);
411 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
412 /* tell the BER dissector the file name */
413 ber_set_filename(cf->filename);
416 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
417 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
422 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
427 * Add an encapsulation type to cf->linktypes.
430 cf_add_encapsulation_type(capture_file *cf, int encap)
434 for (i = 0; i < cf->linktypes->len; i++) {
435 if (g_array_index(cf->linktypes, gint, i) == encap)
436 return; /* it's already there */
438 /* It's not already there - add it. */
439 g_array_append_val(cf->linktypes, encap);
443 * Reset the state for the currently closed file, but don't do the
444 * UI callbacks; this is for use in "cf_open()", where we don't
445 * want the UI to go from "file open" to "file closed" back to
446 * "file open", we want it to go from "old file open" to "new file
447 * open and being read".
449 * XXX - currently, cf_open() calls cf_close(), rather than
453 cf_reset_state(capture_file *cf)
455 /* Die if we're in the middle of reading a file. */
456 g_assert(cf->state != FILE_READ_IN_PROGRESS);
462 /* We have no file open... */
463 if (cf->filename != NULL) {
464 /* If it's a temporary file, remove it. */
466 ws_unlink(cf->filename);
467 g_free(cf->filename);
470 /* ...which means we have no changes to that file to save. */
471 cf->unsaved_changes = FALSE;
473 /* Free up the packet buffer. */
474 buffer_free(&cf->buf);
476 dfilter_free(cf->rfcode);
478 if (cf->frames != NULL) {
479 free_frame_data_sequence(cf->frames);
482 #ifdef WANT_PACKET_EDITOR
483 if (cf->edited_frames) {
484 g_tree_destroy(cf->edited_frames);
485 cf->edited_frames = NULL;
488 if (cf->frames_user_comments) {
489 g_tree_destroy(cf->frames_user_comments);
490 cf->frames_user_comments = NULL;
492 cf_unselect_packet(cf); /* nothing to select */
493 cf->first_displayed = 0;
494 cf->last_displayed = 0;
496 /* No frames, no frame selected, no field in that frame selected. */
498 cf->current_frame = 0;
500 cf->finfo_selected = NULL;
502 /* No frame link-layer types, either. */
503 g_array_free(cf->linktypes, TRUE);
504 cf->linktypes = NULL;
506 /* Clear the packet list. */
507 packet_list_freeze();
512 nstime_set_zero(&cf->elapsed_time);
514 reset_tap_listeners();
516 /* We have no file open. */
517 cf->state = FILE_CLOSED;
520 /* Reset everything to a pristine state */
522 cf_close(capture_file *cf)
524 if (cf->state != FILE_CLOSED) {
525 cf_callback_invoke(cf_cb_file_closing, cf);
527 /* close things, if not already closed before */
528 color_filters_cleanup();
533 cf_callback_invoke(cf_cb_file_closed, cf);
538 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
542 progbar_val = (gfloat) file_pos / (gfloat) size;
543 if (progbar_val > 1.0) {
545 /* The file probably grew while we were reading it.
546 * Update file size, and try again.
548 size = wtap_file_size(cf->wth, NULL);
551 progbar_val = (gfloat) file_pos / (gfloat) size;
553 /* If it's still > 1, either "wtap_file_size()" failed (in which
554 * case there's not much we can do about it), or the file
555 * *shrank* (in which case there's not much we can do about
556 * it); just clip the progress value at 1.0.
558 if (progbar_val > 1.0f)
562 g_snprintf(status_str, status_size,
563 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
564 file_pos / 1024, size / 1024);
570 cf_read(capture_file *cf, gboolean reloading)
575 progdlg_t *progbar = NULL;
580 volatile gboolean create_proto_tree;
584 /* Compile the current display filter.
585 * We assume this will not fail since cf->dfilter is only set in
586 * cf_filter IFF the filter was valid.
588 compiled = dfilter_compile(cf->dfilter, &dfcode);
589 g_assert(!cf->dfilter || (compiled && dfcode));
591 /* Get the union of the flags for all tap listeners. */
592 tap_flags = union_of_tap_listener_flags();
594 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
596 reset_tap_listeners();
598 name_ptr = g_filename_display_basename(cf->filename);
601 cf_callback_invoke(cf_cb_file_reload_started, cf);
603 cf_callback_invoke(cf_cb_file_read_started, cf);
605 /* Record whether the file is compressed.
606 XXX - do we know this at open time? */
607 cf->iscompressed = wtap_iscompressed(cf->wth);
609 /* The packet list window will be empty until the file is completly loaded */
610 packet_list_freeze();
613 g_get_current_time(&start_time);
615 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
619 int displayed_once = 0;
627 gint64 progbar_quantum;
628 gint64 progbar_nextstep;
630 gchar status_str[100];
634 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
636 /* Find the size of the file. */
637 size = wtap_file_size(cf->wth, NULL);
639 /* Update the progress bar when it gets to this value. */
640 progbar_nextstep = 0;
641 /* When we reach the value that triggers a progress bar update,
642 bump that value by this amount. */
644 progbar_quantum = size/N_PROGBAR_UPDATES;
645 if (progbar_quantum < MIN_QUANTUM)
646 progbar_quantum = MIN_QUANTUM;
650 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
653 file_pos = wtap_read_so_far(cf->wth);
655 /* Create the progress bar if necessary.
656 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
658 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
659 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
661 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
662 TRUE, &stop_flag, &start_time, progbar_val);
664 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
665 TRUE, &stop_flag, &start_time, progbar_val);
668 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
669 when we update it, we have to run the GTK+ main loop to get it
670 to repaint what's pending, and doing so may involve an "ioctl()"
671 to see if there's any pending input from an X server, and doing
672 that for every packet can be costly, especially on a big file. */
673 if (file_pos >= progbar_nextstep) {
674 if (progbar != NULL) {
675 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
676 /* update the packet bar content on the first run or frequently on very large files */
678 if (progbar_quantum > 500000 || displayed_once == 0) {
679 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
681 packets_bar_update();
684 #endif /* HAVE_LIBPCAP */
685 update_progress_dlg(progbar, progbar_val, status_str);
687 progbar_nextstep += progbar_quantum;
692 /* Well, the user decided to abort the read. He/She will be warned and
693 it might be enough for him/her to work with the already loaded
695 This is especially true for very large capture files, where you don't
696 want to wait loading the whole file (which may last minutes or even
697 hours even on fast machines) just to see that it was the wrong file. */
700 read_packet(cf, dfcode, &edt, cinfo, data_offset);
703 CATCH(OutOfMemoryError) {
704 simple_message_box(ESD_TYPE_ERROR, NULL,
705 "Some infos / workarounds can be found at:\n"
706 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
707 "Sorry, but Wireshark has run out of memory and has to terminate now!");
709 /* Could we close the current capture and free up memory from that? */
711 /* we have to terminate, as we cannot recover from the memory error */
717 /* Free the display name */
720 /* Cleanup and release all dfilter resources */
721 if (dfcode != NULL) {
722 dfilter_free(dfcode);
725 epan_dissect_cleanup(&edt);
727 /* We're done reading the file; destroy the progress bar if it was created. */
729 destroy_progress_dlg(progbar);
731 /* We're done reading sequentially through the file. */
732 cf->state = FILE_READ_DONE;
734 /* Close the sequential I/O side, to free up memory it requires. */
735 wtap_sequential_close(cf->wth);
737 /* Allow the protocol dissectors to free up memory that they
738 * don't need after the sequential run-through of the packets. */
739 postseq_cleanup_all_protocols();
741 /* compute the time it took to load the file */
742 compute_elapsed(cf, &start_time);
744 /* Set the file encapsulation type now; we don't know what it is until
745 we've looked at all the packets, as we don't know until then whether
746 there's more than one type (and thus whether it's
747 WTAP_ENCAP_PER_PACKET). */
748 cf->lnk_t = wtap_file_encap(cf->wth);
750 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
755 cf_callback_invoke(cf_cb_file_reload_finished, cf);
757 cf_callback_invoke(cf_cb_file_read_finished, cf);
759 /* If we have any displayed packets to select, select the first of those
760 packets by making the first row the selected row. */
761 if (cf->first_displayed != 0) {
762 packet_list_select_first_row();
766 simple_message_box(ESD_TYPE_WARN, NULL,
767 "The remaining packets in the file were discarded.\n"
769 "As a lot of packets from the original file will be missing,\n"
770 "remember to be careful when saving the current content to a file.\n",
771 "File loading was cancelled!");
772 return CF_READ_ERROR;
776 /* Put up a message box noting that the read failed somewhere along
777 the line. Don't throw out the stuff we managed to read, though,
781 case WTAP_ERR_UNSUPPORTED:
782 simple_error_message_box(
783 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
788 case WTAP_ERR_UNSUPPORTED_ENCAP:
789 simple_error_message_box(
790 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
795 case WTAP_ERR_CANT_READ:
796 simple_error_message_box(
797 "An attempt to read from the capture file failed for"
798 " some unknown reason.");
801 case WTAP_ERR_SHORT_READ:
802 simple_error_message_box(
803 "The capture file appears to have been cut short"
804 " in the middle of a packet.");
807 case WTAP_ERR_BAD_FILE:
808 simple_error_message_box(
809 "The capture file appears to be damaged or corrupt.\n(%s)",
814 case WTAP_ERR_DECOMPRESS:
815 simple_error_message_box(
816 "The compressed capture file appears to be damaged or corrupt.\n"
822 simple_error_message_box(
823 "An error occurred while reading the"
824 " capture file: %s.", wtap_strerror(err));
827 return CF_READ_ERROR;
834 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
837 int newly_displayed_packets = 0;
840 gboolean create_proto_tree;
844 /* Compile the current display filter.
845 * We assume this will not fail since cf->dfilter is only set in
846 * cf_filter IFF the filter was valid.
848 compiled = dfilter_compile(cf->dfilter, &dfcode);
849 g_assert(!cf->dfilter || (compiled && dfcode));
851 /* Get the union of the flags for all tap listeners. */
852 tap_flags = union_of_tap_listener_flags();
854 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
858 packet_list_check_end();
859 /* Don't freeze/thaw the list when doing live capture */
860 /*packet_list_freeze();*/
862 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
864 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
867 gint64 data_offset = 0;
870 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
872 while (to_read != 0) {
873 wtap_cleareof(cf->wth);
874 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
877 if (cf->state == FILE_READ_ABORTED) {
878 /* Well, the user decided to exit Wireshark. Break out of the
879 loop, and let the code below (which is called even if there
880 aren't any packets left to read) exit. */
883 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
884 newly_displayed_packets++;
889 CATCH(OutOfMemoryError) {
890 simple_message_box(ESD_TYPE_ERROR, NULL,
891 "Some infos / workarounds can be found at:\n"
892 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
893 "Sorry, but Wireshark has run out of memory and has to terminate now!");
895 /* Could we close the current capture and free up memory from that? */
896 return CF_READ_ABORTED;
898 /* we have to terminate, as we cannot recover from the memory error */
904 /* Update the file encapsulation; it might have changed based on the
905 packets we've read. */
906 cf->lnk_t = wtap_file_encap(cf->wth);
908 /* Cleanup and release all dfilter resources */
909 if (dfcode != NULL) {
910 dfilter_free(dfcode);
913 epan_dissect_cleanup(&edt);
915 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
916 cf->count, cf->state, *err);*/
918 /* Don't freeze/thaw the list when doing live capture */
919 /*packet_list_thaw();*/
920 /* With the new packet list the first packet
921 * isn't automatically selected.
923 if (!cf->current_frame)
924 packet_list_select_first_row();
926 /* moving to the end of the packet list - if the user requested so and
927 we have some new packets. */
928 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
929 packet_list_moveto_end();
931 if (cf->state == FILE_READ_ABORTED) {
932 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
933 so that our caller can kill off the capture child process;
934 this will cause an EOF on the pipe from the child, so
935 "cf_finish_tail()" will be called, and it will clean up
937 return CF_READ_ABORTED;
938 } else if (*err != 0) {
939 /* We got an error reading the capture file.
940 XXX - pop up a dialog box instead? */
941 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
942 wtap_strerror(*err), err_info, cf->filename);
945 return CF_READ_ERROR;
951 cf_fake_continue_tail(capture_file *cf) {
952 cf->state = FILE_READ_DONE;
956 cf_finish_tail(capture_file *cf, int *err)
963 gboolean create_proto_tree;
967 /* Compile the current display filter.
968 * We assume this will not fail since cf->dfilter is only set in
969 * cf_filter IFF the filter was valid.
971 compiled = dfilter_compile(cf->dfilter, &dfcode);
972 g_assert(!cf->dfilter || (compiled && dfcode));
974 /* Get the union of the flags for all tap listeners. */
975 tap_flags = union_of_tap_listener_flags();
976 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
978 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
980 if (cf->wth == NULL) {
982 return CF_READ_ERROR;
985 packet_list_check_end();
986 /* Don't freeze/thaw the list when doing live capture */
987 /*packet_list_freeze();*/
989 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
991 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
992 if (cf->state == FILE_READ_ABORTED) {
993 /* Well, the user decided to abort the read. Break out of the
994 loop, and let the code below (which is called even if there
995 aren't any packets left to read) exit. */
998 read_packet(cf, dfcode, &edt, cinfo, data_offset);
1001 /* Cleanup and release all dfilter resources */
1002 if (dfcode != NULL) {
1003 dfilter_free(dfcode);
1006 epan_dissect_cleanup(&edt);
1008 /* Don't freeze/thaw the list when doing live capture */
1009 /*packet_list_thaw();*/
1011 if (cf->state == FILE_READ_ABORTED) {
1012 /* Well, the user decided to abort the read. We're only called
1013 when the child capture process closes the pipe to us (meaning
1014 it's probably exited), so we can just close the capture
1015 file; we return CF_READ_ABORTED so our caller can do whatever
1016 is appropriate when that happens. */
1018 return CF_READ_ABORTED;
1021 if (auto_scroll_live && cf->count != 0)
1022 packet_list_moveto_end();
1024 /* We're done reading sequentially through the file. */
1025 cf->state = FILE_READ_DONE;
1027 /* We're done reading sequentially through the file; close the
1028 sequential I/O side, to free up memory it requires. */
1029 wtap_sequential_close(cf->wth);
1031 /* Allow the protocol dissectors to free up memory that they
1032 * don't need after the sequential run-through of the packets. */
1033 postseq_cleanup_all_protocols();
1035 /* Update the file encapsulation; it might have changed based on the
1036 packets we've read. */
1037 cf->lnk_t = wtap_file_encap(cf->wth);
1039 /* Update the details in the file-set dialog, as the capture file
1040 * has likely grown since we first stat-ed it */
1041 fileset_update_file(cf->filename);
1044 /* We got an error reading the capture file.
1045 XXX - pop up a dialog box? */
1047 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
1048 wtap_strerror(*err), err_info, cf->filename);
1050 return CF_READ_ERROR;
1055 #endif /* HAVE_LIBPCAP */
1058 cf_get_display_name(capture_file *cf)
1062 /* Return a name to use in displays */
1063 if (!cf->is_tempfile) {
1064 /* Get the last component of the file name, and use that. */
1066 displayname = g_filename_display_basename(cf->filename);
1068 displayname=g_strdup("(No file)");
1071 /* The file we read is a temporary file from a live capture or
1072 a merge operation; we don't mention its name, but, if it's
1073 from a capture, give the source of the capture. */
1075 displayname = g_strdup(cf->source);
1077 displayname = g_strdup("(Untitled)");
1083 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1089 cf->source = g_strdup(source);
1091 cf->source = g_strdup("");
1095 const gchar *cf_get_tempfile_source(capture_file *cf) {
1103 /* XXX - use a macro instead? */
1105 cf_get_packet_count(capture_file *cf)
1110 /* XXX - use a macro instead? */
1112 cf_set_packet_count(capture_file *cf, int packet_count)
1114 cf->count = packet_count;
1117 /* XXX - use a macro instead? */
1119 cf_is_tempfile(capture_file *cf)
1121 return cf->is_tempfile;
1124 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1126 cf->is_tempfile = is_tempfile;
1130 /* XXX - use a macro instead? */
1131 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1133 cf->drops_known = drops_known;
1136 /* XXX - use a macro instead? */
1137 void cf_set_drops(capture_file *cf, guint32 drops)
1142 /* XXX - use a macro instead? */
1143 gboolean cf_get_drops_known(capture_file *cf)
1145 return cf->drops_known;
1148 /* XXX - use a macro instead? */
1149 guint32 cf_get_drops(capture_file *cf)
1154 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1156 cf->rfcode = rfcode;
1160 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1161 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1162 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1166 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1167 &cf->ref, cf->prev_dis);
1168 cf->prev_cap = fdata;
1170 if (dfcode != NULL) {
1171 epan_dissect_prime_dfilter(edt, dfcode);
1174 /* Dissect the frame. */
1175 epan_dissect_run_with_taps(edt, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1177 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1178 if (dfcode != NULL) {
1179 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1181 if (fdata->flags.passed_dfilter) {
1182 /* This frame passed the display filter but it may depend on other
1183 * (potentially not displayed) frames. Find those frames and mark them
1186 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1189 fdata->flags.passed_dfilter = 1;
1191 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1192 cf->displayed_count++;
1194 if (add_to_packet_list) {
1195 /* We fill the needed columns from new_packet_list */
1196 row = packet_list_append(cinfo, fdata);
1199 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1201 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1202 cf->prev_dis = fdata;
1204 /* If we haven't yet seen the first frame, this is it.
1206 XXX - we must do this before we add the row to the display,
1207 as, if the display's GtkCList's selection mode is
1208 GTK_SELECTION_BROWSE, when the first entry is added to it,
1209 "cf_select_packet()" will be called, and it will fetch the row
1210 data for the 0th row, and will get a null pointer rather than
1211 "fdata", as "gtk_clist_append()" won't yet have returned and
1212 thus "gtk_clist_set_row_data()" won't yet have been called.
1214 We thus need to leave behind bread crumbs so that
1215 "cf_select_packet()" can find this frame. See the comment
1216 in "cf_select_packet()". */
1217 if (cf->first_displayed == 0)
1218 cf->first_displayed = fdata->num;
1220 /* This is the last frame we've seen so far. */
1221 cf->last_displayed = fdata->num;
1224 epan_dissect_reset(edt);
1228 /* read in a new packet */
1229 /* returns the row of the new packet in the packet list or -1 if not displayed */
1231 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1232 column_info *cinfo, gint64 offset)
1234 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1235 const guint8 *buf = wtap_buf_ptr(cf->wth);
1242 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1243 it's not already there.
1244 XXX - yes, this is O(N), so if every packet had a different
1245 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1246 there are probably going to be a small number of encapsulation types
1248 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1250 /* The frame number of this packet is one more than the count of
1251 frames in the file so far. */
1252 framenum = cf->count + 1;
1254 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1258 epan_dissect_t rf_edt;
1260 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1261 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1262 epan_dissect_run(&rf_edt, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1263 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1264 epan_dissect_cleanup(&rf_edt);
1268 /* This does a shallow copy of fdlocal, which is good enough. */
1269 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1272 if (phdr->opt_comment != NULL)
1273 cf->packet_comment_count++;
1274 cf->f_datalen = offset + fdlocal.cap_len;
1276 if (!cf->redissecting) {
1277 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1278 cinfo, phdr, buf, TRUE);
1286 cf_merge_files(char **out_filenamep, int in_file_count,
1287 char *const *in_filenames, int file_type, gboolean do_append)
1289 merge_in_file_t *in_files, *in_file;
1294 int open_err, read_err, write_err, close_err;
1298 gboolean got_read_error = FALSE, got_write_error = FALSE;
1300 progdlg_t *progbar = NULL;
1302 gint64 f_len, file_pos;
1304 GTimeVal start_time;
1305 gchar status_str[100];
1306 gint64 progbar_nextstep;
1307 gint64 progbar_quantum;
1308 gchar *display_basename;
1309 int selected_frame_type;
1310 gboolean fake_interface_ids = FALSE;
1312 /* open the input files */
1313 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1314 &open_err, &err_info, &err_fileno)) {
1316 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1321 if (*out_filenamep != NULL) {
1322 out_filename = *out_filenamep;
1323 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1327 out_fd = create_tempfile(&tmpname, "wireshark");
1330 out_filename = g_strdup(tmpname);
1331 *out_filenamep = out_filename;
1335 merge_close_in_files(in_file_count, in_files);
1337 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1341 selected_frame_type = merge_select_frame_type(in_file_count, in_files);
1343 /* If we are trying to merge a number of libpcap files with different encapsulation types
1344 * change the output file type to pcapng and create SHB and IDB:s for the new file use the
1345 * interface index stored in in_files per file to change the phdr before writing the datablock.
1346 * XXX should it be an option to convert to pcapng?
1348 * We need something similar when merging pcapng files possibly with an option to say
1349 * the same interface(s) used in all in files. SHBs comments should be merged together.
1351 if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP)) {
1352 /* Write output in pcapng format */
1353 wtapng_section_t *shb_hdr;
1354 wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
1355 wtapng_if_descr_t int_data, *file_int_data;
1356 GString *comment_gstr;
1358 fake_interface_ids = TRUE;
1359 /* Create SHB info */
1360 shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
1361 comment_gstr = g_string_new("");
1362 g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
1363 g_string_append_printf(comment_gstr, "File created by merging: \n");
1364 file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1366 for (i = 0; i < in_file_count; i++) {
1367 g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
1369 shb_hdr->section_length = -1;
1371 shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
1372 shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */
1373 /* description of the hardware used to create this section. */
1374 shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */
1375 /* of the operating system used to create this section. */
1376 shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name */
1377 /* of the application used to create this section. */
1379 /* create fake IDB info */
1380 idb_inf = g_new(wtapng_iface_descriptions_t,1);
1381 idb_inf->number_of_interfaces = in_file_count; /* TODO make this the number of DIFFERENT encapsulation types
1382 * check that snaplength is the same too?
1384 idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1386 for (i = 0; i < in_file_count; i++) {
1387 idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
1388 /* read the interface data from the in file to our combined interfca data */
1389 file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
1390 int_data.wtap_encap = file_int_data->wtap_encap;
1391 int_data.time_units_per_second = file_int_data->time_units_per_second;
1392 int_data.link_type = file_int_data->link_type;
1393 int_data.snap_len = file_int_data->snap_len;
1394 int_data.if_name = g_strdup(file_int_data->if_name);
1395 int_data.opt_comment = NULL;
1396 int_data.if_description = NULL;
1397 int_data.if_speed = 0;
1398 int_data.if_tsresol = 6;
1399 int_data.if_filter_str = NULL;
1400 int_data.bpf_filter_len = 0;
1401 int_data.if_filter_bpf_bytes = NULL;
1402 int_data.if_os = NULL;
1403 int_data.if_fcslen = -1;
1404 int_data.num_stat_entries = 0; /* Number of ISB:s */
1405 int_data.interface_statistics = NULL;
1407 g_array_append_val(idb_inf->interface_data, int_data);
1408 g_free(idb_inf_merge_file);
1410 /* Set fake interface Id in per file data */
1411 in_files[i].interface_id = i;
1414 pdh = wtap_dump_fdopen_ng(out_fd, file_type,
1415 selected_frame_type,
1416 merge_max_snapshot_length(in_file_count, in_files),
1417 FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
1421 merge_close_in_files(in_file_count, in_files);
1423 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1430 pdh = wtap_dump_fdopen(out_fd, file_type,
1431 selected_frame_type,
1432 merge_max_snapshot_length(in_file_count, in_files),
1433 FALSE /* compressed */, &open_err);
1436 merge_close_in_files(in_file_count, in_files);
1438 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1444 /* Get the sum of the sizes of all the files. */
1446 for (i = 0; i < in_file_count; i++)
1447 f_len += in_files[i].size;
1449 /* Update the progress bar when it gets to this value. */
1450 progbar_nextstep = 0;
1451 /* When we reach the value that triggers a progress bar update,
1452 bump that value by this amount. */
1453 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1454 /* Progress so far. */
1458 g_get_current_time(&start_time);
1460 /* do the merge (or append) */
1463 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1466 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1468 if (in_file == NULL) {
1473 if (read_err != 0) {
1474 /* I/O error reading from in_file */
1475 got_read_error = TRUE;
1479 /* Get the sum of the data offsets in all of the files. */
1481 for (i = 0; i < in_file_count; i++)
1482 data_offset += in_files[i].data_offset;
1484 /* Create the progress bar if necessary.
1485 We check on every iteration of the loop, so that it takes no
1486 longer than the standard time to create it (otherwise, for a
1487 large file, we might take considerably longer than that standard
1488 time in order to get to the next progress bar step). */
1489 if (progbar == NULL) {
1490 progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1491 FALSE, &stop_flag, &start_time, progbar_val);
1494 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1495 when we update it, we have to run the GTK+ main loop to get it
1496 to repaint what's pending, and doing so may involve an "ioctl()"
1497 to see if there's any pending input from an X server, and doing
1498 that for every packet can be costly, especially on a big file. */
1499 if (data_offset >= progbar_nextstep) {
1500 /* Get the sum of the seek positions in all of the files. */
1502 for (i = 0; i < in_file_count; i++)
1503 file_pos += wtap_read_so_far(in_files[i].wth);
1504 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1505 if (progbar_val > 1.0f) {
1506 /* Some file probably grew while we were reading it.
1507 That "shouldn't happen", so we'll just clip the progress
1511 if (progbar != NULL) {
1512 g_snprintf(status_str, sizeof(status_str),
1513 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1514 file_pos / 1024, f_len / 1024);
1515 update_progress_dlg(progbar, progbar_val, status_str);
1517 progbar_nextstep += progbar_quantum;
1521 /* Well, the user decided to abort the merge. */
1525 /* If we have WTAP_ENCAP_PER_PACKET and the infiles are of type
1526 * WTAP_FILE_TYPE_SUBTYPE_PCAP, we need to set the interface id
1527 * in the paket header = the interface index we used in the IDBs
1528 * interface description for this file(encapsulation type).
1530 if (fake_interface_ids) {
1531 struct wtap_pkthdr *phdr;
1533 phdr = wtap_phdr(in_file->wth);
1534 phdr->interface_id = in_file->interface_id;
1535 phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
1537 if (!wtap_dump(pdh, wtap_phdr(in_file->wth),
1538 wtap_buf_ptr(in_file->wth), &write_err)) {
1539 got_write_error = TRUE;
1544 /* We're done merging the files; destroy the progress bar if it was created. */
1545 if (progbar != NULL)
1546 destroy_progress_dlg(progbar);
1548 merge_close_in_files(in_file_count, in_files);
1549 if (!got_write_error) {
1550 if (!wtap_dump_close(pdh, &write_err))
1551 got_write_error = TRUE;
1554 * We already got a write error; no need to report another
1555 * write error on close.
1557 * Don't overwrite the earlier write error.
1559 (void)wtap_dump_close(pdh, &close_err);
1562 if (got_read_error) {
1564 * Find the file on which we got the error, and report the error.
1566 for (i = 0; i < in_file_count; i++) {
1567 if (in_files[i].state == GOT_ERROR) {
1568 /* Put up a message box noting that a read failed somewhere along
1570 display_basename = g_filename_display_basename(in_files[i].filename);
1573 case WTAP_ERR_UNSUPPORTED_ENCAP:
1574 simple_error_message_box(
1575 "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1576 display_basename, err_info);
1580 case WTAP_ERR_CANT_READ:
1581 simple_error_message_box(
1582 "An attempt to read from the capture file %s failed for"
1583 " some unknown reason.", display_basename);
1586 case WTAP_ERR_SHORT_READ:
1587 simple_error_message_box(
1588 "The capture file %s appears to have been cut short"
1589 " in the middle of a packet.", display_basename);
1592 case WTAP_ERR_BAD_FILE:
1593 simple_error_message_box(
1594 "The capture file %s appears to be damaged or corrupt.\n(%s)",
1595 display_basename, err_info);
1599 case WTAP_ERR_DECOMPRESS:
1600 simple_error_message_box(
1601 "The compressed capture file %s appears to be damaged or corrupt.\n"
1602 "(%s)", display_basename, err_info);
1607 simple_error_message_box(
1608 "An error occurred while reading the"
1609 " capture file %s: %s.",
1610 display_basename, wtap_strerror(read_err));
1613 g_free(display_basename);
1618 if (got_write_error) {
1619 /* Put up an alert box for the write error. */
1620 if (write_err < 0) {
1621 /* Wiretap error. */
1622 switch (write_err) {
1624 case WTAP_ERR_UNSUPPORTED_ENCAP:
1626 * This is a problem with the particular frame we're writing and
1627 * the file type and subtype we're writing; note that, and report
1628 * the frame number and file type/subtype.
1630 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1631 simple_error_message_box(
1632 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1633 in_file ? in_file->packet_num : 0, display_basename,
1634 wtap_file_type_subtype_string(file_type));
1635 g_free(display_basename);
1638 case WTAP_ERR_PACKET_TOO_LARGE:
1640 * This is a problem with the particular frame we're writing and
1641 * the file type and subtype we're writing; note that, and report
1642 * the frame number and file type/subtype.
1644 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1645 simple_error_message_box(
1646 "Frame %u of \"%s\" is too large for a \"%s\" file.",
1647 in_file ? in_file->packet_num : 0, display_basename,
1648 wtap_file_type_subtype_string(file_type));
1649 g_free(display_basename);
1653 display_basename = g_filename_display_basename(out_filename);
1654 simple_error_message_box(
1655 "An error occurred while writing to the file \"%s\": %s.",
1656 out_filename, wtap_strerror(write_err));
1657 g_free(display_basename);
1662 write_failure_alert_box(out_filename, write_err);
1666 if (got_read_error || got_write_error || stop_flag) {
1667 /* Callers aren't expected to treat an error or an explicit abort
1668 differently - we put up error dialogs ourselves, so they don't
1676 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1678 const char *filter_new = dftext ? dftext : "";
1679 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1681 GTimeVal start_time;
1683 /* if new filter equals old one, do nothing unless told to do so */
1684 if (!force && strcmp(filter_new, filter_old) == 0) {
1690 if (dftext == NULL) {
1691 /* The new filter is an empty filter (i.e., display all packets).
1692 * so leave dfcode==NULL
1696 * We have a filter; make a copy of it (as we'll be saving it),
1697 * and try to compile it.
1699 dftext = g_strdup(dftext);
1700 if (!dfilter_compile(dftext, &dfcode)) {
1701 /* The attempt failed; report an error. */
1702 simple_message_box(ESD_TYPE_ERROR, NULL,
1703 "See the help for a description of the display filter syntax.",
1704 "\"%s\" isn't a valid display filter: %s",
1705 dftext, dfilter_error_msg);
1711 if (dfcode == NULL) {
1712 /* Yes - free the filter text, and set it to null. */
1718 /* We have a valid filter. Replace the current filter. */
1719 g_free(cf->dfilter);
1720 cf->dfilter = dftext;
1721 g_get_current_time(&start_time);
1724 /* Now rescan the packet list, applying the new filter, but not
1725 throwing away information constructed on a previous pass. */
1726 if (dftext == NULL) {
1727 rescan_packets(cf, "Resetting", "Filter", FALSE);
1729 rescan_packets(cf, "Filtering", dftext, FALSE);
1732 /* Cleanup and release all dfilter resources */
1733 dfilter_free(dfcode);
1739 cf_reftime_packets(capture_file *cf)
1741 ref_time_packets(cf);
1745 cf_redissect_packets(capture_file *cf)
1747 if (cf->state != FILE_CLOSED) {
1748 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1753 cf_read_frame_r(capture_file *cf, const frame_data *fdata,
1754 struct wtap_pkthdr *phdr, Buffer *buf)
1758 gchar *display_basename;
1760 #ifdef WANT_PACKET_EDITOR
1761 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1762 if (G_UNLIKELY(fdata->file_off == -1)) {
1763 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1766 simple_error_message_box("fdata->file_off == -1, but can't find modified frame!");
1770 *phdr = frame->phdr;
1771 buffer_assure_space(buf, frame->phdr.caplen);
1772 memcpy(buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1777 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1778 display_basename = g_filename_display_basename(cf->filename);
1781 case WTAP_ERR_UNSUPPORTED_ENCAP:
1782 simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1783 display_basename, err_info);
1787 case WTAP_ERR_BAD_FILE:
1788 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1789 display_basename, wtap_strerror(err), err_info);
1794 simple_error_message_box(
1795 "An error occurred while reading from the file \"%s\": %s.",
1796 display_basename, wtap_strerror(err));
1799 g_free(display_basename);
1806 cf_read_frame(capture_file *cf, frame_data *fdata)
1808 return cf_read_frame_r(cf, fdata, &cf->phdr, &cf->buf);
1811 /* Rescan the list of packets, reconstructing the CList.
1813 "action" describes why we're doing this; it's used in the progress
1816 "action_item" describes what we're doing; it's used in the progress
1819 "redissect" is TRUE if we need to make the dissectors reconstruct
1820 any state information they have (because a preference that affects
1821 some dissector has changed, meaning some dissector might construct
1822 its state differently from the way it was constructed the last time). */
1824 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1826 /* Rescan packets new packet list */
1829 progdlg_t *progbar = NULL;
1832 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1833 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1834 gboolean selected_frame_seen;
1836 GTimeVal start_time;
1837 gchar status_str[100];
1838 int progbar_nextstep;
1839 int progbar_quantum;
1843 gboolean create_proto_tree;
1845 gboolean add_to_packet_list = FALSE;
1847 guint32 frames_count;
1849 /* Compile the current display filter.
1850 * We assume this will not fail since cf->dfilter is only set in
1851 * cf_filter IFF the filter was valid.
1853 compiled = dfilter_compile(cf->dfilter, &dfcode);
1854 g_assert(!cf->dfilter || (compiled && dfcode));
1856 /* Get the union of the flags for all tap listeners. */
1857 tap_flags = union_of_tap_listener_flags();
1858 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1860 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1862 reset_tap_listeners();
1863 /* Which frame, if any, is the currently selected frame?
1864 XXX - should the selected frame or the focus frame be the "current"
1865 frame, that frame being the one from which "Find Frame" searches
1867 selected_frame = cf->current_frame;
1869 /* Mark frame num as not found */
1870 selected_frame_num = -1;
1872 /* Freeze the packet list while we redo it, so we don't get any
1873 screen updates while it happens. */
1874 packet_list_freeze();
1877 /* We need to re-initialize all the state information that protocols
1878 keep, because some preference that controls a dissector has changed,
1879 which might cause the state information to be constructed differently
1880 by that dissector. */
1882 /* We might receive new packets while redissecting, and we don't
1883 want to dissect those before their time. */
1884 cf->redissecting = TRUE;
1886 /* 'reset' dissection session */
1887 epan_free(cf->epan);
1888 cf->epan = ws_epan_new(cf);
1890 /* We need to redissect the packets so we have to discard our old
1891 * packet list store. */
1892 packet_list_clear();
1893 add_to_packet_list = TRUE;
1896 /* We don't yet know which will be the first and last frames displayed. */
1897 cf->first_displayed = 0;
1898 cf->last_displayed = 0;
1900 /* We currently don't display any packets */
1901 cf->displayed_count = 0;
1903 /* Iterate through the list of frames. Call a routine for each frame
1904 to check whether it should be displayed and, if so, add it to
1905 the display list. */
1907 cf->prev_dis = NULL;
1908 cf->prev_cap = NULL;
1911 /* Update the progress bar when it gets to this value. */
1912 progbar_nextstep = 0;
1913 /* When we reach the value that triggers a progress bar update,
1914 bump that value by this amount. */
1915 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1916 /* Count of packets at which we've looked. */
1918 /* Progress so far. */
1922 g_get_current_time(&start_time);
1924 /* no previous row yet */
1925 prev_frame_num = -1;
1928 preceding_frame_num = -1;
1929 preceding_frame = NULL;
1930 following_frame_num = -1;
1931 following_frame = NULL;
1933 selected_frame_seen = FALSE;
1935 frames_count = cf->count;
1937 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1939 for (framenum = 1; framenum <= frames_count; framenum++) {
1940 fdata = frame_data_sequence_find(cf->frames, framenum);
1942 /* Create the progress bar if necessary.
1943 We check on every iteration of the loop, so that it takes no
1944 longer than the standard time to create it (otherwise, for a
1945 large file, we might take considerably longer than that standard
1946 time in order to get to the next progress bar step). */
1947 if (progbar == NULL)
1948 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1949 &stop_flag, &start_time,
1952 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1953 when we update it, we have to run the GTK+ main loop to get it
1954 to repaint what's pending, and doing so may involve an "ioctl()"
1955 to see if there's any pending input from an X server, and doing
1956 that for every packet can be costly, especially on a big file. */
1957 if (count >= progbar_nextstep) {
1958 /* let's not divide by zero. I should never be started
1959 * with count == 0, so let's assert that
1961 g_assert(cf->count > 0);
1962 progbar_val = (gfloat) count / frames_count;
1964 if (progbar != NULL) {
1965 g_snprintf(status_str, sizeof(status_str),
1966 "%4u of %u frames", count, frames_count);
1967 update_progress_dlg(progbar, progbar_val, status_str);
1970 progbar_nextstep += progbar_quantum;
1974 /* Well, the user decided to abort the filtering. Just stop.
1976 XXX - go back to the previous filter? Users probably just
1977 want not to wait for a filtering operation to finish;
1978 unless we cancel by having no filter, reverting to the
1979 previous filter will probably be even more expensive than
1980 continuing the filtering, as it involves going back to the
1981 beginning and filtering, and even with no filter we currently
1982 have to re-generate the entire clist, which is also expensive.
1984 I'm not sure what Network Monitor does, but it doesn't appear
1985 to give you an unfiltered display if you cancel. */
1992 /* Since all state for the frame was destroyed, mark the frame
1993 * as not visited, free the GSList referring to the state
1994 * data (the per-frame data itself was freed by
1995 * "init_dissection()"), and null out the GSList pointer. */
1996 frame_data_reset(fdata);
1997 frames_count = cf->count;
2000 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
2001 fdata->flags.dependent_of_displayed = 0;
2003 if (!cf_read_frame(cf, fdata))
2004 break; /* error reading the frame */
2006 /* If the previous frame is displayed, and we haven't yet seen the
2007 selected frame, remember that frame - it's the closest one we've
2008 yet seen before the selected frame. */
2009 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
2010 preceding_frame_num = prev_frame_num;
2011 preceding_frame = prev_frame;
2014 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
2016 buffer_start_ptr(&cf->buf),
2017 add_to_packet_list);
2019 /* If this frame is displayed, and this is the first frame we've
2020 seen displayed after the selected frame, remember this frame -
2021 it's the closest one we've yet seen at or after the selected
2023 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
2024 following_frame_num = fdata->num;
2025 following_frame = fdata;
2027 if (fdata == selected_frame) {
2028 selected_frame_seen = TRUE;
2029 if (fdata->flags.passed_dfilter)
2030 selected_frame_num = fdata->num;
2033 /* Remember this frame - it'll be the previous frame
2034 on the next pass through the loop. */
2035 prev_frame_num = fdata->num;
2039 epan_dissect_cleanup(&edt);
2041 /* We are done redissecting the packet list. */
2042 cf->redissecting = FALSE;
2045 frames_count = cf->count;
2046 /* Clear out what remains of the visited flags and per-frame data
2049 XXX - that may cause various forms of bogosity when dissecting
2050 these frames, as they won't have been seen by this sequential
2051 pass, but the only alternative I see is to keep scanning them
2052 even though the user requested that the scan stop, and that
2053 would leave the user stuck with an Wireshark grinding on
2054 until it finishes. Should we just stick them with that? */
2055 for (; framenum <= frames_count; framenum++) {
2056 fdata = frame_data_sequence_find(cf->frames, framenum);
2057 frame_data_reset(fdata);
2061 /* We're done filtering the packets; destroy the progress bar if it
2063 if (progbar != NULL)
2064 destroy_progress_dlg(progbar);
2066 /* Unfreeze the packet list. */
2067 if (!add_to_packet_list)
2068 packet_list_recreate_visible_rows();
2070 /* Compute the time it took to filter the file */
2071 compute_elapsed(cf, &start_time);
2075 if (selected_frame_num == -1) {
2076 /* The selected frame didn't pass the filter. */
2077 if (selected_frame == NULL) {
2078 /* That's because there *was* no selected frame. Make the first
2079 displayed frame the current frame. */
2080 selected_frame_num = 0;
2082 /* Find the nearest displayed frame to the selected frame (whether
2083 it's before or after that frame) and make that the current frame.
2084 If the next and previous displayed frames are equidistant from the
2085 selected frame, choose the next one. */
2086 g_assert(following_frame == NULL ||
2087 following_frame->num >= selected_frame->num);
2088 g_assert(preceding_frame == NULL ||
2089 preceding_frame->num <= selected_frame->num);
2090 if (following_frame == NULL) {
2091 /* No frame after the selected frame passed the filter, so we
2092 have to select the last displayed frame before the selected
2094 selected_frame_num = preceding_frame_num;
2095 selected_frame = preceding_frame;
2096 } else if (preceding_frame == NULL) {
2097 /* No frame before the selected frame passed the filter, so we
2098 have to select the first displayed frame after the selected
2100 selected_frame_num = following_frame_num;
2101 selected_frame = following_frame;
2103 /* Frames before and after the selected frame passed the filter, so
2104 we'll select the previous frame */
2105 selected_frame_num = preceding_frame_num;
2106 selected_frame = preceding_frame;
2111 if (selected_frame_num == -1) {
2112 /* There are no frames displayed at all. */
2113 cf_unselect_packet(cf);
2115 /* Either the frame that was selected passed the filter, or we've
2116 found the nearest displayed frame to that frame. Select it, make
2117 it the focus row, and make it visible. */
2118 /* Set to invalid to force update of packet list and packet details */
2119 cf->current_row = -1;
2120 if (selected_frame_num == 0) {
2121 packet_list_select_first_row();
2123 if (!packet_list_select_row_from_data(selected_frame)) {
2124 /* We didn't find a row corresponding to this frame.
2125 This means that the frame isn't being displayed currently,
2126 so we can't select it. */
2127 simple_message_box(ESD_TYPE_INFO, NULL,
2128 "The capture file is probably not fully dissected.",
2129 "End of capture exceeded!");
2134 /* Cleanup and release all dfilter resources */
2135 dfilter_free(dfcode);
2140 * Scan trough all frame data and recalculate the ref time
2141 * without rereading the file.
2142 * XXX - do we need a progres bar or is this fast enough?
2145 ref_time_packets(capture_file *cf)
2152 cf->prev_dis = NULL;
2155 for (framenum = 1; framenum <= cf->count; framenum++) {
2156 fdata = frame_data_sequence_find(cf->frames, framenum);
2158 /* just add some value here until we know if it is being displayed or not */
2159 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
2165 /* If we don't have the time stamp of the first packet in the
2166 capture, it's because this is the first packet. Save the time
2167 stamp of this packet as the time stamp of the first packet. */
2168 if (cf->ref == NULL)
2170 /* if this frames is marked as a reference time frame, reset
2171 firstsec and firstusec to this frame */
2172 if (fdata->flags.ref_time)
2175 /* If we don't have the time stamp of the previous displayed packet,
2176 it's because this is the first displayed packet. Save the time
2177 stamp of this packet as the time stamp of the previous displayed
2179 if (cf->prev_dis == NULL) {
2180 cf->prev_dis = fdata;
2183 /* Get the time elapsed between the first packet and this packet. */
2184 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
2185 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
2187 /* If it's greater than the current elapsed time, set the elapsed time
2188 to it (we check for "greater than" so as not to be confused by
2189 time moving backwards). */
2190 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2191 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2192 cf->elapsed_time = rel_ts;
2195 /* If this frame is displayed, get the time elapsed between the
2196 previous displayed packet and this packet. */
2197 if ( fdata->flags.passed_dfilter ) {
2198 fdata->prev_dis_num = cf->prev_dis->num;
2199 cf->prev_dis = fdata;
2205 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2206 /* This frame either passed the display filter list or is marked as
2207 a time reference frame. All time reference frames are displayed
2208 even if they dont pass the display filter */
2209 if (fdata->flags.ref_time) {
2210 /* if this was a TIME REF frame we should reset the cum_bytes field */
2211 cf->cum_bytes = fdata->pkt_len;
2212 fdata->cum_bytes = cf->cum_bytes;
2214 /* increase cum_bytes with this packets length */
2215 cf->cum_bytes += fdata->pkt_len;
2228 process_specified_packets(capture_file *cf, packet_range_t *range,
2229 const char *string1, const char *string2, gboolean terminate_is_stop,
2230 gboolean (*callback)(capture_file *, frame_data *,
2231 struct wtap_pkthdr *, const guint8 *, void *),
2232 void *callback_args)
2237 psp_return_t ret = PSP_FINISHED;
2239 progdlg_t *progbar = NULL;
2242 gboolean progbar_stop_flag;
2243 GTimeVal progbar_start_time;
2244 gchar progbar_status_str[100];
2245 int progbar_nextstep;
2246 int progbar_quantum;
2247 range_process_e process_this;
2248 struct wtap_pkthdr phdr;
2250 memset(&phdr, 0, sizeof(struct wtap_pkthdr));
2251 buffer_init(&buf, 1500);
2253 /* Update the progress bar when it gets to this value. */
2254 progbar_nextstep = 0;
2255 /* When we reach the value that triggers a progress bar update,
2256 bump that value by this amount. */
2257 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2258 /* Count of packets at which we've looked. */
2260 /* Progress so far. */
2263 progbar_stop_flag = FALSE;
2264 g_get_current_time(&progbar_start_time);
2267 packet_range_process_init(range);
2269 /* Iterate through all the packets, printing the packets that
2270 were selected by the current display filter. */
2271 for (framenum = 1; framenum <= cf->count; framenum++) {
2272 fdata = frame_data_sequence_find(cf->frames, framenum);
2274 /* Create the progress bar if necessary.
2275 We check on every iteration of the loop, so that it takes no
2276 longer than the standard time to create it (otherwise, for a
2277 large file, we might take considerably longer than that standard
2278 time in order to get to the next progress bar step). */
2279 if (progbar == NULL)
2280 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2283 &progbar_start_time,
2286 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2287 when we update it, we have to run the GTK+ main loop to get it
2288 to repaint what's pending, and doing so may involve an "ioctl()"
2289 to see if there's any pending input from an X server, and doing
2290 that for every packet can be costly, especially on a big file. */
2291 if (progbar_count >= progbar_nextstep) {
2292 /* let's not divide by zero. I should never be started
2293 * with count == 0, so let's assert that
2295 g_assert(cf->count > 0);
2296 progbar_val = (gfloat) progbar_count / cf->count;
2298 if (progbar != NULL) {
2299 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2300 "%4u of %u packets", progbar_count, cf->count);
2301 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2304 progbar_nextstep += progbar_quantum;
2307 if (progbar_stop_flag) {
2308 /* Well, the user decided to abort the operation. Just stop,
2309 and arrange to return PSP_STOPPED to our caller, so they know
2310 it was stopped explicitly. */
2317 if (range != NULL) {
2318 /* do we have to process this packet? */
2319 process_this = packet_range_process_packet(range, fdata);
2320 if (process_this == range_process_next) {
2321 /* this packet uninteresting, continue with next one */
2323 } else if (process_this == range_processing_finished) {
2324 /* all interesting packets processed, stop the loop */
2329 /* Get the packet */
2330 if (!cf_read_frame_r(cf, fdata, &phdr, &buf)) {
2331 /* Attempt to get the packet failed. */
2335 /* Process the packet */
2336 if (!callback(cf, fdata, &phdr, buffer_start_ptr(&buf), callback_args)) {
2337 /* Callback failed. We assume it reported the error appropriately. */
2343 /* We're done printing the packets; destroy the progress bar if
2345 if (progbar != NULL)
2346 destroy_progress_dlg(progbar);
2356 } retap_callback_args_t;
2359 retap_packet(capture_file *cf _U_, frame_data *fdata,
2360 struct wtap_pkthdr *phdr, const guint8 *pd,
2363 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2365 epan_dissect_run_with_taps(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2366 epan_dissect_reset(&args->edt);
2372 cf_retap_packets(capture_file *cf)
2374 packet_range_t range;
2375 retap_callback_args_t callback_args;
2376 gboolean construct_protocol_tree;
2377 gboolean filtering_tap_listeners;
2381 /* Do we have any tap listeners with filters? */
2382 filtering_tap_listeners = have_filtering_tap_listeners();
2384 tap_flags = union_of_tap_listener_flags();
2386 /* If any tap listeners have filters, or require the protocol tree,
2387 construct the protocol tree. */
2388 construct_protocol_tree = filtering_tap_listeners ||
2389 (tap_flags & TL_REQUIRES_PROTO_TREE);
2391 /* If any tap listeners require the columns, construct them. */
2392 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2394 /* Reset the tap listeners. */
2395 reset_tap_listeners();
2397 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2399 /* Iterate through the list of packets, dissecting all packets and
2400 re-running the taps. */
2401 packet_range_init(&range, cf);
2402 packet_range_process_init(&range);
2404 ret = process_specified_packets(cf, &range, "Recalculating statistics on",
2405 "all packets", TRUE, retap_packet,
2408 epan_dissect_cleanup(&callback_args.edt);
2412 /* Completed successfully. */
2416 /* Well, the user decided to abort the refiltering.
2417 Return CF_READ_ABORTED so our caller knows they did that. */
2418 return CF_READ_ABORTED;
2421 /* Error while retapping. */
2422 return CF_READ_ERROR;
2425 g_assert_not_reached();
2430 print_args_t *print_args;
2431 gboolean print_header_line;
2432 char *header_line_buf;
2433 int header_line_buf_len;
2434 gboolean print_formfeed;
2435 gboolean print_separator;
2439 int num_visible_cols;
2442 } print_callback_args_t;
2445 print_packet(capture_file *cf, frame_data *fdata,
2446 struct wtap_pkthdr *phdr, const guint8 *pd,
2449 print_callback_args_t *args = (print_callback_args_t *)argsp;
2455 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2456 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2458 /* Fill in the column information if we're printing the summary
2460 if (args->print_args->print_summary) {
2461 col_custom_prime_edt(&args->edt, &cf->cinfo);
2462 epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2463 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2465 epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2467 if (args->print_formfeed) {
2468 if (!new_page(args->print_args->stream))
2471 if (args->print_separator) {
2472 if (!print_line(args->print_args->stream, 0, ""))
2478 * We generate bookmarks, if the output format supports them.
2479 * The name is "__frameN__".
2481 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2483 if (args->print_args->print_summary) {
2484 if (!args->print_args->print_col_headings)
2485 args->print_header_line = FALSE;
2486 if (args->print_header_line) {
2487 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2489 args->print_header_line = FALSE; /* we might not need to print any more */
2491 cp = &args->line_buf[0];
2493 for (i = 0; i < args->num_visible_cols; i++) {
2494 /* Find the length of the string for this column. */
2495 column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
2496 if (args->col_widths[i] > column_len)
2497 column_len = args->col_widths[i];
2499 /* Make sure there's room in the line buffer for the column; if not,
2500 double its length. */
2501 line_len += column_len + 1; /* "+1" for space */
2502 if (line_len > args->line_buf_len) {
2503 cp_off = (int) (cp - args->line_buf);
2504 args->line_buf_len = 2 * line_len;
2505 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2506 cp = args->line_buf + cp_off;
2509 /* Right-justify the packet number column. */
2510 if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
2511 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2513 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2515 if (i != args->num_visible_cols - 1)
2521 * Generate a bookmark, using the summary line as the title.
2523 if (!print_bookmark(args->print_args->stream, bookmark_name,
2527 if (!print_line(args->print_args->stream, 0, args->line_buf))
2531 * Generate a bookmark, using "Frame N" as the title, as we're not
2532 * printing the summary line.
2534 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2535 if (!print_bookmark(args->print_args->stream, bookmark_name,
2538 } /* if (print_summary) */
2540 if (args->print_args->print_dissections != print_dissections_none) {
2541 if (args->print_args->print_summary) {
2542 /* Separate the summary line from the tree with a blank line. */
2543 if (!print_line(args->print_args->stream, 0, ""))
2547 /* Print the information in that tree. */
2548 if (!proto_tree_print(args->print_args, &args->edt, args->print_args->stream))
2551 /* Print a blank line if we print anything after this (aka more than one packet). */
2552 args->print_separator = TRUE;
2554 /* Print a header line if we print any more packet summaries */
2555 if (args->print_args->print_col_headings)
2556 args->print_header_line = TRUE;
2559 if (args->print_args->print_hex) {
2560 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2561 if (!print_line(args->print_args->stream, 0, ""))
2564 /* Print the full packet data as hex. */
2565 if (!print_hex_data(args->print_args->stream, &args->edt))
2568 /* Print a blank line if we print anything after this (aka more than one packet). */
2569 args->print_separator = TRUE;
2571 /* Print a header line if we print any more packet summaries */
2572 if (args->print_args->print_col_headings)
2573 args->print_header_line = TRUE;
2574 } /* if (args->print_args->print_dissections != print_dissections_none) */
2576 epan_dissect_reset(&args->edt);
2578 /* do we want to have a formfeed between each packet from now on? */
2579 if (args->print_args->print_formfeed) {
2580 args->print_formfeed = TRUE;
2586 epan_dissect_reset(&args->edt);
2591 cf_print_packets(capture_file *cf, print_args_t *print_args)
2593 print_callback_args_t callback_args;
2596 int i, cp_off, column_len, line_len;
2597 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2601 gboolean proto_tree_needed;
2603 callback_args.print_args = print_args;
2604 callback_args.print_header_line = print_args->print_col_headings;
2605 callback_args.header_line_buf = NULL;
2606 callback_args.header_line_buf_len = 256;
2607 callback_args.print_formfeed = FALSE;
2608 callback_args.print_separator = FALSE;
2609 callback_args.line_buf = NULL;
2610 callback_args.line_buf_len = 256;
2611 callback_args.col_widths = NULL;
2612 callback_args.num_visible_cols = 0;
2613 callback_args.visible_cols = NULL;
2615 if (!print_preamble(print_args->stream, cf->filename, wireshark_gitversion)) {
2616 destroy_print_stream(print_args->stream);
2617 return CF_PRINT_WRITE_ERROR;
2620 if (print_args->print_summary) {
2621 /* We're printing packet summaries. Allocate the header line buffer
2622 and get the column widths. */
2623 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2625 /* Find the number of visible columns and the last visible column */
2626 for (i = 0; i < prefs.num_cols; i++) {
2628 clp = g_list_nth(prefs.col_list, i);
2629 if (clp == NULL) /* Sanity check, Invalid column requested */
2632 cfmt = (fmt_data *) clp->data;
2633 if (cfmt->visible) {
2635 last_visible_col = i;
2639 /* Find the widths for each of the columns - maximum of the
2640 width of the title and the width of the data - and construct
2641 a buffer with a line containing the column titles. */
2642 callback_args.num_visible_cols = num_visible_col;
2643 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2644 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2645 cp = &callback_args.header_line_buf[0];
2647 visible_col_count = 0;
2648 for (i = 0; i < cf->cinfo.num_cols; i++) {
2650 clp = g_list_nth(prefs.col_list, i);
2651 if (clp == NULL) /* Sanity check, Invalid column requested */
2654 cfmt = (fmt_data *) clp->data;
2655 if (cfmt->visible == FALSE)
2658 /* Save the order of visible columns */
2659 callback_args.visible_cols[visible_col_count] = i;
2661 /* Don't pad the last column. */
2662 if (i == last_visible_col)
2663 callback_args.col_widths[visible_col_count] = 0;
2665 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
2666 data_width = get_column_char_width(get_column_format(i));
2667 if (data_width > callback_args.col_widths[visible_col_count])
2668 callback_args.col_widths[visible_col_count] = data_width;
2671 /* Find the length of the string for this column. */
2672 column_len = (int) strlen(cf->cinfo.col_title[i]);
2673 if (callback_args.col_widths[i] > column_len)
2674 column_len = callback_args.col_widths[visible_col_count];
2676 /* Make sure there's room in the line buffer for the column; if not,
2677 double its length. */
2678 line_len += column_len + 1; /* "+1" for space */
2679 if (line_len > callback_args.header_line_buf_len) {
2680 cp_off = (int) (cp - callback_args.header_line_buf);
2681 callback_args.header_line_buf_len = 2 * line_len;
2682 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2683 callback_args.header_line_buf_len + 1);
2684 cp = callback_args.header_line_buf + cp_off;
2687 /* Right-justify the packet number column. */
2688 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2689 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2691 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2693 if (i != cf->cinfo.num_cols - 1)
2696 visible_col_count++;
2700 /* Now start out the main line buffer with the same length as the
2701 header line buffer. */
2702 callback_args.line_buf_len = callback_args.header_line_buf_len;
2703 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2704 } /* if (print_summary) */
2706 /* Create the protocol tree, and make it visible, if we're printing
2707 the dissection or the hex data.
2708 XXX - do we need it if we're just printing the hex data? */
2710 callback_args.print_args->print_dissections != print_dissections_none ||
2711 callback_args.print_args->print_hex ||
2712 have_custom_cols(&cf->cinfo);
2713 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2715 /* Iterate through the list of packets, printing the packets we were
2717 ret = process_specified_packets(cf, &print_args->range, "Printing",
2718 "selected packets", TRUE, print_packet,
2720 epan_dissect_cleanup(&callback_args.edt);
2721 g_free(callback_args.header_line_buf);
2722 g_free(callback_args.line_buf);
2723 g_free(callback_args.col_widths);
2724 g_free(callback_args.visible_cols);
2729 /* Completed successfully. */
2733 /* Well, the user decided to abort the printing.
2735 XXX - note that what got generated before they did that
2736 will get printed if we're piping to a print program; we'd
2737 have to write to a file and then hand that to the print
2738 program to make it actually not print anything. */
2742 /* Error while printing.
2744 XXX - note that what got generated before they did that
2745 will get printed if we're piping to a print program; we'd
2746 have to write to a file and then hand that to the print
2747 program to make it actually not print anything. */
2748 destroy_print_stream(print_args->stream);
2749 return CF_PRINT_WRITE_ERROR;
2752 if (!print_finale(print_args->stream)) {
2753 destroy_print_stream(print_args->stream);
2754 return CF_PRINT_WRITE_ERROR;
2757 if (!destroy_print_stream(print_args->stream))
2758 return CF_PRINT_WRITE_ERROR;
2766 } write_packet_callback_args_t;
2769 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2770 struct wtap_pkthdr *phdr, const guint8 *pd,
2773 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2775 /* Create the protocol tree, but don't fill in the column information. */
2776 epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2778 /* Write out the information in that tree. */
2779 proto_tree_write_pdml(&args->edt, args->fh);
2781 epan_dissect_reset(&args->edt);
2783 return !ferror(args->fh);
2787 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2789 write_packet_callback_args_t callback_args;
2793 fh = ws_fopen(print_args->file, "w");
2795 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2797 write_pdml_preamble(fh, cf->filename);
2800 return CF_PRINT_WRITE_ERROR;
2803 callback_args.fh = fh;
2804 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2806 /* Iterate through the list of packets, printing the packets we were
2808 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2809 "selected packets", TRUE,
2810 write_pdml_packet, &callback_args);
2812 epan_dissect_cleanup(&callback_args.edt);
2817 /* Completed successfully. */
2821 /* Well, the user decided to abort the printing. */
2825 /* Error while printing. */
2827 return CF_PRINT_WRITE_ERROR;
2830 write_pdml_finale(fh);
2833 return CF_PRINT_WRITE_ERROR;
2836 /* XXX - check for an error */
2843 write_psml_packet(capture_file *cf, frame_data *fdata,
2844 struct wtap_pkthdr *phdr, const guint8 *pd,
2847 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2849 col_custom_prime_edt(&args->edt, &cf->cinfo);
2850 epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2851 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2853 /* Write out the information in that tree. */
2854 proto_tree_write_psml(&args->edt, args->fh);
2856 epan_dissect_reset(&args->edt);
2858 return !ferror(args->fh);
2862 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2864 write_packet_callback_args_t callback_args;
2868 gboolean proto_tree_needed;
2870 fh = ws_fopen(print_args->file, "w");
2872 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2874 write_psml_preamble(fh);
2877 return CF_PRINT_WRITE_ERROR;
2880 callback_args.fh = fh;
2882 /* Fill in the column information, only create the protocol tree
2883 if having custom columns. */
2884 proto_tree_needed = have_custom_cols(&cf->cinfo);
2885 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2887 /* Iterate through the list of packets, printing the packets we were
2889 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2890 "selected packets", TRUE,
2891 write_psml_packet, &callback_args);
2893 epan_dissect_cleanup(&callback_args.edt);
2898 /* Completed successfully. */
2902 /* Well, the user decided to abort the printing. */
2906 /* Error while printing. */
2908 return CF_PRINT_WRITE_ERROR;
2911 write_psml_finale(fh);
2914 return CF_PRINT_WRITE_ERROR;
2917 /* XXX - check for an error */
2924 write_csv_packet(capture_file *cf, frame_data *fdata,
2925 struct wtap_pkthdr *phdr, const guint8 *pd,
2928 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2930 /* Fill in the column information */
2931 col_custom_prime_edt(&args->edt, &cf->cinfo);
2932 epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2933 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2935 /* Write out the information in that tree. */
2936 proto_tree_write_csv(&args->edt, args->fh);
2938 epan_dissect_reset(&args->edt);
2940 return !ferror(args->fh);
2944 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2946 write_packet_callback_args_t callback_args;
2947 gboolean proto_tree_needed;
2951 fh = ws_fopen(print_args->file, "w");
2953 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2955 write_csv_preamble(fh);
2958 return CF_PRINT_WRITE_ERROR;
2961 callback_args.fh = fh;
2963 /* only create the protocol tree if having custom columns. */
2964 proto_tree_needed = have_custom_cols(&cf->cinfo);
2965 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2967 /* Iterate through the list of packets, printing the packets we were
2969 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2970 "selected packets", TRUE,
2971 write_csv_packet, &callback_args);
2973 epan_dissect_cleanup(&callback_args.edt);
2978 /* Completed successfully. */
2982 /* Well, the user decided to abort the printing. */
2986 /* Error while printing. */
2988 return CF_PRINT_WRITE_ERROR;
2991 write_csv_finale(fh);
2994 return CF_PRINT_WRITE_ERROR;
2997 /* XXX - check for an error */
3004 write_carrays_packet(capture_file *cf _U_, frame_data *fdata,
3005 struct wtap_pkthdr *phdr,
3006 const guint8 *pd, void *argsp)
3008 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
3010 epan_dissect_run(&args->edt, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
3011 proto_tree_write_carrays(fdata->num, args->fh, &args->edt);
3012 epan_dissect_reset(&args->edt);
3014 return !ferror(args->fh);
3018 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
3020 write_packet_callback_args_t callback_args;
3024 fh = ws_fopen(print_args->file, "w");
3027 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3029 write_carrays_preamble(fh);
3033 return CF_PRINT_WRITE_ERROR;
3036 callback_args.fh = fh;
3037 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
3039 /* Iterate through the list of packets, printing the packets we were
3041 ret = process_specified_packets(cf, &print_args->range,
3043 "selected packets", TRUE,
3044 write_carrays_packet, &callback_args);
3046 epan_dissect_cleanup(&callback_args.edt);
3050 /* Completed successfully. */
3053 /* Well, the user decided to abort the printing. */
3056 /* Error while printing. */
3058 return CF_PRINT_WRITE_ERROR;
3061 write_carrays_finale(fh);
3065 return CF_PRINT_WRITE_ERROR;
3073 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3074 search_direction dir)
3078 mdata.string = string;
3079 mdata.string_len = strlen(string);
3080 return find_packet(cf, match_protocol_tree, &mdata, dir);
3084 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3086 mdata->frame_matched = FALSE;
3087 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3088 mdata->string_len = strlen(mdata->string);
3090 /* Iterate through all the nodes looking for matching text */
3091 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3092 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3096 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3098 match_data *mdata = (match_data *)criterion;
3101 /* Load the frame's data. */
3102 if (!cf_read_frame(cf, fdata)) {
3103 /* Attempt to get the packet failed. */
3107 /* Construct the protocol tree, including the displayed text */
3108 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3109 /* We don't need the column information */
3110 epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3112 /* Iterate through all the nodes, seeing if they have text that matches. */
3114 mdata->frame_matched = FALSE;
3115 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3116 epan_dissect_cleanup(&edt);
3117 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3121 match_subtree_text(proto_node *node, gpointer data)
3123 match_data *mdata = (match_data *) data;
3124 const gchar *string = mdata->string;
3125 size_t string_len = mdata->string_len;
3126 capture_file *cf = mdata->cf;
3127 field_info *fi = PNODE_FINFO(node);
3128 gchar label_str[ITEM_LABEL_LENGTH];
3135 /* dissection with an invisible proto tree? */
3138 if (mdata->frame_matched) {
3139 /* We already had a match; don't bother doing any more work. */
3143 /* Don't match invisible entries. */
3144 if (PROTO_ITEM_IS_HIDDEN(node))
3147 /* was a free format label produced? */
3149 label_ptr = fi->rep->representation;
3151 /* no, make a generic label */
3152 label_ptr = label_str;
3153 proto_item_fill_label(fi, label_str);
3156 /* Does that label match? */
3157 label_len = strlen(label_ptr);
3158 for (i = 0; i < label_len; i++) {
3159 c_char = label_ptr[i];
3161 c_char = toupper(c_char);
3162 if (c_char == string[c_match]) {
3164 if (c_match == string_len) {
3165 /* No need to look further; we have a match */
3166 mdata->frame_matched = TRUE;
3174 /* Recurse into the subtree, if it exists */
3175 if (node->first_child != NULL)
3176 proto_tree_children_foreach(node, match_subtree_text, mdata);
3180 cf_find_packet_summary_line(capture_file *cf, const char *string,
3181 search_direction dir)
3185 mdata.string = string;
3186 mdata.string_len = strlen(string);
3187 return find_packet(cf, match_summary_line, &mdata, dir);
3191 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3193 match_data *mdata = (match_data *)criterion;
3194 const gchar *string = mdata->string;
3195 size_t string_len = mdata->string_len;
3197 const char *info_column;
3198 size_t info_column_len;
3199 match_result result = MR_NOTMATCHED;
3205 /* Load the frame's data. */
3206 if (!cf_read_frame(cf, fdata)) {
3207 /* Attempt to get the packet failed. */
3211 /* Don't bother constructing the protocol tree */
3212 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3213 /* Get the column information */
3214 epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3217 /* Find the Info column */
3218 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3219 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3220 /* Found it. See if we match. */
3221 info_column = edt.pi.cinfo->col_data[colx];
3222 info_column_len = strlen(info_column);
3223 for (i = 0; i < info_column_len; i++) {
3224 c_char = info_column[i];
3226 c_char = toupper(c_char);
3227 if (c_char == string[c_match]) {
3229 if (c_match == string_len) {
3230 result = MR_MATCHED;
3239 epan_dissect_cleanup(&edt);
3246 } cbs_t; /* "Counted byte string" */
3250 * The current match_* routines only support ASCII case insensitivity and don't
3251 * convert UTF-8 inputs to UTF-16 for matching.
3253 * We could modify them to use the GLib Unicode routines or the International
3254 * Components for Unicode library but it's not apparent that we could do so
3255 * without consuming a lot more CPU and memory or that searching would be
3256 * significantly better.
3260 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3261 search_direction dir)
3266 info.data_len = string_size;
3268 /* String or hex search? */
3270 /* String search - what type of string? */
3271 switch (cf->scs_type) {
3273 case SCS_NARROW_AND_WIDE:
3274 return find_packet(cf, match_narrow_and_wide, &info, dir);
3277 return find_packet(cf, match_narrow, &info, dir);
3280 return find_packet(cf, match_wide, &info, dir);
3283 g_assert_not_reached();
3287 return find_packet(cf, match_binary, &info, dir);
3291 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3293 cbs_t *info = (cbs_t *)criterion;
3294 const guint8 *ascii_text = info->data;
3295 size_t textlen = info->data_len;
3296 match_result result;
3303 /* Load the frame's data. */
3304 if (!cf_read_frame(cf, fdata)) {
3305 /* Attempt to get the packet failed. */
3309 result = MR_NOTMATCHED;
3310 buf_len = fdata->cap_len;
3311 pd = buffer_start_ptr(&cf->buf);
3313 while (i < buf_len) {
3316 c_char = toupper(c_char);
3317 if (c_char != '\0') {
3318 if (c_char == ascii_text[c_match]) {
3320 if (c_match == textlen) {
3321 result = MR_MATCHED;
3322 cf->search_pos = i; /* Save the position of the last character
3323 for highlighting the field. */
3328 g_assert(i>=c_match);
3329 i -= (guint32)c_match;
3339 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3342 cbs_t *info = (cbs_t *)criterion;
3343 const guint8 *ascii_text = info->data;
3344 size_t textlen = info->data_len;
3345 match_result result;
3351 /* Load the frame's data. */
3352 if (!cf_read_frame(cf, fdata)) {
3353 /* Attempt to get the packet failed. */
3357 result = MR_NOTMATCHED;
3358 buf_len = fdata->cap_len;
3359 pd = buffer_start_ptr(&cf->buf);
3361 while (i < buf_len) {
3364 c_char = toupper(c_char);
3365 if (c_char == ascii_text[c_match]) {
3367 if (c_match == textlen) {
3368 result = MR_MATCHED;
3369 cf->search_pos = i; /* Save the position of the last character
3370 for highlighting the field. */
3375 g_assert(i>=c_match);
3376 i -= (guint32)c_match;
3386 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3388 cbs_t *info = (cbs_t *)criterion;
3389 const guint8 *ascii_text = info->data;
3390 size_t textlen = info->data_len;
3391 match_result result;
3398 /* Load the frame's data. */
3399 if (!cf_read_frame(cf, fdata)) {
3400 /* Attempt to get the packet failed. */
3404 result = MR_NOTMATCHED;
3405 buf_len = fdata->cap_len;
3406 pd = buffer_start_ptr(&cf->buf);
3408 while (i < buf_len) {
3411 c_char = toupper(c_char);
3412 if (c_char == ascii_text[c_match]) {
3414 if (c_match == textlen) {
3415 result = MR_MATCHED;
3416 cf->search_pos = i; /* Save the position of the last character
3417 for highlighting the field. */
3423 g_assert(i>=(c_match*2));
3424 i -= (guint32)c_match*2;
3433 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3435 cbs_t *info = (cbs_t *)criterion;
3436 const guint8 *binary_data = info->data;
3437 size_t datalen = info->data_len;
3438 match_result result;
3444 /* Load the frame's data. */
3445 if (!cf_read_frame(cf, fdata)) {
3446 /* Attempt to get the packet failed. */
3450 result = MR_NOTMATCHED;
3451 buf_len = fdata->cap_len;
3452 pd = buffer_start_ptr(&cf->buf);
3454 while (i < buf_len) {
3455 if (pd[i] == binary_data[c_match]) {
3457 if (c_match == datalen) {
3458 result = MR_MATCHED;
3459 cf->search_pos = i; /* Save the position of the last character
3460 for highlighting the field. */
3465 g_assert(i>=c_match);
3466 i -= (guint32)c_match;
3475 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3476 search_direction dir)
3478 return find_packet(cf, match_dfilter, sfcode, dir);
3482 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3483 search_direction dir)
3488 if (!dfilter_compile(filter, &sfcode)) {
3490 * XXX - this shouldn't happen, as the filter string is machine
3495 if (sfcode == NULL) {
3497 * XXX - this shouldn't happen, as the filter string is machine
3502 result = find_packet(cf, match_dfilter, sfcode, dir);
3503 dfilter_free(sfcode);
3508 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3510 dfilter_t *sfcode = (dfilter_t *)criterion;
3512 match_result result;
3514 /* Load the frame's data. */
3515 if (!cf_read_frame(cf, fdata)) {
3516 /* Attempt to get the packet failed. */
3520 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3521 epan_dissect_prime_dfilter(&edt, sfcode);
3522 epan_dissect_run(&edt, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3523 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3524 epan_dissect_cleanup(&edt);
3529 cf_find_packet_marked(capture_file *cf, search_direction dir)
3531 return find_packet(cf, match_marked, NULL, dir);
3535 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3537 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3541 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3543 return find_packet(cf, match_time_reference, NULL, dir);
3547 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3549 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3553 find_packet(capture_file *cf,
3554 match_result (*match_function)(capture_file *, frame_data *, void *),
3555 void *criterion, search_direction dir)
3557 frame_data *start_fd;
3560 frame_data *new_fd = NULL;
3561 progdlg_t *progbar = NULL;
3566 GTimeVal start_time;
3567 gchar status_str[100];
3568 int progbar_nextstep;
3569 int progbar_quantum;
3571 match_result result;
3573 start_fd = cf->current_frame;
3574 if (start_fd != NULL) {
3575 /* Iterate through the list of packets, starting at the packet we've
3576 picked, calling a routine to run the filter on the packet, see if
3577 it matches, and stop if so. */
3579 framenum = start_fd->num;
3581 /* Update the progress bar when it gets to this value. */
3582 progbar_nextstep = 0;
3583 /* When we reach the value that triggers a progress bar update,
3584 bump that value by this amount. */
3585 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3586 /* Progress so far. */
3590 g_get_current_time(&start_time);
3592 title = cf->sfilter?cf->sfilter:"";
3594 /* Create the progress bar if necessary.
3595 We check on every iteration of the loop, so that it takes no
3596 longer than the standard time to create it (otherwise, for a
3597 large file, we might take considerably longer than that standard
3598 time in order to get to the next progress bar step). */
3599 if (progbar == NULL)
3600 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3601 FALSE, &stop_flag, &start_time, progbar_val);
3603 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3604 when we update it, we have to run the GTK+ main loop to get it
3605 to repaint what's pending, and doing so may involve an "ioctl()"
3606 to see if there's any pending input from an X server, and doing
3607 that for every packet can be costly, especially on a big file. */
3608 if (count >= progbar_nextstep) {
3609 /* let's not divide by zero. I should never be started
3610 * with count == 0, so let's assert that
3612 g_assert(cf->count > 0);
3614 progbar_val = (gfloat) count / cf->count;
3616 if (progbar != NULL) {
3617 g_snprintf(status_str, sizeof(status_str),
3618 "%4u of %u packets", count, cf->count);
3619 update_progress_dlg(progbar, progbar_val, status_str);
3622 progbar_nextstep += progbar_quantum;
3626 /* Well, the user decided to abort the search. Go back to the
3627 frame where we started. */
3632 /* Go past the current frame. */
3633 if (dir == SD_BACKWARD) {
3634 /* Go on to the previous frame. */
3635 if (framenum == 1) {
3637 * XXX - other apps have a bit more of a detailed message
3638 * for this, and instead of offering "OK" and "Cancel",
3639 * they offer things such as "Continue" and "Cancel";
3640 * we need an API for popping up alert boxes with
3641 * {Verb} and "Cancel".
3644 if (prefs.gui_find_wrap)
3646 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3647 framenum = cf->count; /* wrap around */
3651 statusbar_push_temporary_msg("Search reached the beginning.");
3652 framenum = start_fd->num; /* stay on previous packet */
3657 /* Go on to the next frame. */
3658 if (framenum == cf->count) {
3659 if (prefs.gui_find_wrap)
3661 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3662 framenum = 1; /* wrap around */
3666 statusbar_push_temporary_msg("Search reached the end.");
3667 framenum = start_fd->num; /* stay on previous packet */
3672 fdata = frame_data_sequence_find(cf->frames, framenum);
3676 /* Is this packet in the display? */
3677 if (fdata->flags.passed_dfilter) {
3678 /* Yes. Does it match the search criterion? */
3679 result = (*match_function)(cf, fdata, criterion);
3680 if (result == MR_ERROR) {
3681 /* Error; our caller has reported the error. Go back to the frame
3682 where we started. */
3685 } else if (result == MR_MATCHED) {
3686 /* Yes. Go to the new frame. */
3692 if (fdata == start_fd) {
3693 /* We're back to the frame we were on originally, and that frame
3694 doesn't match the search filter. The search failed. */
3699 /* We're done scanning the packets; destroy the progress bar if it
3701 if (progbar != NULL)
3702 destroy_progress_dlg(progbar);
3705 if (new_fd != NULL) {
3706 /* Find and select */
3707 cf->search_in_progress = TRUE;
3708 found = packet_list_select_row_from_data(new_fd);
3709 cf->search_in_progress = FALSE;
3710 cf->search_pos = 0; /* Reset the position */
3712 /* We didn't find a row corresponding to this frame.
3713 This means that the frame isn't being displayed currently,
3714 so we can't select it. */
3715 simple_message_box(ESD_TYPE_INFO, NULL,
3716 "The capture file is probably not fully dissected.",
3717 "End of capture exceeded!");
3720 return TRUE; /* success */
3722 return FALSE; /* failure */
3726 cf_goto_frame(capture_file *cf, guint fnumber)
3730 fdata = frame_data_sequence_find(cf->frames, fnumber);
3732 if (fdata == NULL) {
3733 /* we didn't find a packet with that packet number */
3734 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3735 return FALSE; /* we failed to go to that packet */
3737 if (!fdata->flags.passed_dfilter) {
3738 /* that packet currently isn't displayed */
3739 /* XXX - add it to the set of displayed packets? */
3740 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3741 return FALSE; /* we failed to go to that packet */
3744 if (!packet_list_select_row_from_data(fdata)) {
3745 /* We didn't find a row corresponding to this frame.
3746 This means that the frame isn't being displayed currently,
3747 so we can't select it. */
3748 simple_message_box(ESD_TYPE_INFO, NULL,
3749 "The capture file is probably not fully dissected.",
3750 "End of capture exceeded!");
3753 return TRUE; /* we got to that packet */
3757 cf_goto_top_frame(void)
3759 /* Find and select */
3760 packet_list_select_first_row();
3761 return TRUE; /* we got to that packet */
3765 cf_goto_bottom_frame(void)
3767 /* Find and select */
3768 packet_list_select_last_row();
3769 return TRUE; /* we got to that packet */
3773 * Go to frame specified by currently selected protocol tree item.
3776 cf_goto_framenum(capture_file *cf)
3778 header_field_info *hfinfo;
3781 if (cf->finfo_selected) {
3782 hfinfo = cf->finfo_selected->hfinfo;
3784 if (hfinfo->type == FT_FRAMENUM) {
3785 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3787 return cf_goto_frame(cf, framenum);
3794 /* Select the packet on a given row. */
3796 cf_select_packet(capture_file *cf, int row)
3798 epan_dissect_t *old_edt;
3801 /* Get the frame data struct pointer for this frame */
3802 fdata = packet_list_get_row_data(row);
3804 if (fdata == NULL) {
3805 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3806 the first entry is added to it by "real_insert_row()", that row
3807 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3808 our version and the vanilla GTK+ version).
3810 This means that a "select-row" signal is emitted; this causes
3811 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3814 "cf_select_packet()" fetches, above, the data associated with the
3815 row that was selected; however, as "gtk_clist_append()", which
3816 called "real_insert_row()", hasn't yet returned, we haven't yet
3817 associated any data with that row, so we get back a null pointer.
3819 We can't assume that there's only one frame in the frame list,
3820 either, as we may be filtering the display.
3822 We therefore assume that, if "row" is 0, i.e. the first row
3823 is being selected, and "cf->first_displayed" equals
3824 "cf->last_displayed", i.e. there's only one frame being
3825 displayed, that frame is the frame we want.
3827 This means we have to set "cf->first_displayed" and
3828 "cf->last_displayed" before adding the row to the
3829 GtkCList; see the comment in "add_packet_to_packet_list()". */
3831 if (row == 0 && cf->first_displayed == cf->last_displayed)
3832 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3835 /* If fdata _still_ isn't set simply give up. */
3836 if (fdata == NULL) {
3840 /* Get the data in that frame. */
3841 if (!cf_read_frame (cf, fdata)) {
3845 /* Record that this frame is the current frame. */
3846 cf->current_frame = fdata;
3847 cf->current_row = row;
3850 /* Create the logical protocol tree. */
3851 /* We don't need the columns here. */
3852 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3854 tap_build_interesting(cf->edt);
3855 epan_dissect_run(cf->edt, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3856 cf->current_frame, NULL);
3858 dfilter_macro_build_ftv_cache(cf->edt->tree);
3860 cf_callback_invoke(cf_cb_packet_selected, cf);
3862 if (old_edt != NULL)
3863 epan_dissect_free(old_edt);
3867 /* Unselect the selected packet, if any. */
3869 cf_unselect_packet(capture_file *cf)
3871 epan_dissect_t *old_edt = cf->edt;
3875 /* No packet is selected. */
3876 cf->current_frame = NULL;
3877 cf->current_row = 0;
3879 cf_callback_invoke(cf_cb_packet_unselected, cf);
3881 /* No protocol tree means no selected field. */
3882 cf_unselect_field(cf);
3884 /* Destroy the epan_dissect_t for the unselected packet. */
3885 if (old_edt != NULL)
3886 epan_dissect_free(old_edt);
3889 /* Unset the selected protocol tree field, if any. */
3891 cf_unselect_field(capture_file *cf)
3893 cf->finfo_selected = NULL;
3895 cf_callback_invoke(cf_cb_field_unselected, cf);
3899 * Mark a particular frame.
3902 cf_mark_frame(capture_file *cf, frame_data *frame)
3904 if (! frame->flags.marked) {
3905 frame->flags.marked = TRUE;
3906 if (cf->count > cf->marked_count)
3912 * Unmark a particular frame.
3915 cf_unmark_frame(capture_file *cf, frame_data *frame)
3917 if (frame->flags.marked) {
3918 frame->flags.marked = FALSE;
3919 if (cf->marked_count > 0)
3925 * Ignore a particular frame.
3928 cf_ignore_frame(capture_file *cf, frame_data *frame)
3930 if (! frame->flags.ignored) {
3931 frame->flags.ignored = TRUE;
3932 if (cf->count > cf->ignored_count)
3933 cf->ignored_count++;
3938 * Un-ignore a particular frame.
3941 cf_unignore_frame(capture_file *cf, frame_data *frame)
3943 if (frame->flags.ignored) {
3944 frame->flags.ignored = FALSE;
3945 if (cf->ignored_count > 0)
3946 cf->ignored_count--;
3951 * Read the comment in SHB block
3955 cf_read_shb_comment(capture_file *cf)
3957 wtapng_section_t *shb_inf;
3958 const gchar *temp_str;
3960 /* Get info from SHB */
3961 shb_inf = wtap_file_get_shb_info(cf->wth);
3962 if (shb_inf == NULL)
3964 temp_str = shb_inf->opt_comment;
3972 cf_update_capture_comment(capture_file *cf, gchar *comment)
3974 wtapng_section_t *shb_inf;
3976 /* Get info from SHB */
3977 shb_inf = wtap_file_get_shb_info(cf->wth);
3979 /* See if the comment has changed or not */
3980 if (shb_inf && shb_inf->opt_comment) {
3981 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3990 /* The comment has changed, let's update it */
3991 wtap_write_shb_comment(cf->wth, comment);
3992 /* Mark the file as having unsaved changes */
3993 cf->unsaved_changes = TRUE;
3997 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3999 if (cf->frames_user_comments)
4000 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
4007 cf_get_comment(capture_file *cf, const frame_data *fd)
4009 /* fetch user comment */
4010 if (fd->flags.has_user_comment)
4011 return g_strdup(cf_get_user_packet_comment(cf, fd));
4013 /* fetch phdr comment */
4014 if (fd->flags.has_phdr_comment) {
4015 struct wtap_pkthdr phdr; /* Packet header */
4016 Buffer buf; /* Packet data */
4018 phdr.opt_comment = NULL;
4020 buffer_init(&buf, 1500);
4021 if (!cf_read_frame_r(cf, fd, &phdr, &buf))
4022 { /* XXX, what we can do here? */ }
4025 return phdr.opt_comment;
4031 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
4033 const frame_data *fdata1 = (const frame_data *) a;
4034 const frame_data *fdata2 = (const frame_data *) b;
4036 return (fdata1->num < fdata2->num) ? -1 :
4037 (fdata1->num > fdata2->num) ? 1 :
4042 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
4044 char *pkt_comment = cf_get_comment(cf, fd);
4046 /* Check if the comment has changed */
4047 if (!g_strcmp0(pkt_comment, new_comment)) {
4048 g_free(pkt_comment);
4051 g_free(pkt_comment);
4054 cf->packet_comment_count--;
4057 cf->packet_comment_count++;
4059 fd->flags.has_user_comment = TRUE;
4061 if (!cf->frames_user_comments)
4062 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
4064 /* insert new packet comment */
4065 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
4067 expert_update_comment_count(cf->packet_comment_count);
4069 /* OK, we have unsaved changes. */
4070 cf->unsaved_changes = TRUE;
4075 * What types of comments does this capture file have?
4078 cf_comment_types(capture_file *cf)
4080 guint32 comment_types = 0;
4082 if (cf_read_shb_comment(cf) != NULL)
4083 comment_types |= WTAP_COMMENT_PER_SECTION;
4084 if (cf->packet_comment_count != 0)
4085 comment_types |= WTAP_COMMENT_PER_PACKET;
4086 return comment_types;
4093 } save_callback_args_t;
4096 * Save a capture to a file, in a particular format, saving either
4097 * all packets, all currently-displayed packets, or all marked packets.
4099 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4100 * up a message box for the failure.
4103 save_packet(capture_file *cf _U_, frame_data *fdata,
4104 struct wtap_pkthdr *phdr, const guint8 *pd,
4107 save_callback_args_t *args = (save_callback_args_t *)argsp;
4108 struct wtap_pkthdr hdr;
4110 gchar *display_basename;
4111 const char *pkt_comment;
4113 if (fdata->flags.has_user_comment)
4114 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4116 pkt_comment = phdr->opt_comment;
4118 /* init the wtap header for saving */
4119 /* TODO: reuse phdr */
4120 /* XXX - these are the only flags that correspond to data that we have
4121 in the frame_data structure and that matter on a per-packet basis.
4123 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4124 and "on the wire" lengths, or it doesn't.
4126 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4129 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4130 from the packet flags. */
4131 hdr.presence_flags = 0;
4132 if (fdata->flags.has_ts)
4133 hdr.presence_flags |= WTAP_HAS_TS;
4134 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4135 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4136 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4137 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4138 hdr.ts.secs = fdata->abs_ts.secs;
4139 hdr.ts.nsecs = fdata->abs_ts.nsecs;
4140 hdr.caplen = fdata->cap_len;
4141 hdr.len = fdata->pkt_len;
4142 hdr.pkt_encap = fdata->lnk_t;
4144 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4146 hdr.pack_flags = phdr->pack_flags;
4147 hdr.opt_comment = g_strdup(pkt_comment);
4150 hdr.pseudo_header = phdr->pseudo_header;
4153 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4155 /* and save the packet */
4156 if (!wtap_dump(args->pdh, &hdr, pd, &err)) {
4158 /* Wiretap error. */
4161 case WTAP_ERR_UNSUPPORTED_ENCAP:
4163 * This is a problem with the particular frame we're writing and
4164 * the file type and subtype we're writing; note that, and report
4165 * the frame number and file type/subtype.
4167 simple_error_message_box(
4168 "Frame %u has a network type that can't be saved in a \"%s\" file.",
4169 fdata->num, wtap_file_type_subtype_string(args->file_type));
4172 case WTAP_ERR_PACKET_TOO_LARGE:
4174 * This is a problem with the particular frame we're writing and
4175 * the file type and subtype we're writing; note that, and report
4176 * the frame number and file type/subtype.
4178 simple_error_message_box(
4179 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
4180 fdata->num, wtap_file_type_subtype_string(args->file_type));
4184 display_basename = g_filename_display_basename(args->fname);
4185 simple_error_message_box(
4186 "An error occurred while writing to the file \"%s\": %s.",
4187 display_basename, wtap_strerror(err));
4188 g_free(display_basename);
4193 write_failure_alert_box(args->fname, err);
4198 g_free(hdr.opt_comment);
4203 * Can this capture file be written out in any format using Wiretap
4204 * rather than by copying the raw data?
4207 cf_can_write_with_wiretap(capture_file *cf)
4209 /* We don't care whether we support the comments in this file or not;
4210 if we can't, we'll offer the user the option of discarding the
4212 return wtap_dump_can_write(cf->linktypes, 0);
4216 * Should we let the user do a save?
4220 * the file has unsaved changes, and we can save it in some
4221 * format through Wiretap
4225 * the file is a temporary file and has no unsaved changes (so
4226 * that "saving" it just means copying it).
4228 * XXX - we shouldn't allow files to be edited if they can't be saved,
4229 * so cf->unsaved_changes should be true only if the file can be saved.
4231 * We don't care whether we support the comments in this file or not;
4232 * if we can't, we'll offer the user the option of discarding the
4236 cf_can_save(capture_file *cf)
4238 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4239 /* Saved changes, and we can write it out with Wiretap. */
4243 if (cf->is_tempfile && !cf->unsaved_changes) {
4245 * Temporary file with no unsaved changes, so we can just do a
4251 /* Nothing to save. */
4256 * Should we let the user do a "save as"?
4260 * we can save it in some format through Wiretap
4264 * the file is a temporary file and has no unsaved changes (so
4265 * that "saving" it just means copying it).
4267 * XXX - we shouldn't allow files to be edited if they can't be saved,
4268 * so cf->unsaved_changes should be true only if the file can be saved.
4270 * We don't care whether we support the comments in this file or not;
4271 * if we can't, we'll offer the user the option of discarding the
4275 cf_can_save_as(capture_file *cf)
4277 if (wtap_dump_can_write(cf->linktypes, 0)) {
4278 /* We can write it out with Wiretap. */
4282 if (cf->is_tempfile && !cf->unsaved_changes) {
4284 * Temporary file with no unsaved changes, so we can just do a
4290 /* Nothing to save. */
4295 * Does this file have unsaved data?
4298 cf_has_unsaved_data(capture_file *cf)
4301 * If this is a temporary file, or a file with unsaved changes, it
4304 return cf->is_tempfile || cf->unsaved_changes;
4308 * Quick scan to find packet offsets.
4310 static cf_read_status_t
4311 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4313 const struct wtap_pkthdr *phdr;
4318 progdlg_t *progbar = NULL;
4322 GTimeVal start_time;
4323 gchar status_str[100];
4324 gint64 progbar_nextstep;
4325 gint64 progbar_quantum;
4330 int displayed_once = 0;
4333 /* Close the old handle. */
4334 wtap_close(cf->wth);
4336 /* Open the new file. */
4337 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4338 if (cf->wth == NULL) {
4339 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4340 return CF_READ_ERROR;
4343 /* We're scanning a file whose contents should be the same as what
4344 we had before, so we don't discard dissection state etc.. */
4347 /* Set the file name because we need it to set the follow stream filter.
4348 XXX - is that still true? We need it for other reasons, though,
4350 cf->filename = g_strdup(fname);
4352 /* Indicate whether it's a permanent or temporary file. */
4353 cf->is_tempfile = is_tempfile;
4355 /* No user changes yet. */
4356 cf->unsaved_changes = FALSE;
4358 cf->cd_t = wtap_file_type_subtype(cf->wth);
4359 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4361 cf->snap = wtap_snapshot_length(cf->wth);
4362 if (cf->snap == 0) {
4363 /* Snapshot length not known. */
4364 cf->has_snap = FALSE;
4365 cf->snap = WTAP_MAX_PACKET_SIZE;
4367 cf->has_snap = TRUE;
4369 name_ptr = g_filename_display_basename(cf->filename);
4371 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4373 /* Record whether the file is compressed.
4374 XXX - do we know this at open time? */
4375 cf->iscompressed = wtap_iscompressed(cf->wth);
4377 /* Find the size of the file. */
4378 size = wtap_file_size(cf->wth, NULL);
4380 /* Update the progress bar when it gets to this value. */
4381 progbar_nextstep = 0;
4382 /* When we reach the value that triggers a progress bar update,
4383 bump that value by this amount. */
4385 progbar_quantum = size/N_PROGBAR_UPDATES;
4386 if (progbar_quantum < MIN_QUANTUM)
4387 progbar_quantum = MIN_QUANTUM;
4389 progbar_quantum = 0;
4392 g_get_current_time(&start_time);
4395 phdr = wtap_phdr(cf->wth);
4396 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4398 fdata = frame_data_sequence_find(cf->frames, framenum);
4399 fdata->file_off = data_offset;
4402 file_pos = wtap_read_so_far(cf->wth);
4404 /* Create the progress bar if necessary.
4405 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4407 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4408 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4409 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4410 TRUE, &stop_flag, &start_time, progbar_val);
4413 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4414 when we update it, we have to run the GTK+ main loop to get it
4415 to repaint what's pending, and doing so may involve an "ioctl()"
4416 to see if there's any pending input from an X server, and doing
4417 that for every packet can be costly, especially on a big file. */
4418 if (file_pos >= progbar_nextstep) {
4419 if (progbar != NULL) {
4420 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4421 /* update the packet bar content on the first run or frequently on very large files */
4423 if (progbar_quantum > 500000 || displayed_once == 0) {
4424 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4426 packets_bar_update();
4429 #endif /* HAVE_LIBPCAP */
4430 update_progress_dlg(progbar, progbar_val, status_str);
4432 progbar_nextstep += progbar_quantum;
4437 /* Well, the user decided to abort the rescan. Sadly, as this
4438 isn't a reread, recovering is difficult, so we'll just
4439 close the current capture. */
4443 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4444 it's not already there.
4445 XXX - yes, this is O(N), so if every packet had a different
4446 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4447 there are probably going to be a small number of encapsulation types
4449 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4452 /* Free the display name */
4455 /* We're done reading the file; destroy the progress bar if it was created. */
4456 if (progbar != NULL)
4457 destroy_progress_dlg(progbar);
4459 /* We're done reading sequentially through the file. */
4460 cf->state = FILE_READ_DONE;
4462 /* Close the sequential I/O side, to free up memory it requires. */
4463 wtap_sequential_close(cf->wth);
4465 /* compute the time it took to load the file */
4466 compute_elapsed(cf, &start_time);
4468 /* Set the file encapsulation type now; we don't know what it is until
4469 we've looked at all the packets, as we don't know until then whether
4470 there's more than one type (and thus whether it's
4471 WTAP_ENCAP_PER_PACKET). */
4472 cf->lnk_t = wtap_file_encap(cf->wth);
4474 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4477 /* Our caller will give up at this point. */
4478 return CF_READ_ABORTED;
4482 /* Put up a message box noting that the read failed somewhere along
4483 the line. Don't throw out the stuff we managed to read, though,
4487 case WTAP_ERR_UNSUPPORTED:
4488 simple_error_message_box(
4489 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4494 case WTAP_ERR_UNSUPPORTED_ENCAP:
4495 simple_error_message_box(
4496 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
4501 case WTAP_ERR_CANT_READ:
4502 simple_error_message_box(
4503 "An attempt to read from the capture file failed for"
4504 " some unknown reason.");
4507 case WTAP_ERR_SHORT_READ:
4508 simple_error_message_box(
4509 "The capture file appears to have been cut short"
4510 " in the middle of a packet.");
4513 case WTAP_ERR_BAD_FILE:
4514 simple_error_message_box(
4515 "The capture file appears to be damaged or corrupt.\n(%s)",
4520 case WTAP_ERR_DECOMPRESS:
4521 simple_error_message_box(
4522 "The compressed capture file appears to be damaged or corrupt.\n"
4528 simple_error_message_box(
4529 "An error occurred while reading the"
4530 " capture file: %s.", wtap_strerror(*err));
4533 return CF_READ_ERROR;
4539 cf_save_packets(capture_file *cf, const char *fname, guint save_format,
4540 gboolean compressed, gboolean discard_comments,
4541 gboolean dont_reopen)
4544 gchar *fname_new = NULL;
4547 addrinfo_lists_t *addr_lists;
4551 gchar *display_basename;
4558 save_callback_args_t callback_args;
4560 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4562 addr_lists = get_addrinfo_list();
4564 if (save_format == cf->cd_t && compressed == cf->iscompressed
4565 && !discard_comments && !cf->unsaved_changes
4566 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4567 /* We're saving in the format it's already in, and we're
4568 not discarding comments, and there are no changes we have
4569 in memory that aren't saved to the file, and we have no name
4570 resolution blocks to write, so we can just move or copy the raw data. */
4572 if (cf->is_tempfile) {
4573 /* The file being saved is a temporary file from a live
4574 capture, so it doesn't need to stay around under that name;
4575 first, try renaming the capture buffer file to the new name.
4576 This acts as a "safe save", in that, if the file already
4577 exists, the existing file will be removed only if the rename
4580 Sadly, on Windows, as we have the current capture file
4581 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4582 (to cause the rename to remove an existing target), as
4583 done by ws_stdio_rename() (ws_rename() is #defined to
4584 be ws_stdio_rename() on Windows) will fail.
4586 According to the MSDN documentation for CreateFile(), if,
4587 when we open a capture file, we were to directly do a CreateFile(),
4588 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4589 convert it to a file descriptor with _open_osfhandle(),
4590 that would allow the file to be renamed out from under us.
4592 However, that doesn't work in practice. Perhaps the problem
4593 is that the process doing the rename is the process that
4594 has the file open. */
4596 if (ws_rename(cf->filename, fname) == 0) {
4597 /* That succeeded - there's no need to copy the source file. */
4598 how_to_save = SAVE_WITH_MOVE;
4600 if (errno == EXDEV) {
4601 /* They're on different file systems, so we have to copy the
4603 how_to_save = SAVE_WITH_COPY;
4605 /* The rename failed, but not because they're on different
4606 file systems - put up an error message. (Or should we
4607 just punt and try to copy? The only reason why I'd
4608 expect the rename to fail and the copy to succeed would
4609 be if we didn't have permission to remove the file from
4610 the temporary directory, and that might be fixable - but
4611 is it worth requiring the user to go off and fix it?) */
4612 cf_rename_failure_alert_box(fname, errno);
4617 how_to_save = SAVE_WITH_COPY;
4620 /* It's a permanent file, so we should copy it, and not remove the
4622 how_to_save = SAVE_WITH_COPY;
4625 if (how_to_save == SAVE_WITH_COPY) {
4626 /* Copy the file, if we haven't moved it. If we're overwriting
4627 an existing file, we do it with a "safe save", by writing
4628 to a new file and, if the write succeeds, renaming the
4629 new file on top of the old file. */
4630 if (file_exists(fname)) {
4631 fname_new = g_strdup_printf("%s~", fname);
4632 if (!copy_file_binary_mode(cf->filename, fname_new))
4635 if (!copy_file_binary_mode(cf->filename, fname))
4640 /* Either we're saving in a different format or we're saving changes,
4641 such as added, modified, or removed comments, that haven't yet
4642 been written to the underlying file; we can't do that by copying
4643 or moving the capture file, we have to do it by writing the packets
4646 wtapng_section_t *shb_hdr = NULL;
4647 wtapng_iface_descriptions_t *idb_inf = NULL;
4650 shb_hdr = wtap_file_get_shb_info(cf->wth);
4651 idb_inf = wtap_file_get_idb_info(cf->wth);
4653 /* Determine what file encapsulation type we should use. */
4654 encap = wtap_dump_file_encap_type(cf->linktypes);
4656 if (file_exists(fname)) {
4657 /* We're overwriting an existing file; write out to a new file,
4658 and, if that succeeds, rename the new file on top of the
4659 old file. That makes this a "safe save", so that we don't
4660 lose the old file if we have a problem writing out the new
4661 file. (If the existing file is the current capture file,
4662 we *HAVE* to do that, otherwise we're overwriting the file
4663 from which we're reading the packets that we're writing!) */
4664 fname_new = g_strdup_printf("%s~", fname);
4665 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4666 compressed, shb_hdr, idb_inf, &err);
4668 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4669 compressed, shb_hdr, idb_inf, &err);
4675 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4679 /* Add address resolution */
4680 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4682 /* Iterate through the list of packets, processing all the packets. */
4683 callback_args.pdh = pdh;
4684 callback_args.fname = fname;
4685 callback_args.file_type = save_format;
4686 switch (process_specified_packets(cf, NULL, "Saving", "packets",
4687 TRUE, save_packet, &callback_args)) {
4690 /* Completed successfully. */
4694 /* The user decided to abort the saving.
4695 If we're writing to a temporary file, remove it.
4696 XXX - should we do so even if we're not writing to a
4698 wtap_dump_close(pdh, &err);
4699 if (fname_new != NULL)
4700 ws_unlink(fname_new);
4701 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4702 return CF_WRITE_ABORTED;
4705 /* Error while saving.
4706 If we're writing to a temporary file, remove it. */
4707 if (fname_new != NULL)
4708 ws_unlink(fname_new);
4709 wtap_dump_close(pdh, &err);
4713 if (!wtap_dump_close(pdh, &err)) {
4714 cf_close_failure_alert_box(fname, err);
4718 how_to_save = SAVE_WITH_WTAP;
4721 if (fname_new != NULL) {
4722 /* We wrote out to fname_new, and should rename it on top of
4723 fname. fname_new is now closed, so that should be possible even
4724 on Windows. However, on Windows, we first need to close whatever
4725 file descriptors we have open for fname. */
4727 wtap_fdclose(cf->wth);
4729 /* Now do the rename. */
4730 if (ws_rename(fname_new, fname) == -1) {
4731 /* Well, the rename failed. */
4732 cf_rename_failure_alert_box(fname, errno);
4734 /* Attempt to reopen the random file descriptor using the
4735 current file's filename. (At this point, the sequential
4736 file descriptor is closed.) */
4737 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4738 /* Oh, well, we're screwed. */
4739 display_basename = g_filename_display_basename(cf->filename);
4740 simple_error_message_box(
4741 file_open_error_message(err, FALSE), display_basename);
4742 g_free(display_basename);
4749 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4750 cf->unsaved_changes = FALSE;
4753 switch (how_to_save) {
4755 case SAVE_WITH_MOVE:
4756 /* We just moved the file, so the wtap structure refers to the
4757 new file, and all the information other than the filename
4758 and the "is temporary" status applies to the new file; just
4760 g_free(cf->filename);
4761 cf->filename = g_strdup(fname);
4762 cf->is_tempfile = FALSE;
4763 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4766 case SAVE_WITH_COPY:
4767 /* We just copied the file, s all the information other than
4768 the wtap structure, the filename, and the "is temporary"
4769 status applies to the new file; just update that. */
4770 wtap_close(cf->wth);
4771 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4772 if (cf->wth == NULL) {
4773 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4776 g_free(cf->filename);
4777 cf->filename = g_strdup(fname);
4778 cf->is_tempfile = FALSE;
4780 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4783 case SAVE_WITH_WTAP:
4784 /* Open and read the file we saved to.
4786 XXX - this is somewhat of a waste; we already have the
4787 packets, all this gets us is updated file type information
4788 (which we could just stuff into "cf"), and having the new
4789 file be the one we have opened and from which we're reading
4790 the data, and it means we have to spend time opening and
4791 reading the file, which could be a significant amount of
4792 time if the file is large.
4794 If the capture-file-writing code were to return the
4795 seek offset of each packet it writes, we could save that
4796 in the frame_data structure for the frame, and just open
4797 the file without reading it again...
4799 ...as long as, for gzipped files, the process of writing
4800 out the file *also* generates the information needed to
4801 support fast random access to the compressed file. */
4802 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4803 /* The rescan failed; just close the file. Either
4804 a dialog was popped up for the failure, so the
4805 user knows what happened, or they stopped the
4806 rescan, in which case they know what happened. */
4812 /* If we were told to discard the comments, do so. */
4813 if (discard_comments) {
4814 /* Remove SHB comment, if any. */
4815 wtap_write_shb_comment(cf->wth, NULL);
4817 /* remove all user comments */
4818 for (framenum = 1; framenum <= cf->count; framenum++) {
4819 fdata = frame_data_sequence_find(cf->frames, framenum);
4821 fdata->flags.has_phdr_comment = FALSE;
4822 fdata->flags.has_user_comment = FALSE;
4825 if (cf->frames_user_comments) {
4826 g_tree_destroy(cf->frames_user_comments);
4827 cf->frames_user_comments = NULL;
4830 cf->packet_comment_count = 0;
4836 if (fname_new != NULL) {
4837 /* We were trying to write to a temporary file; get rid of it if it
4838 exists. (We don't care whether this fails, as, if it fails,
4839 there's not much we can do about it. I guess if it failed for
4840 a reason other than "it doesn't exist", we could report an
4841 error, so the user knows there's a junk file that they might
4842 want to clean up.) */
4843 ws_unlink(fname_new);
4846 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4847 return CF_WRITE_ERROR;
4851 cf_export_specified_packets(capture_file *cf, const char *fname,
4852 packet_range_t *range, guint save_format,
4853 gboolean compressed)
4855 gchar *fname_new = NULL;
4858 save_callback_args_t callback_args;
4859 wtapng_section_t *shb_hdr;
4860 wtapng_iface_descriptions_t *idb_inf;
4863 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4865 packet_range_process_init(range);
4867 /* We're writing out specified packets from the specified capture
4868 file to another file. Even if all captured packets are to be
4869 written, don't special-case the operation - read each packet
4870 and then write it out if it's one of the specified ones. */
4872 shb_hdr = wtap_file_get_shb_info(cf->wth);
4873 idb_inf = wtap_file_get_idb_info(cf->wth);
4875 /* Determine what file encapsulation type we should use. */
4876 encap = wtap_dump_file_encap_type(cf->linktypes);
4878 if (file_exists(fname)) {
4879 /* We're overwriting an existing file; write out to a new file,
4880 and, if that succeeds, rename the new file on top of the
4881 old file. That makes this a "safe save", so that we don't
4882 lose the old file if we have a problem writing out the new
4883 file. (If the existing file is the current capture file,
4884 we *HAVE* to do that, otherwise we're overwriting the file
4885 from which we're reading the packets that we're writing!) */
4886 fname_new = g_strdup_printf("%s~", fname);
4887 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4888 compressed, shb_hdr, idb_inf, &err);
4890 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4891 compressed, shb_hdr, idb_inf, &err);
4897 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4901 /* Add address resolution */
4902 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4904 /* Iterate through the list of packets, processing the packets we were
4907 XXX - we've already called "packet_range_process_init(range)", but
4908 "process_specified_packets()" will do it again. Fortunately,
4909 that's harmless in this case, as we haven't done anything to
4910 "range" since we initialized it. */
4911 callback_args.pdh = pdh;
4912 callback_args.fname = fname;
4913 callback_args.file_type = save_format;
4914 switch (process_specified_packets(cf, range, "Writing", "specified packets",
4915 TRUE, save_packet, &callback_args)) {
4918 /* Completed successfully. */
4922 /* The user decided to abort the saving.
4923 If we're writing to a temporary file, remove it.
4924 XXX - should we do so even if we're not writing to a
4926 wtap_dump_close(pdh, &err);
4927 if (fname_new != NULL)
4928 ws_unlink(fname_new);
4929 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4930 return CF_WRITE_ABORTED;
4934 /* Error while saving.
4935 If we're writing to a temporary file, remove it. */
4936 if (fname_new != NULL)
4937 ws_unlink(fname_new);
4938 wtap_dump_close(pdh, &err);
4942 if (!wtap_dump_close(pdh, &err)) {
4943 cf_close_failure_alert_box(fname, err);
4947 if (fname_new != NULL) {
4948 /* We wrote out to fname_new, and should rename it on top of
4949 fname; fname is now closed, so that should be possible even
4950 on Windows. Do the rename. */
4951 if (ws_rename(fname_new, fname) == -1) {
4952 /* Well, the rename failed. */
4953 cf_rename_failure_alert_box(fname, errno);
4958 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4962 if (fname_new != NULL) {
4963 /* We were trying to write to a temporary file; get rid of it if it
4964 exists. (We don't care whether this fails, as, if it fails,
4965 there's not much we can do about it. I guess if it failed for
4966 a reason other than "it doesn't exist", we could report an
4967 error, so the user knows there's a junk file that they might
4968 want to clean up.) */
4969 ws_unlink(fname_new);
4972 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4973 return CF_WRITE_ERROR;
4977 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4978 gboolean for_writing, int file_type)
4980 gchar *display_basename;
4983 /* Wiretap error. */
4984 display_basename = g_filename_display_basename(filename);
4987 case WTAP_ERR_NOT_REGULAR_FILE:
4988 simple_error_message_box(
4989 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4993 case WTAP_ERR_RANDOM_OPEN_PIPE:
4994 /* Seen only when opening a capture file for reading. */
4995 simple_error_message_box(
4996 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4997 "To capture from a pipe or FIFO use wireshark -i -",
5001 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
5002 /* Seen only when opening a capture file for reading. */
5003 simple_error_message_box(
5004 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
5008 case WTAP_ERR_UNSUPPORTED:
5009 /* Seen only when opening a capture file for reading. */
5010 simple_error_message_box(
5011 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
5013 display_basename, err_info);
5017 case WTAP_ERR_CANT_WRITE_TO_PIPE:
5018 /* Seen only when opening a capture file for writing. */
5019 simple_error_message_box(
5020 "The file \"%s\" is a pipe, and %s capture files can't be "
5021 "written to a pipe.",
5022 display_basename, wtap_file_type_subtype_string(file_type));
5025 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
5026 /* Seen only when opening a capture file for writing. */
5027 simple_error_message_box(
5028 "Wireshark doesn't support writing capture files in that format.");
5031 case WTAP_ERR_UNSUPPORTED_ENCAP:
5033 simple_error_message_box("Wireshark can't save this capture in that format.");
5035 simple_error_message_box(
5036 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
5038 display_basename, err_info);
5043 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
5045 simple_error_message_box(
5046 "Wireshark can't save this capture in that format.");
5048 simple_error_message_box(
5049 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
5054 case WTAP_ERR_BAD_FILE:
5055 /* Seen only when opening a capture file for reading. */
5056 simple_error_message_box(
5057 "The file \"%s\" appears to be damaged or corrupt.\n"
5059 display_basename, err_info);
5063 case WTAP_ERR_CANT_OPEN:
5065 simple_error_message_box(
5066 "The file \"%s\" could not be created for some unknown reason.",
5069 simple_error_message_box(
5070 "The file \"%s\" could not be opened for some unknown reason.",
5075 case WTAP_ERR_SHORT_READ:
5076 simple_error_message_box(
5077 "The file \"%s\" appears to have been cut short"
5078 " in the middle of a packet or other data.",
5082 case WTAP_ERR_SHORT_WRITE:
5083 simple_error_message_box(
5084 "A full header couldn't be written to the file \"%s\".",
5088 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
5089 simple_error_message_box(
5090 "This file type cannot be written as a compressed file.");
5093 case WTAP_ERR_DECOMPRESS:
5094 simple_error_message_box(
5095 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
5096 "(%s)", display_basename, err_info);
5101 simple_error_message_box(
5102 "The file \"%s\" could not be %s: %s.",
5104 for_writing ? "created" : "opened",
5105 wtap_strerror(err));
5108 g_free(display_basename);
5111 open_failure_alert_box(filename, err, for_writing);
5116 * XXX - whether we mention the source pathname, the target pathname,
5117 * or both depends on the error and on what we find if we look for
5118 * one or both of them.
5121 cf_rename_failure_alert_box(const char *filename, int err)
5123 gchar *display_basename;
5125 display_basename = g_filename_display_basename(filename);
5129 /* XXX - should check whether the source exists and, if not,
5130 report it as the problem and, if so, report the destination
5132 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
5137 /* XXX - if we're doing a rename after a safe save, we should
5138 probably say something else. */
5139 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
5144 /* XXX - this should probably mention both the source and destination
5146 simple_error_message_box("The file \"%s\" could not be moved: %s.",
5147 display_basename, wtap_strerror(err));
5150 g_free(display_basename);
5153 /* Check for write errors - if the file is being written to an NFS server,
5154 a write error may not show up until the file is closed, as NFS clients
5155 might not send writes to the server until the "write()" call finishes,
5156 so that the write may fail on the server but the "write()" may succeed. */
5158 cf_close_failure_alert_box(const char *filename, int err)
5160 gchar *display_basename;
5163 /* Wiretap error. */
5164 display_basename = g_filename_display_basename(filename);
5167 case WTAP_ERR_CANT_CLOSE:
5168 simple_error_message_box(
5169 "The file \"%s\" couldn't be closed for some unknown reason.",
5173 case WTAP_ERR_SHORT_WRITE:
5174 simple_error_message_box(
5175 "Not all the packets could be written to the file \"%s\".",
5180 simple_error_message_box(
5181 "An error occurred while closing the file \"%s\": %s.",
5182 display_basename, wtap_strerror(err));
5185 g_free(display_basename);
5188 We assume that a close error from the OS is really a write error. */
5189 write_failure_alert_box(filename, err);
5193 /* Reload the current capture file. */
5195 cf_reload(capture_file *cf) {
5197 gboolean is_tempfile;
5200 /* If the file could be opened, "cf_open()" calls "cf_close()"
5201 to get rid of state for the old capture file before filling in state
5202 for the new capture file. "cf_close()" will remove the file if
5203 it's a temporary file; we don't want that to happen (for one thing,
5204 it'd prevent subsequent reopens from working). Remember whether it's
5205 a temporary file, mark it as not being a temporary file, and then
5206 reopen it as the type of file it was.
5208 Also, "cf_close()" will free "cf->filename", so we must make
5209 a copy of it first. */
5210 filename = g_strdup(cf->filename);
5211 is_tempfile = cf->is_tempfile;
5212 cf->is_tempfile = FALSE;
5213 if (cf_open(cf, filename, WTAP_TYPE_AUTO, is_tempfile, &err) == CF_OK) {
5214 switch (cf_read(cf, TRUE)) {
5218 /* Just because we got an error, that doesn't mean we were unable
5219 to read any of the file; we handle what we could get from the
5223 case CF_READ_ABORTED:
5224 /* The user bailed out of re-reading the capture file; the
5225 capture file has been closed - just free the capture file name
5226 string and return (without changing the last containing
5232 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5233 Instead, the file was left open, so we should restore "cf->is_tempfile"
5236 XXX - change the menu? Presumably "cf_open()" will do that;
5237 make sure it does! */
5238 cf->is_tempfile = is_tempfile;
5240 /* "cf_open()" made a copy of the file name we handed it, so
5241 we should free up our copy. */
5251 * indent-tabs-mode: nil
5254 * ex: set shiftwidth=2 tabstop=8 expandtab:
5255 * :indentSize=2:tabSize=8:noTabs=true: