4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
42 #include <wsutil/tempfile.h>
43 #include <wsutil/file_util.h>
44 #include <wsutil/filesystem.h>
45 #include <wsutil/ws_version_info.h>
47 #include <wiretap/merge.h>
49 #include <epan/exceptions.h>
50 #include <epan/epan-int.h>
51 #include <epan/epan.h>
52 #include <epan/column.h>
53 #include <epan/packet.h>
54 #include <epan/column-utils.h>
55 #include <epan/expert.h>
56 #include <epan/prefs.h>
57 #include <epan/dfilter/dfilter.h>
58 #include <epan/epan_dissect.h>
60 #include <epan/dissectors/packet-data.h>
61 #include <epan/dissectors/packet-ber.h>
62 #include <epan/timestamp.h>
63 #include <epan/dfilter/dfilter-macro.h>
64 #include <epan/strutil.h>
65 #include <epan/addr_resolv.h>
68 #include "color_filters.h"
72 #include "frame_tvbuff.h"
74 #include "ui/alert_box.h"
75 #include "ui/simple_dialog.h"
76 #include "ui/main_statusbar.h"
77 #include "ui/progress_dlg.h"
78 #include "ui/ui_util.h"
80 /* Needed for addrinfo */
81 #ifdef HAVE_SYS_TYPES_H
82 # include <sys/types.h>
85 #ifdef HAVE_SYS_SOCKET_H
86 #include <sys/socket.h>
89 #ifdef HAVE_NETINET_IN_H
90 # include <netinet/in.h>
97 #ifdef HAVE_WINSOCK2_H
98 # include <winsock2.h>
101 #if defined(_WIN32) && defined(INET6)
102 # include <ws2tcpip.h>
106 gboolean auto_scroll_live;
109 static void cf_reset_state(capture_file *cf);
111 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
112 column_info *cinfo, gint64 offset);
114 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
121 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
123 static void match_subtree_text(proto_node *node, gpointer data);
124 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
126 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
128 static match_result match_narrow(capture_file *cf, frame_data *fdata,
130 static match_result match_wide(capture_file *cf, frame_data *fdata,
132 static match_result match_binary(capture_file *cf, frame_data *fdata,
134 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
136 static match_result match_marked(capture_file *cf, frame_data *fdata,
138 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
140 static gboolean find_packet(capture_file *cf,
141 match_result (*match_function)(capture_file *, frame_data *, void *),
142 void *criterion, search_direction dir);
144 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
146 static void cf_open_failure_alert_box(const char *filename, int err,
147 gchar *err_info, gboolean for_writing,
149 static void cf_rename_failure_alert_box(const char *filename, int err);
150 static void cf_close_failure_alert_box(const char *filename, int err);
151 static void ref_time_packets(capture_file *cf);
152 /* Update the progress bar this many times when reading a file. */
153 #define N_PROGBAR_UPDATES 100
154 /* We read around 200k/100ms don't update the progress bar more often than that */
155 #define MIN_QUANTUM 200000
156 #define MIN_NUMBER_OF_PACKET 1500
159 * We could probably use g_signal_...() instead of the callbacks below but that
160 * would require linking our CLI programs to libgobject and creating an object
161 * instance for the signals.
164 cf_callback_t cb_fct;
166 } cf_callback_data_t;
168 static GList *cf_callbacks = NULL;
171 cf_callback_invoke(int event, gpointer data)
173 cf_callback_data_t *cb;
174 GList *cb_item = cf_callbacks;
176 /* there should be at least one interested */
177 g_assert(cb_item != NULL);
179 while (cb_item != NULL) {
180 cb = (cf_callback_data_t *)cb_item->data;
181 cb->cb_fct(event, data, cb->user_data);
182 cb_item = g_list_next(cb_item);
188 cf_callback_add(cf_callback_t func, gpointer user_data)
190 cf_callback_data_t *cb;
192 cb = g_new(cf_callback_data_t,1);
194 cb->user_data = user_data;
196 cf_callbacks = g_list_prepend(cf_callbacks, cb);
200 cf_callback_remove(cf_callback_t func)
202 cf_callback_data_t *cb;
203 GList *cb_item = cf_callbacks;
205 while (cb_item != NULL) {
206 cb = (cf_callback_data_t *)cb_item->data;
207 if (cb->cb_fct == func) {
208 cf_callbacks = g_list_remove(cf_callbacks, cb);
212 cb_item = g_list_next(cb_item);
215 g_assert_not_reached();
219 cf_timestamp_auto_precision(capture_file *cf)
222 int prec = timestamp_get_precision();
225 /* don't try to get the file's precision if none is opened */
226 if (cf->state == FILE_CLOSED) {
230 /* if we are in auto mode, set precision of current file */
231 if (prec == TS_PREC_AUTO ||
232 prec == TS_PREC_AUTO_SEC ||
233 prec == TS_PREC_AUTO_DSEC ||
234 prec == TS_PREC_AUTO_CSEC ||
235 prec == TS_PREC_AUTO_MSEC ||
236 prec == TS_PREC_AUTO_USEC ||
237 prec == TS_PREC_AUTO_NSEC)
239 switch(wtap_file_tsprecision(cf->wth)) {
240 case(WTAP_FILE_TSPREC_SEC):
241 timestamp_set_precision(TS_PREC_AUTO_SEC);
243 case(WTAP_FILE_TSPREC_DSEC):
244 timestamp_set_precision(TS_PREC_AUTO_DSEC);
246 case(WTAP_FILE_TSPREC_CSEC):
247 timestamp_set_precision(TS_PREC_AUTO_CSEC);
249 case(WTAP_FILE_TSPREC_MSEC):
250 timestamp_set_precision(TS_PREC_AUTO_MSEC);
252 case(WTAP_FILE_TSPREC_USEC):
253 timestamp_set_precision(TS_PREC_AUTO_USEC);
255 case(WTAP_FILE_TSPREC_NSEC):
256 timestamp_set_precision(TS_PREC_AUTO_NSEC);
259 g_assert_not_reached();
262 /* Set the column widths of those columns that show the time in
263 "command-line-specified" format. */
264 for (i = 0; i < cf->cinfo.num_cols; i++) {
265 if (col_has_time_fmt(&cf->cinfo, i)) {
266 packet_list_resize_column(i);
272 cf_get_computed_elapsed(capture_file *cf)
274 return cf->computed_elapsed;
278 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
281 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
286 g_get_current_time(&time_now);
288 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
289 time_now.tv_usec - start_time->tv_usec;
291 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
294 static const nstime_t *
295 ws_get_frame_ts(void *data, guint32 frame_num)
297 capture_file *cf = (capture_file *) data;
299 if (cf->prev_dis && cf->prev_dis->num == frame_num)
300 return &cf->prev_dis->abs_ts;
302 if (cf->prev_cap && cf->prev_cap->num == frame_num)
303 return &cf->prev_cap->abs_ts;
306 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
308 return (fd) ? &fd->abs_ts : NULL;
315 ws_get_user_comment(void *data, const frame_data *fd)
317 capture_file *cf = (capture_file *) data;
319 return cf_get_user_packet_comment(cf, fd);
323 ws_epan_new(capture_file *cf)
325 epan_t *epan = epan_new();
328 epan->get_frame_ts = ws_get_frame_ts;
329 epan->get_interface_name = cap_file_get_interface_name;
330 epan->get_user_comment = ws_get_user_comment;
336 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
341 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
345 /* The open succeeded. Close whatever capture file we had open,
346 and fill in the information for this file. */
349 /* XXX - we really want to initialize this after we've read all
350 the packets, so we know how much we'll ultimately need. */
351 buffer_init(&cf->buf, 1500);
353 /* Create new epan session for dissection.
354 * (The old one was freed in cf_close().)
356 cf->epan = ws_epan_new(cf);
358 /* We're about to start reading the file. */
359 cf->state = FILE_READ_IN_PROGRESS;
364 /* Set the file name because we need it to set the follow stream filter.
365 XXX - is that still true? We need it for other reasons, though,
367 cf->filename = g_strdup(fname);
369 /* Indicate whether it's a permanent or temporary file. */
370 cf->is_tempfile = is_tempfile;
372 /* No user changes yet. */
373 cf->unsaved_changes = FALSE;
375 cf->computed_elapsed = 0;
377 cf->cd_t = wtap_file_type_subtype(cf->wth);
378 cf->open_type = type;
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 /* no open_routine type */
474 cf->open_type = WTAP_TYPE_AUTO;
476 /* Free up the packet buffer. */
477 buffer_free(&cf->buf);
479 dfilter_free(cf->rfcode);
481 if (cf->frames != NULL) {
482 free_frame_data_sequence(cf->frames);
485 #ifdef WANT_PACKET_EDITOR
486 if (cf->edited_frames) {
487 g_tree_destroy(cf->edited_frames);
488 cf->edited_frames = NULL;
491 if (cf->frames_user_comments) {
492 g_tree_destroy(cf->frames_user_comments);
493 cf->frames_user_comments = NULL;
495 cf_unselect_packet(cf); /* nothing to select */
496 cf->first_displayed = 0;
497 cf->last_displayed = 0;
499 /* No frames, no frame selected, no field in that frame selected. */
501 cf->current_frame = 0;
503 cf->finfo_selected = NULL;
505 /* No frame link-layer types, either. */
506 g_array_free(cf->linktypes, TRUE);
507 cf->linktypes = NULL;
509 /* Clear the packet list. */
510 packet_list_freeze();
515 nstime_set_zero(&cf->elapsed_time);
517 reset_tap_listeners();
519 /* We have no file open. */
520 cf->state = FILE_CLOSED;
523 /* Reset everything to a pristine state */
525 cf_close(capture_file *cf)
527 if (cf->state != FILE_CLOSED) {
528 cf_callback_invoke(cf_cb_file_closing, cf);
530 /* close things, if not already closed before */
531 color_filters_cleanup();
536 cf_callback_invoke(cf_cb_file_closed, cf);
541 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
545 progbar_val = (gfloat) file_pos / (gfloat) size;
546 if (progbar_val > 1.0) {
548 /* The file probably grew while we were reading it.
549 * Update file size, and try again.
551 size = wtap_file_size(cf->wth, NULL);
554 progbar_val = (gfloat) file_pos / (gfloat) size;
556 /* If it's still > 1, either "wtap_file_size()" failed (in which
557 * case there's not much we can do about it), or the file
558 * *shrank* (in which case there's not much we can do about
559 * it); just clip the progress value at 1.0.
561 if (progbar_val > 1.0f)
565 g_snprintf(status_str, status_size,
566 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
567 file_pos / 1024, size / 1024);
573 cf_read(capture_file *cf, gboolean reloading)
578 progdlg_t *progbar = NULL;
583 volatile gboolean create_proto_tree;
587 /* Compile the current display filter.
588 * We assume this will not fail since cf->dfilter is only set in
589 * cf_filter IFF the filter was valid.
591 compiled = dfilter_compile(cf->dfilter, &dfcode);
592 g_assert(!cf->dfilter || (compiled && dfcode));
594 /* Get the union of the flags for all tap listeners. */
595 tap_flags = union_of_tap_listener_flags();
597 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
599 reset_tap_listeners();
601 name_ptr = g_filename_display_basename(cf->filename);
604 cf_callback_invoke(cf_cb_file_reload_started, cf);
606 cf_callback_invoke(cf_cb_file_read_started, cf);
608 /* Record whether the file is compressed.
609 XXX - do we know this at open time? */
610 cf->iscompressed = wtap_iscompressed(cf->wth);
612 /* The packet list window will be empty until the file is completly loaded */
613 packet_list_freeze();
616 g_get_current_time(&start_time);
618 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
622 int displayed_once = 0;
630 gint64 progbar_quantum;
631 gint64 progbar_nextstep;
633 gchar status_str[100];
637 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
639 /* Find the size of the file. */
640 size = wtap_file_size(cf->wth, NULL);
642 /* Update the progress bar when it gets to this value. */
643 progbar_nextstep = 0;
644 /* When we reach the value that triggers a progress bar update,
645 bump that value by this amount. */
647 progbar_quantum = size/N_PROGBAR_UPDATES;
648 if (progbar_quantum < MIN_QUANTUM)
649 progbar_quantum = MIN_QUANTUM;
653 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
656 file_pos = wtap_read_so_far(cf->wth);
658 /* Create the progress bar if necessary.
659 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
661 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
662 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
664 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
665 TRUE, &stop_flag, &start_time, progbar_val);
667 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
668 TRUE, &stop_flag, &start_time, progbar_val);
671 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
672 when we update it, we have to run the GTK+ main loop to get it
673 to repaint what's pending, and doing so may involve an "ioctl()"
674 to see if there's any pending input from an X server, and doing
675 that for every packet can be costly, especially on a big file. */
676 if (file_pos >= progbar_nextstep) {
677 if (progbar != NULL) {
678 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
679 /* update the packet bar content on the first run or frequently on very large files */
681 if (progbar_quantum > 500000 || displayed_once == 0) {
682 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
684 packets_bar_update();
687 #endif /* HAVE_LIBPCAP */
688 update_progress_dlg(progbar, progbar_val, status_str);
690 progbar_nextstep += progbar_quantum;
695 /* Well, the user decided to abort the read. He/She will be warned and
696 it might be enough for him/her to work with the already loaded
698 This is especially true for very large capture files, where you don't
699 want to wait loading the whole file (which may last minutes or even
700 hours even on fast machines) just to see that it was the wrong file. */
703 read_packet(cf, dfcode, &edt, cinfo, data_offset);
706 CATCH(OutOfMemoryError) {
707 simple_message_box(ESD_TYPE_ERROR, NULL,
708 "Some infos / workarounds can be found at:\n"
709 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
710 "Sorry, but Wireshark has run out of memory and has to terminate now!");
712 /* Could we close the current capture and free up memory from that? */
714 /* we have to terminate, as we cannot recover from the memory error */
720 /* Free the display name */
723 /* Cleanup and release all dfilter resources */
724 if (dfcode != NULL) {
725 dfilter_free(dfcode);
728 epan_dissect_cleanup(&edt);
730 /* We're done reading the file; destroy the progress bar if it was created. */
732 destroy_progress_dlg(progbar);
734 /* We're done reading sequentially through the file. */
735 cf->state = FILE_READ_DONE;
737 /* Close the sequential I/O side, to free up memory it requires. */
738 wtap_sequential_close(cf->wth);
740 /* Allow the protocol dissectors to free up memory that they
741 * don't need after the sequential run-through of the packets. */
742 postseq_cleanup_all_protocols();
744 /* compute the time it took to load the file */
745 compute_elapsed(cf, &start_time);
747 /* Set the file encapsulation type now; we don't know what it is until
748 we've looked at all the packets, as we don't know until then whether
749 there's more than one type (and thus whether it's
750 WTAP_ENCAP_PER_PACKET). */
751 cf->lnk_t = wtap_file_encap(cf->wth);
753 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
758 cf_callback_invoke(cf_cb_file_reload_finished, cf);
760 cf_callback_invoke(cf_cb_file_read_finished, cf);
762 /* If we have any displayed packets to select, select the first of those
763 packets by making the first row the selected row. */
764 if (cf->first_displayed != 0) {
765 packet_list_select_first_row();
769 simple_message_box(ESD_TYPE_WARN, NULL,
770 "The remaining packets in the file were discarded.\n"
772 "As a lot of packets from the original file will be missing,\n"
773 "remember to be careful when saving the current content to a file.\n",
774 "File loading was cancelled!");
775 return CF_READ_ERROR;
779 /* Put up a message box noting that the read failed somewhere along
780 the line. Don't throw out the stuff we managed to read, though,
784 case WTAP_ERR_UNSUPPORTED:
785 simple_error_message_box(
786 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
791 case WTAP_ERR_UNSUPPORTED_ENCAP:
792 simple_error_message_box(
793 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
798 case WTAP_ERR_CANT_READ:
799 simple_error_message_box(
800 "An attempt to read from the capture file failed for"
801 " some unknown reason.");
804 case WTAP_ERR_SHORT_READ:
805 simple_error_message_box(
806 "The capture file appears to have been cut short"
807 " in the middle of a packet.");
810 case WTAP_ERR_BAD_FILE:
811 simple_error_message_box(
812 "The capture file appears to be damaged or corrupt.\n(%s)",
817 case WTAP_ERR_DECOMPRESS:
818 simple_error_message_box(
819 "The compressed capture file appears to be damaged or corrupt.\n"
825 simple_error_message_box(
826 "An error occurred while reading the"
827 " capture file: %s.", wtap_strerror(err));
830 return CF_READ_ERROR;
837 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
840 volatile int newly_displayed_packets = 0;
843 gboolean create_proto_tree;
847 /* Compile the current display filter.
848 * We assume this will not fail since cf->dfilter is only set in
849 * cf_filter IFF the filter was valid.
851 compiled = dfilter_compile(cf->dfilter, &dfcode);
852 g_assert(!cf->dfilter || (compiled && dfcode));
854 /* Get the union of the flags for all tap listeners. */
855 tap_flags = union_of_tap_listener_flags();
857 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
861 packet_list_check_end();
862 /* Don't freeze/thaw the list when doing live capture */
863 /*packet_list_freeze();*/
865 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
867 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
870 gint64 data_offset = 0;
873 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
875 while (to_read != 0) {
876 wtap_cleareof(cf->wth);
877 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
880 if (cf->state == FILE_READ_ABORTED) {
881 /* Well, the user decided to exit Wireshark. Break out of the
882 loop, and let the code below (which is called even if there
883 aren't any packets left to read) exit. */
886 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
887 newly_displayed_packets++;
892 CATCH(OutOfMemoryError) {
893 simple_message_box(ESD_TYPE_ERROR, NULL,
894 "Some infos / workarounds can be found at:\n"
895 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
896 "Sorry, but Wireshark has run out of memory and has to terminate now!");
898 /* Could we close the current capture and free up memory from that? */
899 return CF_READ_ABORTED;
901 /* we have to terminate, as we cannot recover from the memory error */
907 /* Update the file encapsulation; it might have changed based on the
908 packets we've read. */
909 cf->lnk_t = wtap_file_encap(cf->wth);
911 /* Cleanup and release all dfilter resources */
912 if (dfcode != NULL) {
913 dfilter_free(dfcode);
916 epan_dissect_cleanup(&edt);
918 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
919 cf->count, cf->state, *err);*/
921 /* Don't freeze/thaw the list when doing live capture */
922 /*packet_list_thaw();*/
923 /* With the new packet list the first packet
924 * isn't automatically selected.
926 if (!cf->current_frame)
927 packet_list_select_first_row();
929 /* moving to the end of the packet list - if the user requested so and
930 we have some new packets. */
931 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
932 packet_list_moveto_end();
934 if (cf->state == FILE_READ_ABORTED) {
935 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
936 so that our caller can kill off the capture child process;
937 this will cause an EOF on the pipe from the child, so
938 "cf_finish_tail()" will be called, and it will clean up
940 return CF_READ_ABORTED;
941 } else if (*err != 0) {
942 /* We got an error reading the capture file.
943 XXX - pop up a dialog box instead? */
944 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
945 wtap_strerror(*err), err_info, cf->filename);
948 return CF_READ_ERROR;
954 cf_fake_continue_tail(capture_file *cf) {
955 cf->state = FILE_READ_DONE;
959 cf_finish_tail(capture_file *cf, int *err)
966 gboolean create_proto_tree;
970 /* Compile the current display filter.
971 * We assume this will not fail since cf->dfilter is only set in
972 * cf_filter IFF the filter was valid.
974 compiled = dfilter_compile(cf->dfilter, &dfcode);
975 g_assert(!cf->dfilter || (compiled && dfcode));
977 /* Get the union of the flags for all tap listeners. */
978 tap_flags = union_of_tap_listener_flags();
979 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
981 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
983 if (cf->wth == NULL) {
985 return CF_READ_ERROR;
988 packet_list_check_end();
989 /* Don't freeze/thaw the list when doing live capture */
990 /*packet_list_freeze();*/
992 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
994 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
995 if (cf->state == FILE_READ_ABORTED) {
996 /* Well, the user decided to abort the read. Break out of the
997 loop, and let the code below (which is called even if there
998 aren't any packets left to read) exit. */
1001 read_packet(cf, dfcode, &edt, cinfo, data_offset);
1004 /* Cleanup and release all dfilter resources */
1005 if (dfcode != NULL) {
1006 dfilter_free(dfcode);
1009 epan_dissect_cleanup(&edt);
1011 /* Don't freeze/thaw the list when doing live capture */
1012 /*packet_list_thaw();*/
1014 if (cf->state == FILE_READ_ABORTED) {
1015 /* Well, the user decided to abort the read. We're only called
1016 when the child capture process closes the pipe to us (meaning
1017 it's probably exited), so we can just close the capture
1018 file; we return CF_READ_ABORTED so our caller can do whatever
1019 is appropriate when that happens. */
1021 return CF_READ_ABORTED;
1024 if (auto_scroll_live && cf->count != 0)
1025 packet_list_moveto_end();
1027 /* We're done reading sequentially through the file. */
1028 cf->state = FILE_READ_DONE;
1030 /* We're done reading sequentially through the file; close the
1031 sequential I/O side, to free up memory it requires. */
1032 wtap_sequential_close(cf->wth);
1034 /* Allow the protocol dissectors to free up memory that they
1035 * don't need after the sequential run-through of the packets. */
1036 postseq_cleanup_all_protocols();
1038 /* Update the file encapsulation; it might have changed based on the
1039 packets we've read. */
1040 cf->lnk_t = wtap_file_encap(cf->wth);
1042 /* Update the details in the file-set dialog, as the capture file
1043 * has likely grown since we first stat-ed it */
1044 fileset_update_file(cf->filename);
1047 /* We got an error reading the capture file.
1048 XXX - pop up a dialog box? */
1050 g_warning("Error \"%s\" while reading: \"%s\" (\"%s\")",
1051 wtap_strerror(*err), err_info, cf->filename);
1053 return CF_READ_ERROR;
1058 #endif /* HAVE_LIBPCAP */
1061 cf_get_display_name(capture_file *cf)
1065 /* Return a name to use in displays */
1066 if (!cf->is_tempfile) {
1067 /* Get the last component of the file name, and use that. */
1069 displayname = g_filename_display_basename(cf->filename);
1071 displayname=g_strdup("(No file)");
1074 /* The file we read is a temporary file from a live capture or
1075 a merge operation; we don't mention its name, but, if it's
1076 from a capture, give the source of the capture. */
1078 displayname = g_strdup(cf->source);
1080 displayname = g_strdup("(Untitled)");
1086 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1092 cf->source = g_strdup(source);
1094 cf->source = g_strdup("");
1098 const gchar *cf_get_tempfile_source(capture_file *cf) {
1106 /* XXX - use a macro instead? */
1108 cf_get_packet_count(capture_file *cf)
1113 /* XXX - use a macro instead? */
1115 cf_set_packet_count(capture_file *cf, int packet_count)
1117 cf->count = packet_count;
1120 /* XXX - use a macro instead? */
1122 cf_is_tempfile(capture_file *cf)
1124 return cf->is_tempfile;
1127 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1129 cf->is_tempfile = is_tempfile;
1133 /* XXX - use a macro instead? */
1134 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1136 cf->drops_known = drops_known;
1139 /* XXX - use a macro instead? */
1140 void cf_set_drops(capture_file *cf, guint32 drops)
1145 /* XXX - use a macro instead? */
1146 gboolean cf_get_drops_known(capture_file *cf)
1148 return cf->drops_known;
1151 /* XXX - use a macro instead? */
1152 guint32 cf_get_drops(capture_file *cf)
1157 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1159 cf->rfcode = rfcode;
1163 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1164 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1165 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1169 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1170 &cf->ref, cf->prev_dis);
1171 cf->prev_cap = fdata;
1173 if (dfcode != NULL) {
1174 epan_dissect_prime_dfilter(edt, dfcode);
1177 /* Dissect the frame. */
1178 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1180 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1181 if (dfcode != NULL) {
1182 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1184 if (fdata->flags.passed_dfilter) {
1185 /* This frame passed the display filter but it may depend on other
1186 * (potentially not displayed) frames. Find those frames and mark them
1189 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1192 fdata->flags.passed_dfilter = 1;
1194 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1195 cf->displayed_count++;
1197 if (add_to_packet_list) {
1198 /* We fill the needed columns from new_packet_list */
1199 row = packet_list_append(cinfo, fdata);
1202 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1204 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1205 cf->prev_dis = fdata;
1207 /* If we haven't yet seen the first frame, this is it.
1209 XXX - we must do this before we add the row to the display,
1210 as, if the display's GtkCList's selection mode is
1211 GTK_SELECTION_BROWSE, when the first entry is added to it,
1212 "cf_select_packet()" will be called, and it will fetch the row
1213 data for the 0th row, and will get a null pointer rather than
1214 "fdata", as "gtk_clist_append()" won't yet have returned and
1215 thus "gtk_clist_set_row_data()" won't yet have been called.
1217 We thus need to leave behind bread crumbs so that
1218 "cf_select_packet()" can find this frame. See the comment
1219 in "cf_select_packet()". */
1220 if (cf->first_displayed == 0)
1221 cf->first_displayed = fdata->num;
1223 /* This is the last frame we've seen so far. */
1224 cf->last_displayed = fdata->num;
1227 epan_dissect_reset(edt);
1231 /* read in a new packet */
1232 /* returns the row of the new packet in the packet list or -1 if not displayed */
1234 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1235 column_info *cinfo, gint64 offset)
1237 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1238 const guint8 *buf = wtap_buf_ptr(cf->wth);
1245 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1246 it's not already there.
1247 XXX - yes, this is O(N), so if every packet had a different
1248 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1249 there are probably going to be a small number of encapsulation types
1251 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1253 /* The frame number of this packet is one more than the count of
1254 frames in the file so far. */
1255 framenum = cf->count + 1;
1257 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1261 epan_dissect_t rf_edt;
1263 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1264 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1265 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1266 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1267 epan_dissect_cleanup(&rf_edt);
1271 /* This does a shallow copy of fdlocal, which is good enough. */
1272 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1275 if (phdr->opt_comment != NULL)
1276 cf->packet_comment_count++;
1277 cf->f_datalen = offset + fdlocal.cap_len;
1279 if (!cf->redissecting) {
1280 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1281 cinfo, phdr, buf, TRUE);
1289 cf_merge_files(char **out_filenamep, int in_file_count,
1290 char *const *in_filenames, int file_type, gboolean do_append)
1292 merge_in_file_t *in_files, *in_file;
1297 int open_err, read_err, write_err, close_err;
1301 gboolean got_read_error = FALSE, got_write_error = FALSE;
1303 progdlg_t *progbar = NULL;
1305 gint64 f_len, file_pos;
1307 GTimeVal start_time;
1308 gchar status_str[100];
1309 gint64 progbar_nextstep;
1310 gint64 progbar_quantum;
1311 gchar *display_basename;
1312 int selected_frame_type;
1313 gboolean fake_interface_ids = FALSE;
1315 /* open the input files */
1316 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1317 &open_err, &err_info, &err_fileno)) {
1319 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1324 if (*out_filenamep != NULL) {
1325 out_filename = *out_filenamep;
1326 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1330 out_fd = create_tempfile(&tmpname, "wireshark");
1333 out_filename = g_strdup(tmpname);
1334 *out_filenamep = out_filename;
1338 merge_close_in_files(in_file_count, in_files);
1340 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1344 selected_frame_type = merge_select_frame_type(in_file_count, in_files);
1346 /* If we are trying to merge a number of libpcap files with different encapsulation types
1347 * change the output file type to pcapng and create SHB and IDB:s for the new file use the
1348 * interface index stored in in_files per file to change the phdr before writing the datablock.
1349 * XXX should it be an option to convert to pcapng?
1351 * We need something similar when merging pcapng files possibly with an option to say
1352 * the same interface(s) used in all in files. SHBs comments should be merged together.
1354 if ((selected_frame_type == WTAP_ENCAP_PER_PACKET)&&(file_type == WTAP_FILE_TYPE_SUBTYPE_PCAP)) {
1355 /* Write output in pcapng format */
1356 wtapng_section_t *shb_hdr;
1357 wtapng_iface_descriptions_t *idb_inf, *idb_inf_merge_file;
1358 wtapng_if_descr_t int_data, *file_int_data;
1359 GString *comment_gstr;
1361 fake_interface_ids = TRUE;
1362 /* Create SHB info */
1363 shb_hdr = wtap_file_get_shb_info(in_files[0].wth);
1364 comment_gstr = g_string_new("");
1365 g_string_append_printf(comment_gstr, "%s \n",shb_hdr->opt_comment);
1366 g_string_append_printf(comment_gstr, "File created by merging: \n");
1367 file_type = WTAP_FILE_TYPE_SUBTYPE_PCAPNG;
1369 for (i = 0; i < in_file_count; i++) {
1370 g_string_append_printf(comment_gstr, "File%d: %s \n",i+1,in_files[i].filename);
1372 shb_hdr->section_length = -1;
1374 shb_hdr->opt_comment = g_string_free(comment_gstr, FALSE); /* NULL if not available */
1375 shb_hdr->shb_hardware = NULL; /* NULL if not available, UTF-8 string containing the */
1376 /* description of the hardware used to create this section. */
1377 shb_hdr->shb_os = NULL; /* NULL if not available, UTF-8 string containing the name */
1378 /* of the operating system used to create this section. */
1379 shb_hdr->shb_user_appl = "Wireshark"; /* NULL if not available, UTF-8 string containing the name */
1380 /* of the application used to create this section. */
1382 /* create fake IDB info */
1383 idb_inf = g_new(wtapng_iface_descriptions_t,1);
1384 /* TODO make this the number of DIFFERENT encapsulation types
1385 * check that snaplength is the same too?
1387 idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));
1389 for (i = 0; i < in_file_count; i++) {
1390 idb_inf_merge_file = wtap_file_get_idb_info(in_files[i].wth);
1391 /* read the interface data from the in file to our combined interfca data */
1392 file_int_data = &g_array_index (idb_inf_merge_file->interface_data, wtapng_if_descr_t, 0);
1393 int_data.wtap_encap = file_int_data->wtap_encap;
1394 int_data.time_units_per_second = file_int_data->time_units_per_second;
1395 int_data.link_type = file_int_data->link_type;
1396 int_data.snap_len = file_int_data->snap_len;
1397 int_data.if_name = g_strdup(file_int_data->if_name);
1398 int_data.opt_comment = NULL;
1399 int_data.if_description = NULL;
1400 int_data.if_speed = 0;
1401 int_data.if_tsresol = 6;
1402 int_data.if_filter_str = NULL;
1403 int_data.bpf_filter_len = 0;
1404 int_data.if_filter_bpf_bytes = NULL;
1405 int_data.if_os = NULL;
1406 int_data.if_fcslen = -1;
1407 int_data.num_stat_entries = 0; /* Number of ISB:s */
1408 int_data.interface_statistics = NULL;
1410 g_array_append_val(idb_inf->interface_data, int_data);
1411 g_free(idb_inf_merge_file);
1413 /* Set fake interface Id in per file data */
1414 in_files[i].interface_id = i;
1417 pdh = wtap_dump_fdopen_ng(out_fd, file_type,
1418 selected_frame_type,
1419 merge_max_snapshot_length(in_file_count, in_files),
1420 FALSE /* compressed */, shb_hdr, idb_inf /* wtapng_iface_descriptions_t *idb_inf */, &open_err);
1424 merge_close_in_files(in_file_count, in_files);
1426 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1433 pdh = wtap_dump_fdopen(out_fd, file_type,
1434 selected_frame_type,
1435 merge_max_snapshot_length(in_file_count, in_files),
1436 FALSE /* compressed */, &open_err);
1439 merge_close_in_files(in_file_count, in_files);
1441 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1447 /* Get the sum of the sizes of all the files. */
1449 for (i = 0; i < in_file_count; i++)
1450 f_len += in_files[i].size;
1452 /* Update the progress bar when it gets to this value. */
1453 progbar_nextstep = 0;
1454 /* When we reach the value that triggers a progress bar update,
1455 bump that value by this amount. */
1456 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1457 /* Progress so far. */
1461 g_get_current_time(&start_time);
1463 /* do the merge (or append) */
1466 in_file = merge_append_read_packet(in_file_count, in_files, &read_err,
1469 in_file = merge_read_packet(in_file_count, in_files, &read_err,
1471 if (in_file == NULL) {
1476 if (read_err != 0) {
1477 /* I/O error reading from in_file */
1478 got_read_error = TRUE;
1482 /* Get the sum of the data offsets in all of the files. */
1484 for (i = 0; i < in_file_count; i++)
1485 data_offset += in_files[i].data_offset;
1487 /* Create the progress bar if necessary.
1488 We check on every iteration of the loop, so that it takes no
1489 longer than the standard time to create it (otherwise, for a
1490 large file, we might take considerably longer than that standard
1491 time in order to get to the next progress bar step). */
1492 if (progbar == NULL) {
1493 progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1494 FALSE, &stop_flag, &start_time, progbar_val);
1497 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1498 when we update it, we have to run the GTK+ main loop to get it
1499 to repaint what's pending, and doing so may involve an "ioctl()"
1500 to see if there's any pending input from an X server, and doing
1501 that for every packet can be costly, especially on a big file. */
1502 if (data_offset >= progbar_nextstep) {
1503 /* Get the sum of the seek positions in all of the files. */
1505 for (i = 0; i < in_file_count; i++)
1506 file_pos += wtap_read_so_far(in_files[i].wth);
1507 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1508 if (progbar_val > 1.0f) {
1509 /* Some file probably grew while we were reading it.
1510 That "shouldn't happen", so we'll just clip the progress
1514 if (progbar != NULL) {
1515 g_snprintf(status_str, sizeof(status_str),
1516 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1517 file_pos / 1024, f_len / 1024);
1518 update_progress_dlg(progbar, progbar_val, status_str);
1520 progbar_nextstep += progbar_quantum;
1524 /* Well, the user decided to abort the merge. */
1528 /* If we have WTAP_ENCAP_PER_PACKET and the infiles are of type
1529 * WTAP_FILE_TYPE_SUBTYPE_PCAP, we need to set the interface id
1530 * in the paket header = the interface index we used in the IDBs
1531 * interface description for this file(encapsulation type).
1533 if (fake_interface_ids) {
1534 struct wtap_pkthdr *phdr;
1536 phdr = wtap_phdr(in_file->wth);
1537 phdr->interface_id = in_file->interface_id;
1538 phdr->presence_flags = phdr->presence_flags | WTAP_HAS_INTERFACE_ID;
1540 if (!wtap_dump(pdh, wtap_phdr(in_file->wth),
1541 wtap_buf_ptr(in_file->wth), &write_err)) {
1542 got_write_error = TRUE;
1547 /* We're done merging the files; destroy the progress bar if it was created. */
1548 if (progbar != NULL)
1549 destroy_progress_dlg(progbar);
1551 merge_close_in_files(in_file_count, in_files);
1552 if (!got_write_error) {
1553 if (!wtap_dump_close(pdh, &write_err))
1554 got_write_error = TRUE;
1557 * We already got a write error; no need to report another
1558 * write error on close.
1560 * Don't overwrite the earlier write error.
1562 (void)wtap_dump_close(pdh, &close_err);
1565 if (got_read_error) {
1567 * Find the file on which we got the error, and report the error.
1569 for (i = 0; i < in_file_count; i++) {
1570 if (in_files[i].state == GOT_ERROR) {
1571 /* Put up a message box noting that a read failed somewhere along
1573 display_basename = g_filename_display_basename(in_files[i].filename);
1576 case WTAP_ERR_UNSUPPORTED_ENCAP:
1577 simple_error_message_box(
1578 "The capture file %s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1579 display_basename, err_info);
1583 case WTAP_ERR_CANT_READ:
1584 simple_error_message_box(
1585 "An attempt to read from the capture file %s failed for"
1586 " some unknown reason.", display_basename);
1589 case WTAP_ERR_SHORT_READ:
1590 simple_error_message_box(
1591 "The capture file %s appears to have been cut short"
1592 " in the middle of a packet.", display_basename);
1595 case WTAP_ERR_BAD_FILE:
1596 simple_error_message_box(
1597 "The capture file %s appears to be damaged or corrupt.\n(%s)",
1598 display_basename, err_info);
1602 case WTAP_ERR_DECOMPRESS:
1603 simple_error_message_box(
1604 "The compressed capture file %s appears to be damaged or corrupt.\n"
1605 "(%s)", display_basename, err_info);
1610 simple_error_message_box(
1611 "An error occurred while reading the"
1612 " capture file %s: %s.",
1613 display_basename, wtap_strerror(read_err));
1616 g_free(display_basename);
1621 if (got_write_error) {
1622 /* Put up an alert box for the write error. */
1623 if (write_err < 0) {
1624 /* Wiretap error. */
1625 switch (write_err) {
1627 case WTAP_ERR_UNSUPPORTED_ENCAP:
1629 * This is a problem with the particular frame we're writing and
1630 * the file type and subtype we're writing; note that, and report
1631 * the frame number and file type/subtype.
1633 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1634 simple_error_message_box(
1635 "Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.",
1636 in_file ? in_file->packet_num : 0, display_basename,
1637 wtap_file_type_subtype_string(file_type));
1638 g_free(display_basename);
1641 case WTAP_ERR_PACKET_TOO_LARGE:
1643 * This is a problem with the particular frame we're writing and
1644 * the file type and subtype we're writing; note that, and report
1645 * the frame number and file type/subtype.
1647 display_basename = g_filename_display_basename(in_file ? in_file->filename : "UNKNOWN");
1648 simple_error_message_box(
1649 "Frame %u of \"%s\" is too large for a \"%s\" file.",
1650 in_file ? in_file->packet_num : 0, display_basename,
1651 wtap_file_type_subtype_string(file_type));
1652 g_free(display_basename);
1656 display_basename = g_filename_display_basename(out_filename);
1657 simple_error_message_box(
1658 "An error occurred while writing to the file \"%s\": %s.",
1659 out_filename, wtap_strerror(write_err));
1660 g_free(display_basename);
1665 write_failure_alert_box(out_filename, write_err);
1669 if (got_read_error || got_write_error || stop_flag) {
1670 /* Callers aren't expected to treat an error or an explicit abort
1671 differently - we put up error dialogs ourselves, so they don't
1679 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1681 const char *filter_new = dftext ? dftext : "";
1682 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1684 GTimeVal start_time;
1686 /* if new filter equals old one, do nothing unless told to do so */
1687 if (!force && strcmp(filter_new, filter_old) == 0) {
1693 if (dftext == NULL) {
1694 /* The new filter is an empty filter (i.e., display all packets).
1695 * so leave dfcode==NULL
1699 * We have a filter; make a copy of it (as we'll be saving it),
1700 * and try to compile it.
1702 dftext = g_strdup(dftext);
1703 if (!dfilter_compile(dftext, &dfcode)) {
1704 /* The attempt failed; report an error. */
1705 simple_message_box(ESD_TYPE_ERROR, NULL,
1706 "See the help for a description of the display filter syntax.",
1707 "\"%s\" isn't a valid display filter: %s",
1708 dftext, dfilter_error_msg);
1714 if (dfcode == NULL) {
1715 /* Yes - free the filter text, and set it to null. */
1721 /* We have a valid filter. Replace the current filter. */
1722 g_free(cf->dfilter);
1723 cf->dfilter = dftext;
1724 g_get_current_time(&start_time);
1727 /* Now rescan the packet list, applying the new filter, but not
1728 throwing away information constructed on a previous pass. */
1729 if (dftext == NULL) {
1730 rescan_packets(cf, "Resetting", "Filter", FALSE);
1732 rescan_packets(cf, "Filtering", dftext, FALSE);
1735 /* Cleanup and release all dfilter resources */
1736 dfilter_free(dfcode);
1742 cf_reftime_packets(capture_file *cf)
1744 ref_time_packets(cf);
1748 cf_redissect_packets(capture_file *cf)
1750 if (cf->state != FILE_CLOSED) {
1751 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1756 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1757 struct wtap_pkthdr *phdr, Buffer *buf)
1761 gchar *display_basename;
1763 #ifdef WANT_PACKET_EDITOR
1764 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1765 if (G_UNLIKELY(fdata->file_off == -1)) {
1766 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1769 simple_error_message_box("fdata->file_off == -1, but can't find modified frame!");
1773 *phdr = frame->phdr;
1774 buffer_assure_space(buf, frame->phdr.caplen);
1775 memcpy(buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1780 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1781 display_basename = g_filename_display_basename(cf->filename);
1784 case WTAP_ERR_UNSUPPORTED_ENCAP:
1785 simple_error_message_box("The file \"%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
1786 display_basename, err_info);
1790 case WTAP_ERR_BAD_FILE:
1791 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1792 display_basename, wtap_strerror(err), err_info);
1797 simple_error_message_box(
1798 "An error occurred while reading from the file \"%s\": %s.",
1799 display_basename, wtap_strerror(err));
1802 g_free(display_basename);
1809 cf_read_record(capture_file *cf, frame_data *fdata)
1811 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1814 /* Rescan the list of packets, reconstructing the CList.
1816 "action" describes why we're doing this; it's used in the progress
1819 "action_item" describes what we're doing; it's used in the progress
1822 "redissect" is TRUE if we need to make the dissectors reconstruct
1823 any state information they have (because a preference that affects
1824 some dissector has changed, meaning some dissector might construct
1825 its state differently from the way it was constructed the last time). */
1827 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1829 /* Rescan packets new packet list */
1832 progdlg_t *progbar = NULL;
1835 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1836 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1837 gboolean selected_frame_seen;
1839 GTimeVal start_time;
1840 gchar status_str[100];
1841 int progbar_nextstep;
1842 int progbar_quantum;
1846 gboolean create_proto_tree;
1848 gboolean add_to_packet_list = FALSE;
1850 guint32 frames_count;
1852 /* Compile the current display filter.
1853 * We assume this will not fail since cf->dfilter is only set in
1854 * cf_filter IFF the filter was valid.
1856 compiled = dfilter_compile(cf->dfilter, &dfcode);
1857 g_assert(!cf->dfilter || (compiled && dfcode));
1859 /* Get the union of the flags for all tap listeners. */
1860 tap_flags = union_of_tap_listener_flags();
1861 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1863 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1865 reset_tap_listeners();
1866 /* Which frame, if any, is the currently selected frame?
1867 XXX - should the selected frame or the focus frame be the "current"
1868 frame, that frame being the one from which "Find Frame" searches
1870 selected_frame = cf->current_frame;
1872 /* Mark frame num as not found */
1873 selected_frame_num = -1;
1875 /* Freeze the packet list while we redo it, so we don't get any
1876 screen updates while it happens. */
1877 packet_list_freeze();
1880 /* We need to re-initialize all the state information that protocols
1881 keep, because some preference that controls a dissector has changed,
1882 which might cause the state information to be constructed differently
1883 by that dissector. */
1885 /* We might receive new packets while redissecting, and we don't
1886 want to dissect those before their time. */
1887 cf->redissecting = TRUE;
1889 /* 'reset' dissection session */
1890 epan_free(cf->epan);
1891 cf->epan = ws_epan_new(cf);
1892 cf->cinfo.epan = cf->epan;
1894 /* We need to redissect the packets so we have to discard our old
1895 * packet list store. */
1896 packet_list_clear();
1897 add_to_packet_list = TRUE;
1900 /* We don't yet know which will be the first and last frames displayed. */
1901 cf->first_displayed = 0;
1902 cf->last_displayed = 0;
1904 /* We currently don't display any packets */
1905 cf->displayed_count = 0;
1907 /* Iterate through the list of frames. Call a routine for each frame
1908 to check whether it should be displayed and, if so, add it to
1909 the display list. */
1911 cf->prev_dis = NULL;
1912 cf->prev_cap = NULL;
1915 /* Update the progress bar when it gets to this value. */
1916 progbar_nextstep = 0;
1917 /* When we reach the value that triggers a progress bar update,
1918 bump that value by this amount. */
1919 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1920 /* Count of packets at which we've looked. */
1922 /* Progress so far. */
1926 g_get_current_time(&start_time);
1928 /* no previous row yet */
1929 prev_frame_num = -1;
1932 preceding_frame_num = -1;
1933 preceding_frame = NULL;
1934 following_frame_num = -1;
1935 following_frame = NULL;
1937 selected_frame_seen = FALSE;
1939 frames_count = cf->count;
1941 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1943 for (framenum = 1; framenum <= frames_count; framenum++) {
1944 fdata = frame_data_sequence_find(cf->frames, framenum);
1946 /* Create the progress bar if necessary.
1947 We check on every iteration of the loop, so that it takes no
1948 longer than the standard time to create it (otherwise, for a
1949 large file, we might take considerably longer than that standard
1950 time in order to get to the next progress bar step). */
1951 if (progbar == NULL)
1952 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1953 &stop_flag, &start_time,
1956 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1957 when we update it, we have to run the GTK+ main loop to get it
1958 to repaint what's pending, and doing so may involve an "ioctl()"
1959 to see if there's any pending input from an X server, and doing
1960 that for every packet can be costly, especially on a big file. */
1961 if (count >= progbar_nextstep) {
1962 /* let's not divide by zero. I should never be started
1963 * with count == 0, so let's assert that
1965 g_assert(cf->count > 0);
1966 progbar_val = (gfloat) count / frames_count;
1968 if (progbar != NULL) {
1969 g_snprintf(status_str, sizeof(status_str),
1970 "%4u of %u frames", count, frames_count);
1971 update_progress_dlg(progbar, progbar_val, status_str);
1974 progbar_nextstep += progbar_quantum;
1978 /* Well, the user decided to abort the filtering. Just stop.
1980 XXX - go back to the previous filter? Users probably just
1981 want not to wait for a filtering operation to finish;
1982 unless we cancel by having no filter, reverting to the
1983 previous filter will probably be even more expensive than
1984 continuing the filtering, as it involves going back to the
1985 beginning and filtering, and even with no filter we currently
1986 have to re-generate the entire clist, which is also expensive.
1988 I'm not sure what Network Monitor does, but it doesn't appear
1989 to give you an unfiltered display if you cancel. */
1996 /* Since all state for the frame was destroyed, mark the frame
1997 * as not visited, free the GSList referring to the state
1998 * data (the per-frame data itself was freed by
1999 * "init_dissection()"), and null out the GSList pointer. */
2000 frame_data_reset(fdata);
2001 frames_count = cf->count;
2004 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
2005 fdata->flags.dependent_of_displayed = 0;
2007 if (!cf_read_record(cf, fdata))
2008 break; /* error reading the frame */
2010 /* If the previous frame is displayed, and we haven't yet seen the
2011 selected frame, remember that frame - it's the closest one we've
2012 yet seen before the selected frame. */
2013 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
2014 preceding_frame_num = prev_frame_num;
2015 preceding_frame = prev_frame;
2018 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
2020 buffer_start_ptr(&cf->buf),
2021 add_to_packet_list);
2023 /* If this frame is displayed, and this is the first frame we've
2024 seen displayed after the selected frame, remember this frame -
2025 it's the closest one we've yet seen at or after the selected
2027 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
2028 following_frame_num = fdata->num;
2029 following_frame = fdata;
2031 if (fdata == selected_frame) {
2032 selected_frame_seen = TRUE;
2033 if (fdata->flags.passed_dfilter)
2034 selected_frame_num = fdata->num;
2037 /* Remember this frame - it'll be the previous frame
2038 on the next pass through the loop. */
2039 prev_frame_num = fdata->num;
2043 epan_dissect_cleanup(&edt);
2045 /* We are done redissecting the packet list. */
2046 cf->redissecting = FALSE;
2049 frames_count = cf->count;
2050 /* Clear out what remains of the visited flags and per-frame data
2053 XXX - that may cause various forms of bogosity when dissecting
2054 these frames, as they won't have been seen by this sequential
2055 pass, but the only alternative I see is to keep scanning them
2056 even though the user requested that the scan stop, and that
2057 would leave the user stuck with an Wireshark grinding on
2058 until it finishes. Should we just stick them with that? */
2059 for (; framenum <= frames_count; framenum++) {
2060 fdata = frame_data_sequence_find(cf->frames, framenum);
2061 frame_data_reset(fdata);
2065 /* We're done filtering the packets; destroy the progress bar if it
2067 if (progbar != NULL)
2068 destroy_progress_dlg(progbar);
2070 /* Unfreeze the packet list. */
2071 if (!add_to_packet_list)
2072 packet_list_recreate_visible_rows();
2074 /* Compute the time it took to filter the file */
2075 compute_elapsed(cf, &start_time);
2079 if (selected_frame_num == -1) {
2080 /* The selected frame didn't pass the filter. */
2081 if (selected_frame == NULL) {
2082 /* That's because there *was* no selected frame. Make the first
2083 displayed frame the current frame. */
2084 selected_frame_num = 0;
2086 /* Find the nearest displayed frame to the selected frame (whether
2087 it's before or after that frame) and make that the current frame.
2088 If the next and previous displayed frames are equidistant from the
2089 selected frame, choose the next one. */
2090 g_assert(following_frame == NULL ||
2091 following_frame->num >= selected_frame->num);
2092 g_assert(preceding_frame == NULL ||
2093 preceding_frame->num <= selected_frame->num);
2094 if (following_frame == NULL) {
2095 /* No frame after the selected frame passed the filter, so we
2096 have to select the last displayed frame before the selected
2098 selected_frame_num = preceding_frame_num;
2099 selected_frame = preceding_frame;
2100 } else if (preceding_frame == NULL) {
2101 /* No frame before the selected frame passed the filter, so we
2102 have to select the first displayed frame after the selected
2104 selected_frame_num = following_frame_num;
2105 selected_frame = following_frame;
2107 /* Frames before and after the selected frame passed the filter, so
2108 we'll select the previous frame */
2109 selected_frame_num = preceding_frame_num;
2110 selected_frame = preceding_frame;
2115 if (selected_frame_num == -1) {
2116 /* There are no frames displayed at all. */
2117 cf_unselect_packet(cf);
2119 /* Either the frame that was selected passed the filter, or we've
2120 found the nearest displayed frame to that frame. Select it, make
2121 it the focus row, and make it visible. */
2122 /* Set to invalid to force update of packet list and packet details */
2123 cf->current_row = -1;
2124 if (selected_frame_num == 0) {
2125 packet_list_select_first_row();
2127 if (!packet_list_select_row_from_data(selected_frame)) {
2128 /* We didn't find a row corresponding to this frame.
2129 This means that the frame isn't being displayed currently,
2130 so we can't select it. */
2131 simple_message_box(ESD_TYPE_INFO, NULL,
2132 "The capture file is probably not fully dissected.",
2133 "End of capture exceeded!");
2138 /* Cleanup and release all dfilter resources */
2139 dfilter_free(dfcode);
2144 * Scan trough all frame data and recalculate the ref time
2145 * without rereading the file.
2146 * XXX - do we need a progres bar or is this fast enough?
2149 ref_time_packets(capture_file *cf)
2156 cf->prev_dis = NULL;
2159 for (framenum = 1; framenum <= cf->count; framenum++) {
2160 fdata = frame_data_sequence_find(cf->frames, framenum);
2162 /* just add some value here until we know if it is being displayed or not */
2163 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
2169 /* If we don't have the time stamp of the first packet in the
2170 capture, it's because this is the first packet. Save the time
2171 stamp of this packet as the time stamp of the first packet. */
2172 if (cf->ref == NULL)
2174 /* if this frames is marked as a reference time frame, reset
2175 firstsec and firstusec to this frame */
2176 if (fdata->flags.ref_time)
2179 /* If we don't have the time stamp of the previous displayed packet,
2180 it's because this is the first displayed packet. Save the time
2181 stamp of this packet as the time stamp of the previous displayed
2183 if (cf->prev_dis == NULL) {
2184 cf->prev_dis = fdata;
2187 /* Get the time elapsed between the first packet and this packet. */
2188 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
2189 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
2191 /* If it's greater than the current elapsed time, set the elapsed time
2192 to it (we check for "greater than" so as not to be confused by
2193 time moving backwards). */
2194 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
2195 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
2196 cf->elapsed_time = rel_ts;
2199 /* If this frame is displayed, get the time elapsed between the
2200 previous displayed packet and this packet. */
2201 if ( fdata->flags.passed_dfilter ) {
2202 fdata->prev_dis_num = cf->prev_dis->num;
2203 cf->prev_dis = fdata;
2209 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
2210 /* This frame either passed the display filter list or is marked as
2211 a time reference frame. All time reference frames are displayed
2212 even if they dont pass the display filter */
2213 if (fdata->flags.ref_time) {
2214 /* if this was a TIME REF frame we should reset the cum_bytes field */
2215 cf->cum_bytes = fdata->pkt_len;
2216 fdata->cum_bytes = cf->cum_bytes;
2218 /* increase cum_bytes with this packets length */
2219 cf->cum_bytes += fdata->pkt_len;
2232 process_specified_records(capture_file *cf, packet_range_t *range,
2233 const char *string1, const char *string2, gboolean terminate_is_stop,
2234 gboolean (*callback)(capture_file *, frame_data *,
2235 struct wtap_pkthdr *, const guint8 *, void *),
2236 void *callback_args)
2241 psp_return_t ret = PSP_FINISHED;
2243 progdlg_t *progbar = NULL;
2246 gboolean progbar_stop_flag;
2247 GTimeVal progbar_start_time;
2248 gchar progbar_status_str[100];
2249 int progbar_nextstep;
2250 int progbar_quantum;
2251 range_process_e process_this;
2252 struct wtap_pkthdr phdr;
2254 memset(&phdr, 0, sizeof(struct wtap_pkthdr));
2255 buffer_init(&buf, 1500);
2257 /* Update the progress bar when it gets to this value. */
2258 progbar_nextstep = 0;
2259 /* When we reach the value that triggers a progress bar update,
2260 bump that value by this amount. */
2261 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2262 /* Count of packets at which we've looked. */
2264 /* Progress so far. */
2267 progbar_stop_flag = FALSE;
2268 g_get_current_time(&progbar_start_time);
2271 packet_range_process_init(range);
2273 /* Iterate through all the packets, printing the packets that
2274 were selected by the current display filter. */
2275 for (framenum = 1; framenum <= cf->count; framenum++) {
2276 fdata = frame_data_sequence_find(cf->frames, framenum);
2278 /* Create the progress bar if necessary.
2279 We check on every iteration of the loop, so that it takes no
2280 longer than the standard time to create it (otherwise, for a
2281 large file, we might take considerably longer than that standard
2282 time in order to get to the next progress bar step). */
2283 if (progbar == NULL)
2284 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2287 &progbar_start_time,
2290 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2291 when we update it, we have to run the GTK+ main loop to get it
2292 to repaint what's pending, and doing so may involve an "ioctl()"
2293 to see if there's any pending input from an X server, and doing
2294 that for every packet can be costly, especially on a big file. */
2295 if (progbar_count >= progbar_nextstep) {
2296 /* let's not divide by zero. I should never be started
2297 * with count == 0, so let's assert that
2299 g_assert(cf->count > 0);
2300 progbar_val = (gfloat) progbar_count / cf->count;
2302 if (progbar != NULL) {
2303 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2304 "%4u of %u packets", progbar_count, cf->count);
2305 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2308 progbar_nextstep += progbar_quantum;
2311 if (progbar_stop_flag) {
2312 /* Well, the user decided to abort the operation. Just stop,
2313 and arrange to return PSP_STOPPED to our caller, so they know
2314 it was stopped explicitly. */
2321 if (range != NULL) {
2322 /* do we have to process this packet? */
2323 process_this = packet_range_process_packet(range, fdata);
2324 if (process_this == range_process_next) {
2325 /* this packet uninteresting, continue with next one */
2327 } else if (process_this == range_processing_finished) {
2328 /* all interesting packets processed, stop the loop */
2333 /* Get the packet */
2334 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2335 /* Attempt to get the packet failed. */
2339 /* Process the packet */
2340 if (!callback(cf, fdata, &phdr, buffer_start_ptr(&buf), callback_args)) {
2341 /* Callback failed. We assume it reported the error appropriately. */
2347 /* We're done printing the packets; destroy the progress bar if
2349 if (progbar != NULL)
2350 destroy_progress_dlg(progbar);
2360 } retap_callback_args_t;
2363 retap_packet(capture_file *cf, frame_data *fdata,
2364 struct wtap_pkthdr *phdr, const guint8 *pd,
2367 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2369 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2370 epan_dissect_reset(&args->edt);
2376 cf_retap_packets(capture_file *cf)
2378 packet_range_t range;
2379 retap_callback_args_t callback_args;
2380 gboolean construct_protocol_tree;
2381 gboolean filtering_tap_listeners;
2385 /* Presumably the user closed the capture file. */
2387 return CF_READ_ABORTED;
2390 /* Do we have any tap listeners with filters? */
2391 filtering_tap_listeners = have_filtering_tap_listeners();
2393 tap_flags = union_of_tap_listener_flags();
2395 /* If any tap listeners have filters, or require the protocol tree,
2396 construct the protocol tree. */
2397 construct_protocol_tree = filtering_tap_listeners ||
2398 (tap_flags & TL_REQUIRES_PROTO_TREE);
2400 /* If any tap listeners require the columns, construct them. */
2401 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2403 /* Reset the tap listeners. */
2404 reset_tap_listeners();
2406 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2408 /* Iterate through the list of packets, dissecting all packets and
2409 re-running the taps. */
2410 packet_range_init(&range, cf);
2411 packet_range_process_init(&range);
2413 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2414 "all packets", TRUE, retap_packet,
2417 epan_dissect_cleanup(&callback_args.edt);
2421 /* Completed successfully. */
2425 /* Well, the user decided to abort the refiltering.
2426 Return CF_READ_ABORTED so our caller knows they did that. */
2427 return CF_READ_ABORTED;
2430 /* Error while retapping. */
2431 return CF_READ_ERROR;
2434 g_assert_not_reached();
2439 print_args_t *print_args;
2440 gboolean print_header_line;
2441 char *header_line_buf;
2442 int header_line_buf_len;
2443 gboolean print_formfeed;
2444 gboolean print_separator;
2448 int num_visible_cols;
2451 } print_callback_args_t;
2454 print_packet(capture_file *cf, frame_data *fdata,
2455 struct wtap_pkthdr *phdr, const guint8 *pd,
2458 print_callback_args_t *args = (print_callback_args_t *)argsp;
2464 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2465 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2467 /* Fill in the column information if we're printing the summary
2469 if (args->print_args->print_summary) {
2470 col_custom_prime_edt(&args->edt, &cf->cinfo);
2471 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2472 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2474 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2476 if (args->print_formfeed) {
2477 if (!new_page(args->print_args->stream))
2480 if (args->print_separator) {
2481 if (!print_line(args->print_args->stream, 0, ""))
2487 * We generate bookmarks, if the output format supports them.
2488 * The name is "__frameN__".
2490 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2492 if (args->print_args->print_summary) {
2493 if (!args->print_args->print_col_headings)
2494 args->print_header_line = FALSE;
2495 if (args->print_header_line) {
2496 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2498 args->print_header_line = FALSE; /* we might not need to print any more */
2500 cp = &args->line_buf[0];
2502 for (i = 0; i < args->num_visible_cols; i++) {
2503 /* Find the length of the string for this column. */
2504 column_len = (int) strlen(cf->cinfo.col_data[args->visible_cols[i]]);
2505 if (args->col_widths[i] > column_len)
2506 column_len = args->col_widths[i];
2508 /* Make sure there's room in the line buffer for the column; if not,
2509 double its length. */
2510 line_len += column_len + 1; /* "+1" for space */
2511 if (line_len > args->line_buf_len) {
2512 cp_off = (int) (cp - args->line_buf);
2513 args->line_buf_len = 2 * line_len;
2514 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2515 cp = args->line_buf + cp_off;
2518 /* Right-justify the packet number column. */
2519 if (cf->cinfo.col_fmt[args->visible_cols[i]] == COL_NUMBER)
2520 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2522 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], cf->cinfo.col_data[args->visible_cols[i]]);
2524 if (i != args->num_visible_cols - 1)
2530 * Generate a bookmark, using the summary line as the title.
2532 if (!print_bookmark(args->print_args->stream, bookmark_name,
2536 if (!print_line(args->print_args->stream, 0, args->line_buf))
2540 * Generate a bookmark, using "Frame N" as the title, as we're not
2541 * printing the summary line.
2543 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2544 if (!print_bookmark(args->print_args->stream, bookmark_name,
2547 } /* if (print_summary) */
2549 if (args->print_args->print_dissections != print_dissections_none) {
2550 if (args->print_args->print_summary) {
2551 /* Separate the summary line from the tree with a blank line. */
2552 if (!print_line(args->print_args->stream, 0, ""))
2556 /* Print the information in that tree. */
2557 if (!proto_tree_print(args->print_args, &args->edt, args->print_args->stream))
2560 /* Print a blank line if we print anything after this (aka more than one packet). */
2561 args->print_separator = TRUE;
2563 /* Print a header line if we print any more packet summaries */
2564 if (args->print_args->print_col_headings)
2565 args->print_header_line = TRUE;
2568 if (args->print_args->print_hex) {
2569 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2570 if (!print_line(args->print_args->stream, 0, ""))
2573 /* Print the full packet data as hex. */
2574 if (!print_hex_data(args->print_args->stream, &args->edt))
2577 /* Print a blank line if we print anything after this (aka more than one packet). */
2578 args->print_separator = TRUE;
2580 /* Print a header line if we print any more packet summaries */
2581 if (args->print_args->print_col_headings)
2582 args->print_header_line = TRUE;
2583 } /* if (args->print_args->print_dissections != print_dissections_none) */
2585 epan_dissect_reset(&args->edt);
2587 /* do we want to have a formfeed between each packet from now on? */
2588 if (args->print_args->print_formfeed) {
2589 args->print_formfeed = TRUE;
2595 epan_dissect_reset(&args->edt);
2600 cf_print_packets(capture_file *cf, print_args_t *print_args)
2602 print_callback_args_t callback_args;
2605 int i, cp_off, column_len, line_len;
2606 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2610 gboolean proto_tree_needed;
2612 callback_args.print_args = print_args;
2613 callback_args.print_header_line = print_args->print_col_headings;
2614 callback_args.header_line_buf = NULL;
2615 callback_args.header_line_buf_len = 256;
2616 callback_args.print_formfeed = FALSE;
2617 callback_args.print_separator = FALSE;
2618 callback_args.line_buf = NULL;
2619 callback_args.line_buf_len = 256;
2620 callback_args.col_widths = NULL;
2621 callback_args.num_visible_cols = 0;
2622 callback_args.visible_cols = NULL;
2624 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2625 destroy_print_stream(print_args->stream);
2626 return CF_PRINT_WRITE_ERROR;
2629 if (print_args->print_summary) {
2630 /* We're printing packet summaries. Allocate the header line buffer
2631 and get the column widths. */
2632 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2634 /* Find the number of visible columns and the last visible column */
2635 for (i = 0; i < prefs.num_cols; i++) {
2637 clp = g_list_nth(prefs.col_list, i);
2638 if (clp == NULL) /* Sanity check, Invalid column requested */
2641 cfmt = (fmt_data *) clp->data;
2642 if (cfmt->visible) {
2644 last_visible_col = i;
2648 /* Find the widths for each of the columns - maximum of the
2649 width of the title and the width of the data - and construct
2650 a buffer with a line containing the column titles. */
2651 callback_args.num_visible_cols = num_visible_col;
2652 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2653 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2654 cp = &callback_args.header_line_buf[0];
2656 visible_col_count = 0;
2657 for (i = 0; i < cf->cinfo.num_cols; i++) {
2659 clp = g_list_nth(prefs.col_list, i);
2660 if (clp == NULL) /* Sanity check, Invalid column requested */
2663 cfmt = (fmt_data *) clp->data;
2664 if (cfmt->visible == FALSE)
2667 /* Save the order of visible columns */
2668 callback_args.visible_cols[visible_col_count] = i;
2670 /* Don't pad the last column. */
2671 if (i == last_visible_col)
2672 callback_args.col_widths[visible_col_count] = 0;
2674 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.col_title[i]);
2675 data_width = get_column_char_width(get_column_format(i));
2676 if (data_width > callback_args.col_widths[visible_col_count])
2677 callback_args.col_widths[visible_col_count] = data_width;
2680 /* Find the length of the string for this column. */
2681 column_len = (int) strlen(cf->cinfo.col_title[i]);
2682 if (callback_args.col_widths[i] > column_len)
2683 column_len = callback_args.col_widths[visible_col_count];
2685 /* Make sure there's room in the line buffer for the column; if not,
2686 double its length. */
2687 line_len += column_len + 1; /* "+1" for space */
2688 if (line_len > callback_args.header_line_buf_len) {
2689 cp_off = (int) (cp - callback_args.header_line_buf);
2690 callback_args.header_line_buf_len = 2 * line_len;
2691 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2692 callback_args.header_line_buf_len + 1);
2693 cp = callback_args.header_line_buf + cp_off;
2696 /* Right-justify the packet number column. */
2697 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2698 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2700 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.col_title[i]);
2702 if (i != cf->cinfo.num_cols - 1)
2705 visible_col_count++;
2709 /* Now start out the main line buffer with the same length as the
2710 header line buffer. */
2711 callback_args.line_buf_len = callback_args.header_line_buf_len;
2712 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2713 } /* if (print_summary) */
2715 /* Create the protocol tree, and make it visible, if we're printing
2716 the dissection or the hex data.
2717 XXX - do we need it if we're just printing the hex data? */
2719 callback_args.print_args->print_dissections != print_dissections_none ||
2720 callback_args.print_args->print_hex ||
2721 have_custom_cols(&cf->cinfo);
2722 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2724 /* Iterate through the list of packets, printing the packets we were
2726 ret = process_specified_records(cf, &print_args->range, "Printing",
2727 "selected packets", TRUE, print_packet,
2729 epan_dissect_cleanup(&callback_args.edt);
2730 g_free(callback_args.header_line_buf);
2731 g_free(callback_args.line_buf);
2732 g_free(callback_args.col_widths);
2733 g_free(callback_args.visible_cols);
2738 /* Completed successfully. */
2742 /* Well, the user decided to abort the 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. */
2751 /* Error while printing.
2753 XXX - note that what got generated before they did that
2754 will get printed if we're piping to a print program; we'd
2755 have to write to a file and then hand that to the print
2756 program to make it actually not print anything. */
2757 destroy_print_stream(print_args->stream);
2758 return CF_PRINT_WRITE_ERROR;
2761 if (!print_finale(print_args->stream)) {
2762 destroy_print_stream(print_args->stream);
2763 return CF_PRINT_WRITE_ERROR;
2766 if (!destroy_print_stream(print_args->stream))
2767 return CF_PRINT_WRITE_ERROR;
2775 } write_packet_callback_args_t;
2778 write_pdml_packet(capture_file *cf, frame_data *fdata,
2779 struct wtap_pkthdr *phdr, const guint8 *pd,
2782 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2784 /* Create the protocol tree, but don't fill in the column information. */
2785 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2787 /* Write out the information in that tree. */
2788 proto_tree_write_pdml(&args->edt, args->fh);
2790 epan_dissect_reset(&args->edt);
2792 return !ferror(args->fh);
2796 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2798 write_packet_callback_args_t callback_args;
2802 fh = ws_fopen(print_args->file, "w");
2804 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2806 write_pdml_preamble(fh, cf->filename);
2809 return CF_PRINT_WRITE_ERROR;
2812 callback_args.fh = fh;
2813 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2815 /* Iterate through the list of packets, printing the packets we were
2817 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2818 "selected packets", TRUE,
2819 write_pdml_packet, &callback_args);
2821 epan_dissect_cleanup(&callback_args.edt);
2826 /* Completed successfully. */
2830 /* Well, the user decided to abort the printing. */
2834 /* Error while printing. */
2836 return CF_PRINT_WRITE_ERROR;
2839 write_pdml_finale(fh);
2842 return CF_PRINT_WRITE_ERROR;
2845 /* XXX - check for an error */
2852 write_psml_packet(capture_file *cf, frame_data *fdata,
2853 struct wtap_pkthdr *phdr, const guint8 *pd,
2856 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2858 col_custom_prime_edt(&args->edt, &cf->cinfo);
2859 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2860 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2862 /* Write out the information in that tree. */
2863 proto_tree_write_psml(&args->edt, args->fh);
2865 epan_dissect_reset(&args->edt);
2867 return !ferror(args->fh);
2871 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2873 write_packet_callback_args_t callback_args;
2877 gboolean proto_tree_needed;
2879 fh = ws_fopen(print_args->file, "w");
2881 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2883 write_psml_preamble(fh);
2886 return CF_PRINT_WRITE_ERROR;
2889 callback_args.fh = fh;
2891 /* Fill in the column information, only create the protocol tree
2892 if having custom columns. */
2893 proto_tree_needed = have_custom_cols(&cf->cinfo);
2894 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2896 /* Iterate through the list of packets, printing the packets we were
2898 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2899 "selected packets", TRUE,
2900 write_psml_packet, &callback_args);
2902 epan_dissect_cleanup(&callback_args.edt);
2907 /* Completed successfully. */
2911 /* Well, the user decided to abort the printing. */
2915 /* Error while printing. */
2917 return CF_PRINT_WRITE_ERROR;
2920 write_psml_finale(fh);
2923 return CF_PRINT_WRITE_ERROR;
2926 /* XXX - check for an error */
2933 write_csv_packet(capture_file *cf, frame_data *fdata,
2934 struct wtap_pkthdr *phdr, const guint8 *pd,
2937 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2939 /* Fill in the column information */
2940 col_custom_prime_edt(&args->edt, &cf->cinfo);
2941 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2942 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2944 /* Write out the information in that tree. */
2945 proto_tree_write_csv(&args->edt, args->fh);
2947 epan_dissect_reset(&args->edt);
2949 return !ferror(args->fh);
2953 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2955 write_packet_callback_args_t callback_args;
2956 gboolean proto_tree_needed;
2960 fh = ws_fopen(print_args->file, "w");
2962 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2964 write_csv_preamble(fh);
2967 return CF_PRINT_WRITE_ERROR;
2970 callback_args.fh = fh;
2972 /* only create the protocol tree if having custom columns. */
2973 proto_tree_needed = have_custom_cols(&cf->cinfo);
2974 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2976 /* Iterate through the list of packets, printing the packets we were
2978 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2979 "selected packets", TRUE,
2980 write_csv_packet, &callback_args);
2982 epan_dissect_cleanup(&callback_args.edt);
2987 /* Completed successfully. */
2991 /* Well, the user decided to abort the printing. */
2995 /* Error while printing. */
2997 return CF_PRINT_WRITE_ERROR;
3000 write_csv_finale(fh);
3003 return CF_PRINT_WRITE_ERROR;
3006 /* XXX - check for an error */
3013 write_carrays_packet(capture_file *cf, frame_data *fdata,
3014 struct wtap_pkthdr *phdr,
3015 const guint8 *pd, void *argsp)
3017 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
3019 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
3020 proto_tree_write_carrays(fdata->num, args->fh, &args->edt);
3021 epan_dissect_reset(&args->edt);
3023 return !ferror(args->fh);
3027 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
3029 write_packet_callback_args_t callback_args;
3033 fh = ws_fopen(print_args->file, "w");
3036 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
3038 write_carrays_preamble(fh);
3042 return CF_PRINT_WRITE_ERROR;
3045 callback_args.fh = fh;
3046 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
3048 /* Iterate through the list of packets, printing the packets we were
3050 ret = process_specified_records(cf, &print_args->range,
3052 "selected packets", TRUE,
3053 write_carrays_packet, &callback_args);
3055 epan_dissect_cleanup(&callback_args.edt);
3059 /* Completed successfully. */
3062 /* Well, the user decided to abort the printing. */
3065 /* Error while printing. */
3067 return CF_PRINT_WRITE_ERROR;
3070 write_carrays_finale(fh);
3074 return CF_PRINT_WRITE_ERROR;
3082 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
3083 search_direction dir)
3087 mdata.string = string;
3088 mdata.string_len = strlen(string);
3089 return find_packet(cf, match_protocol_tree, &mdata, dir);
3093 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
3095 mdata->frame_matched = FALSE;
3096 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
3097 mdata->string_len = strlen(mdata->string);
3099 /* Iterate through all the nodes looking for matching text */
3100 proto_tree_children_foreach(tree, match_subtree_text, mdata);
3101 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3105 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
3107 match_data *mdata = (match_data *)criterion;
3110 /* Load the frame's data. */
3111 if (!cf_read_record(cf, fdata)) {
3112 /* Attempt to get the packet failed. */
3116 /* Construct the protocol tree, including the displayed text */
3117 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
3118 /* We don't need the column information */
3119 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3121 /* Iterate through all the nodes, seeing if they have text that matches. */
3123 mdata->frame_matched = FALSE;
3124 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
3125 epan_dissect_cleanup(&edt);
3126 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
3130 match_subtree_text(proto_node *node, gpointer data)
3132 match_data *mdata = (match_data *) data;
3133 const gchar *string = mdata->string;
3134 size_t string_len = mdata->string_len;
3135 capture_file *cf = mdata->cf;
3136 field_info *fi = PNODE_FINFO(node);
3137 gchar label_str[ITEM_LABEL_LENGTH];
3144 /* dissection with an invisible proto tree? */
3147 if (mdata->frame_matched) {
3148 /* We already had a match; don't bother doing any more work. */
3152 /* Don't match invisible entries. */
3153 if (PROTO_ITEM_IS_HIDDEN(node))
3156 /* was a free format label produced? */
3158 label_ptr = fi->rep->representation;
3160 /* no, make a generic label */
3161 label_ptr = label_str;
3162 proto_item_fill_label(fi, label_str);
3165 /* Does that label match? */
3166 label_len = strlen(label_ptr);
3167 for (i = 0; i < label_len; i++) {
3168 c_char = label_ptr[i];
3170 c_char = toupper(c_char);
3171 if (c_char == string[c_match]) {
3173 if (c_match == string_len) {
3174 /* No need to look further; we have a match */
3175 mdata->frame_matched = TRUE;
3183 /* Recurse into the subtree, if it exists */
3184 if (node->first_child != NULL)
3185 proto_tree_children_foreach(node, match_subtree_text, mdata);
3189 cf_find_packet_summary_line(capture_file *cf, const char *string,
3190 search_direction dir)
3194 mdata.string = string;
3195 mdata.string_len = strlen(string);
3196 return find_packet(cf, match_summary_line, &mdata, dir);
3200 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
3202 match_data *mdata = (match_data *)criterion;
3203 const gchar *string = mdata->string;
3204 size_t string_len = mdata->string_len;
3206 const char *info_column;
3207 size_t info_column_len;
3208 match_result result = MR_NOTMATCHED;
3214 /* Load the frame's data. */
3215 if (!cf_read_record(cf, fdata)) {
3216 /* Attempt to get the packet failed. */
3220 /* Don't bother constructing the protocol tree */
3221 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
3222 /* Get the column information */
3223 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
3226 /* Find the Info column */
3227 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
3228 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
3229 /* Found it. See if we match. */
3230 info_column = edt.pi.cinfo->col_data[colx];
3231 info_column_len = strlen(info_column);
3232 for (i = 0; i < info_column_len; i++) {
3233 c_char = info_column[i];
3235 c_char = toupper(c_char);
3236 if (c_char == string[c_match]) {
3238 if (c_match == string_len) {
3239 result = MR_MATCHED;
3248 epan_dissect_cleanup(&edt);
3255 } cbs_t; /* "Counted byte string" */
3259 * The current match_* routines only support ASCII case insensitivity and don't
3260 * convert UTF-8 inputs to UTF-16 for matching.
3262 * We could modify them to use the GLib Unicode routines or the International
3263 * Components for Unicode library but it's not apparent that we could do so
3264 * without consuming a lot more CPU and memory or that searching would be
3265 * significantly better.
3269 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3270 search_direction dir)
3275 info.data_len = string_size;
3277 /* String or hex search? */
3279 /* String search - what type of string? */
3280 switch (cf->scs_type) {
3282 case SCS_NARROW_AND_WIDE:
3283 return find_packet(cf, match_narrow_and_wide, &info, dir);
3286 return find_packet(cf, match_narrow, &info, dir);
3289 return find_packet(cf, match_wide, &info, dir);
3292 g_assert_not_reached();
3296 return find_packet(cf, match_binary, &info, dir);
3300 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3302 cbs_t *info = (cbs_t *)criterion;
3303 const guint8 *ascii_text = info->data;
3304 size_t textlen = info->data_len;
3305 match_result result;
3312 /* Load the frame's data. */
3313 if (!cf_read_record(cf, fdata)) {
3314 /* Attempt to get the packet failed. */
3318 result = MR_NOTMATCHED;
3319 buf_len = fdata->cap_len;
3320 pd = buffer_start_ptr(&cf->buf);
3322 while (i < buf_len) {
3325 c_char = toupper(c_char);
3326 if (c_char != '\0') {
3327 if (c_char == ascii_text[c_match]) {
3329 if (c_match == textlen) {
3330 result = MR_MATCHED;
3331 cf->search_pos = i; /* Save the position of the last character
3332 for highlighting the field. */
3337 g_assert(i>=c_match);
3338 i -= (guint32)c_match;
3348 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3351 cbs_t *info = (cbs_t *)criterion;
3352 const guint8 *ascii_text = info->data;
3353 size_t textlen = info->data_len;
3354 match_result result;
3360 /* Load the frame's data. */
3361 if (!cf_read_record(cf, fdata)) {
3362 /* Attempt to get the packet failed. */
3366 result = MR_NOTMATCHED;
3367 buf_len = fdata->cap_len;
3368 pd = buffer_start_ptr(&cf->buf);
3370 while (i < buf_len) {
3373 c_char = toupper(c_char);
3374 if (c_char == ascii_text[c_match]) {
3376 if (c_match == textlen) {
3377 result = MR_MATCHED;
3378 cf->search_pos = i; /* Save the position of the last character
3379 for highlighting the field. */
3384 g_assert(i>=c_match);
3385 i -= (guint32)c_match;
3395 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3397 cbs_t *info = (cbs_t *)criterion;
3398 const guint8 *ascii_text = info->data;
3399 size_t textlen = info->data_len;
3400 match_result result;
3407 /* Load the frame's data. */
3408 if (!cf_read_record(cf, fdata)) {
3409 /* Attempt to get the packet failed. */
3413 result = MR_NOTMATCHED;
3414 buf_len = fdata->cap_len;
3415 pd = buffer_start_ptr(&cf->buf);
3417 while (i < buf_len) {
3420 c_char = toupper(c_char);
3421 if (c_char == ascii_text[c_match]) {
3423 if (c_match == textlen) {
3424 result = MR_MATCHED;
3425 cf->search_pos = i; /* Save the position of the last character
3426 for highlighting the field. */
3432 g_assert(i>=(c_match*2));
3433 i -= (guint32)c_match*2;
3442 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3444 cbs_t *info = (cbs_t *)criterion;
3445 const guint8 *binary_data = info->data;
3446 size_t datalen = info->data_len;
3447 match_result result;
3453 /* Load the frame's data. */
3454 if (!cf_read_record(cf, fdata)) {
3455 /* Attempt to get the packet failed. */
3459 result = MR_NOTMATCHED;
3460 buf_len = fdata->cap_len;
3461 pd = buffer_start_ptr(&cf->buf);
3463 while (i < buf_len) {
3464 if (pd[i] == binary_data[c_match]) {
3466 if (c_match == datalen) {
3467 result = MR_MATCHED;
3468 cf->search_pos = i; /* Save the position of the last character
3469 for highlighting the field. */
3474 g_assert(i>=c_match);
3475 i -= (guint32)c_match;
3484 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3485 search_direction dir)
3487 return find_packet(cf, match_dfilter, sfcode, dir);
3491 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3492 search_direction dir)
3497 if (!dfilter_compile(filter, &sfcode)) {
3499 * XXX - this shouldn't happen, as the filter string is machine
3504 if (sfcode == NULL) {
3506 * XXX - this shouldn't happen, as the filter string is machine
3511 result = find_packet(cf, match_dfilter, sfcode, dir);
3512 dfilter_free(sfcode);
3517 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3519 dfilter_t *sfcode = (dfilter_t *)criterion;
3521 match_result result;
3523 /* Load the frame's data. */
3524 if (!cf_read_record(cf, fdata)) {
3525 /* Attempt to get the packet failed. */
3529 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3530 epan_dissect_prime_dfilter(&edt, sfcode);
3531 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3532 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3533 epan_dissect_cleanup(&edt);
3538 cf_find_packet_marked(capture_file *cf, search_direction dir)
3540 return find_packet(cf, match_marked, NULL, dir);
3544 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3546 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3550 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3552 return find_packet(cf, match_time_reference, NULL, dir);
3556 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3558 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3562 find_packet(capture_file *cf,
3563 match_result (*match_function)(capture_file *, frame_data *, void *),
3564 void *criterion, search_direction dir)
3566 frame_data *start_fd;
3569 frame_data *new_fd = NULL;
3570 progdlg_t *progbar = NULL;
3575 GTimeVal start_time;
3576 gchar status_str[100];
3577 int progbar_nextstep;
3578 int progbar_quantum;
3580 match_result result;
3582 start_fd = cf->current_frame;
3583 if (start_fd != NULL) {
3584 /* Iterate through the list of packets, starting at the packet we've
3585 picked, calling a routine to run the filter on the packet, see if
3586 it matches, and stop if so. */
3588 framenum = start_fd->num;
3590 /* Update the progress bar when it gets to this value. */
3591 progbar_nextstep = 0;
3592 /* When we reach the value that triggers a progress bar update,
3593 bump that value by this amount. */
3594 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3595 /* Progress so far. */
3599 g_get_current_time(&start_time);
3601 title = cf->sfilter?cf->sfilter:"";
3603 /* Create the progress bar if necessary.
3604 We check on every iteration of the loop, so that it takes no
3605 longer than the standard time to create it (otherwise, for a
3606 large file, we might take considerably longer than that standard
3607 time in order to get to the next progress bar step). */
3608 if (progbar == NULL)
3609 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3610 FALSE, &stop_flag, &start_time, progbar_val);
3612 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3613 when we update it, we have to run the GTK+ main loop to get it
3614 to repaint what's pending, and doing so may involve an "ioctl()"
3615 to see if there's any pending input from an X server, and doing
3616 that for every packet can be costly, especially on a big file. */
3617 if (count >= progbar_nextstep) {
3618 /* let's not divide by zero. I should never be started
3619 * with count == 0, so let's assert that
3621 g_assert(cf->count > 0);
3623 progbar_val = (gfloat) count / cf->count;
3625 if (progbar != NULL) {
3626 g_snprintf(status_str, sizeof(status_str),
3627 "%4u of %u packets", count, cf->count);
3628 update_progress_dlg(progbar, progbar_val, status_str);
3631 progbar_nextstep += progbar_quantum;
3635 /* Well, the user decided to abort the search. Go back to the
3636 frame where we started. */
3641 /* Go past the current frame. */
3642 if (dir == SD_BACKWARD) {
3643 /* Go on to the previous frame. */
3644 if (framenum == 1) {
3646 * XXX - other apps have a bit more of a detailed message
3647 * for this, and instead of offering "OK" and "Cancel",
3648 * they offer things such as "Continue" and "Cancel";
3649 * we need an API for popping up alert boxes with
3650 * {Verb} and "Cancel".
3653 if (prefs.gui_find_wrap)
3655 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3656 framenum = cf->count; /* wrap around */
3660 statusbar_push_temporary_msg("Search reached the beginning.");
3661 framenum = start_fd->num; /* stay on previous packet */
3666 /* Go on to the next frame. */
3667 if (framenum == cf->count) {
3668 if (prefs.gui_find_wrap)
3670 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3671 framenum = 1; /* wrap around */
3675 statusbar_push_temporary_msg("Search reached the end.");
3676 framenum = start_fd->num; /* stay on previous packet */
3681 fdata = frame_data_sequence_find(cf->frames, framenum);
3685 /* Is this packet in the display? */
3686 if (fdata->flags.passed_dfilter) {
3687 /* Yes. Does it match the search criterion? */
3688 result = (*match_function)(cf, fdata, criterion);
3689 if (result == MR_ERROR) {
3690 /* Error; our caller has reported the error. Go back to the frame
3691 where we started. */
3694 } else if (result == MR_MATCHED) {
3695 /* Yes. Go to the new frame. */
3701 if (fdata == start_fd) {
3702 /* We're back to the frame we were on originally, and that frame
3703 doesn't match the search filter. The search failed. */
3708 /* We're done scanning the packets; destroy the progress bar if it
3710 if (progbar != NULL)
3711 destroy_progress_dlg(progbar);
3714 if (new_fd != NULL) {
3715 /* Find and select */
3716 cf->search_in_progress = TRUE;
3717 found = packet_list_select_row_from_data(new_fd);
3718 cf->search_in_progress = FALSE;
3719 cf->search_pos = 0; /* Reset the position */
3721 /* We didn't find a row corresponding to this frame.
3722 This means that the frame isn't being displayed currently,
3723 so we can't select it. */
3724 simple_message_box(ESD_TYPE_INFO, NULL,
3725 "The capture file is probably not fully dissected.",
3726 "End of capture exceeded!");
3729 return TRUE; /* success */
3731 return FALSE; /* failure */
3735 cf_goto_frame(capture_file *cf, guint fnumber)
3739 fdata = frame_data_sequence_find(cf->frames, fnumber);
3741 if (fdata == NULL) {
3742 /* we didn't find a packet with that packet number */
3743 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3744 return FALSE; /* we failed to go to that packet */
3746 if (!fdata->flags.passed_dfilter) {
3747 /* that packet currently isn't displayed */
3748 /* XXX - add it to the set of displayed packets? */
3749 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3750 return FALSE; /* we failed to go to that packet */
3753 if (!packet_list_select_row_from_data(fdata)) {
3754 /* We didn't find a row corresponding to this frame.
3755 This means that the frame isn't being displayed currently,
3756 so we can't select it. */
3757 simple_message_box(ESD_TYPE_INFO, NULL,
3758 "The capture file is probably not fully dissected.",
3759 "End of capture exceeded!");
3762 return TRUE; /* we got to that packet */
3766 cf_goto_top_frame(void)
3768 /* Find and select */
3769 packet_list_select_first_row();
3770 return TRUE; /* we got to that packet */
3774 cf_goto_bottom_frame(void)
3776 /* Find and select */
3777 packet_list_select_last_row();
3778 return TRUE; /* we got to that packet */
3782 * Go to frame specified by currently selected protocol tree item.
3785 cf_goto_framenum(capture_file *cf)
3787 header_field_info *hfinfo;
3790 if (cf->finfo_selected) {
3791 hfinfo = cf->finfo_selected->hfinfo;
3793 if (hfinfo->type == FT_FRAMENUM) {
3794 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3796 return cf_goto_frame(cf, framenum);
3803 /* Select the packet on a given row. */
3805 cf_select_packet(capture_file *cf, int row)
3807 epan_dissect_t *old_edt;
3810 /* Get the frame data struct pointer for this frame */
3811 fdata = packet_list_get_row_data(row);
3813 if (fdata == NULL) {
3814 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3815 the first entry is added to it by "real_insert_row()", that row
3816 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3817 our version and the vanilla GTK+ version).
3819 This means that a "select-row" signal is emitted; this causes
3820 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3823 "cf_select_packet()" fetches, above, the data associated with the
3824 row that was selected; however, as "gtk_clist_append()", which
3825 called "real_insert_row()", hasn't yet returned, we haven't yet
3826 associated any data with that row, so we get back a null pointer.
3828 We can't assume that there's only one frame in the frame list,
3829 either, as we may be filtering the display.
3831 We therefore assume that, if "row" is 0, i.e. the first row
3832 is being selected, and "cf->first_displayed" equals
3833 "cf->last_displayed", i.e. there's only one frame being
3834 displayed, that frame is the frame we want.
3836 This means we have to set "cf->first_displayed" and
3837 "cf->last_displayed" before adding the row to the
3838 GtkCList; see the comment in "add_packet_to_packet_list()". */
3840 if (row == 0 && cf->first_displayed == cf->last_displayed)
3841 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3844 /* If fdata _still_ isn't set simply give up. */
3845 if (fdata == NULL) {
3849 /* Get the data in that frame. */
3850 if (!cf_read_record (cf, fdata)) {
3854 /* Record that this frame is the current frame. */
3855 cf->current_frame = fdata;
3856 cf->current_row = row;
3859 /* Create the logical protocol tree. */
3860 /* We don't need the columns here. */
3861 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3863 tap_build_interesting(cf->edt);
3864 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3865 cf->current_frame, NULL);
3867 dfilter_macro_build_ftv_cache(cf->edt->tree);
3869 cf_callback_invoke(cf_cb_packet_selected, cf);
3871 if (old_edt != NULL)
3872 epan_dissect_free(old_edt);
3876 /* Unselect the selected packet, if any. */
3878 cf_unselect_packet(capture_file *cf)
3880 epan_dissect_t *old_edt = cf->edt;
3884 /* No packet is selected. */
3885 cf->current_frame = NULL;
3886 cf->current_row = 0;
3888 cf_callback_invoke(cf_cb_packet_unselected, cf);
3890 /* No protocol tree means no selected field. */
3891 cf_unselect_field(cf);
3893 /* Destroy the epan_dissect_t for the unselected packet. */
3894 if (old_edt != NULL)
3895 epan_dissect_free(old_edt);
3898 /* Unset the selected protocol tree field, if any. */
3900 cf_unselect_field(capture_file *cf)
3902 cf->finfo_selected = NULL;
3904 cf_callback_invoke(cf_cb_field_unselected, cf);
3908 * Mark a particular frame.
3911 cf_mark_frame(capture_file *cf, frame_data *frame)
3913 if (! frame->flags.marked) {
3914 frame->flags.marked = TRUE;
3915 if (cf->count > cf->marked_count)
3921 * Unmark a particular frame.
3924 cf_unmark_frame(capture_file *cf, frame_data *frame)
3926 if (frame->flags.marked) {
3927 frame->flags.marked = FALSE;
3928 if (cf->marked_count > 0)
3934 * Ignore a particular frame.
3937 cf_ignore_frame(capture_file *cf, frame_data *frame)
3939 if (! frame->flags.ignored) {
3940 frame->flags.ignored = TRUE;
3941 if (cf->count > cf->ignored_count)
3942 cf->ignored_count++;
3947 * Un-ignore a particular frame.
3950 cf_unignore_frame(capture_file *cf, frame_data *frame)
3952 if (frame->flags.ignored) {
3953 frame->flags.ignored = FALSE;
3954 if (cf->ignored_count > 0)
3955 cf->ignored_count--;
3960 * Read the comment in SHB block
3964 cf_read_shb_comment(capture_file *cf)
3966 wtapng_section_t *shb_inf;
3967 const gchar *temp_str;
3969 /* Get info from SHB */
3970 shb_inf = wtap_file_get_shb_info(cf->wth);
3971 if (shb_inf == NULL)
3973 temp_str = shb_inf->opt_comment;
3981 cf_update_capture_comment(capture_file *cf, gchar *comment)
3983 wtapng_section_t *shb_inf;
3985 /* Get info from SHB */
3986 shb_inf = wtap_file_get_shb_info(cf->wth);
3988 /* See if the comment has changed or not */
3989 if (shb_inf && shb_inf->opt_comment) {
3990 if (strcmp(shb_inf->opt_comment, comment) == 0) {
3999 /* The comment has changed, let's update it */
4000 wtap_write_shb_comment(cf->wth, comment);
4001 /* Mark the file as having unsaved changes */
4002 cf->unsaved_changes = TRUE;
4006 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
4008 if (cf->frames_user_comments)
4009 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
4016 cf_get_comment(capture_file *cf, const frame_data *fd)
4018 /* fetch user comment */
4019 if (fd->flags.has_user_comment)
4020 return g_strdup(cf_get_user_packet_comment(cf, fd));
4022 /* fetch phdr comment */
4023 if (fd->flags.has_phdr_comment) {
4024 struct wtap_pkthdr phdr; /* Packet header */
4025 Buffer buf; /* Packet data */
4027 memset(&phdr, 0, sizeof(struct wtap_pkthdr));
4029 buffer_init(&buf, 1500);
4030 if (!cf_read_record_r(cf, fd, &phdr, &buf))
4031 { /* XXX, what we can do here? */ }
4034 return phdr.opt_comment;
4040 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
4042 const frame_data *fdata1 = (const frame_data *) a;
4043 const frame_data *fdata2 = (const frame_data *) b;
4045 return (fdata1->num < fdata2->num) ? -1 :
4046 (fdata1->num > fdata2->num) ? 1 :
4051 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
4053 char *pkt_comment = cf_get_comment(cf, fd);
4055 /* Check if the comment has changed */
4056 if (!g_strcmp0(pkt_comment, new_comment)) {
4057 g_free(pkt_comment);
4060 g_free(pkt_comment);
4063 cf->packet_comment_count--;
4066 cf->packet_comment_count++;
4068 fd->flags.has_user_comment = TRUE;
4070 if (!cf->frames_user_comments)
4071 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
4073 /* insert new packet comment */
4074 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
4076 expert_update_comment_count(cf->packet_comment_count);
4078 /* OK, we have unsaved changes. */
4079 cf->unsaved_changes = TRUE;
4084 * What types of comments does this capture file have?
4087 cf_comment_types(capture_file *cf)
4089 guint32 comment_types = 0;
4091 if (cf_read_shb_comment(cf) != NULL)
4092 comment_types |= WTAP_COMMENT_PER_SECTION;
4093 if (cf->packet_comment_count != 0)
4094 comment_types |= WTAP_COMMENT_PER_PACKET;
4095 return comment_types;
4102 } save_callback_args_t;
4105 * Save a capture to a file, in a particular format, saving either
4106 * all packets, all currently-displayed packets, or all marked packets.
4108 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
4109 * up a message box for the failure.
4112 save_record(capture_file *cf _U_, frame_data *fdata,
4113 struct wtap_pkthdr *phdr, const guint8 *pd,
4116 save_callback_args_t *args = (save_callback_args_t *)argsp;
4117 struct wtap_pkthdr hdr;
4119 gchar *display_basename;
4120 const char *pkt_comment;
4122 if (fdata->flags.has_user_comment)
4123 pkt_comment = cf_get_user_packet_comment(cf, fdata);
4125 pkt_comment = phdr->opt_comment;
4127 /* init the wtap header for saving */
4128 /* TODO: reuse phdr */
4129 /* XXX - these are the only flags that correspond to data that we have
4130 in the frame_data structure and that matter on a per-packet basis.
4132 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
4133 and "on the wire" lengths, or it doesn't.
4135 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
4138 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
4139 from the packet flags. */
4140 hdr.rec_type = phdr->rec_type;
4141 hdr.presence_flags = 0;
4142 if (fdata->flags.has_ts)
4143 hdr.presence_flags |= WTAP_HAS_TS;
4144 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
4145 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
4146 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
4147 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
4148 hdr.ts.secs = fdata->abs_ts.secs;
4149 hdr.ts.nsecs = fdata->abs_ts.nsecs;
4150 hdr.caplen = phdr->caplen;
4151 hdr.len = phdr->len;
4152 hdr.pkt_encap = fdata->lnk_t;
4154 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
4156 hdr.pack_flags = phdr->pack_flags;
4157 hdr.opt_comment = g_strdup(pkt_comment);
4160 hdr.pseudo_header = phdr->pseudo_header;
4163 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
4165 /* and save the packet */
4166 if (!wtap_dump(args->pdh, &hdr, pd, &err)) {
4168 /* Wiretap error. */
4171 case WTAP_ERR_UNSUPPORTED_ENCAP:
4173 * This is a problem with the particular frame we're writing and
4174 * the file type and subtype we're writing; note that, and report
4175 * the frame number and file type/subtype.
4177 simple_error_message_box(
4178 "Frame %u has a network type that can't be saved in a \"%s\" file.",
4179 fdata->num, wtap_file_type_subtype_string(args->file_type));
4182 case WTAP_ERR_PACKET_TOO_LARGE:
4184 * This is a problem with the particular frame we're writing and
4185 * the file type and subtype we're writing; note that, and report
4186 * the frame number and file type/subtype.
4188 simple_error_message_box(
4189 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
4190 fdata->num, wtap_file_type_subtype_string(args->file_type));
4194 display_basename = g_filename_display_basename(args->fname);
4195 simple_error_message_box(
4196 "An error occurred while writing to the file \"%s\": %s.",
4197 display_basename, wtap_strerror(err));
4198 g_free(display_basename);
4203 write_failure_alert_box(args->fname, err);
4208 g_free(hdr.opt_comment);
4213 * Can this capture file be written out in any format using Wiretap
4214 * rather than by copying the raw data?
4217 cf_can_write_with_wiretap(capture_file *cf)
4219 /* We don't care whether we support the comments in this file or not;
4220 if we can't, we'll offer the user the option of discarding the
4222 return wtap_dump_can_write(cf->linktypes, 0);
4226 * Should we let the user do a save?
4230 * the file has unsaved changes, and we can save it in some
4231 * format through Wiretap
4235 * the file is a temporary file and has no unsaved changes (so
4236 * that "saving" it just means copying it).
4238 * XXX - we shouldn't allow files to be edited if they can't be saved,
4239 * so cf->unsaved_changes should be true only if the file can be saved.
4241 * We don't care whether we support the comments in this file or not;
4242 * if we can't, we'll offer the user the option of discarding the
4246 cf_can_save(capture_file *cf)
4248 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4249 /* Saved changes, and we can write it out with Wiretap. */
4253 if (cf->is_tempfile && !cf->unsaved_changes) {
4255 * Temporary file with no unsaved changes, so we can just do a
4261 /* Nothing to save. */
4266 * Should we let the user do a "save as"?
4270 * we can save it in some format through Wiretap
4274 * the file is a temporary file and has no unsaved changes (so
4275 * that "saving" it just means copying it).
4277 * XXX - we shouldn't allow files to be edited if they can't be saved,
4278 * so cf->unsaved_changes should be true only if the file can be saved.
4280 * We don't care whether we support the comments in this file or not;
4281 * if we can't, we'll offer the user the option of discarding the
4285 cf_can_save_as(capture_file *cf)
4287 if (wtap_dump_can_write(cf->linktypes, 0)) {
4288 /* We can write it out with Wiretap. */
4292 if (cf->is_tempfile && !cf->unsaved_changes) {
4294 * Temporary file with no unsaved changes, so we can just do a
4300 /* Nothing to save. */
4305 * Does this file have unsaved data?
4308 cf_has_unsaved_data(capture_file *cf)
4311 * If this is a temporary file, or a file with unsaved changes, it
4314 return cf->is_tempfile || cf->unsaved_changes;
4318 * Quick scan to find packet offsets.
4320 static cf_read_status_t
4321 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4323 const struct wtap_pkthdr *phdr;
4328 progdlg_t *progbar = NULL;
4332 GTimeVal start_time;
4333 gchar status_str[100];
4334 gint64 progbar_nextstep;
4335 gint64 progbar_quantum;
4340 int displayed_once = 0;
4343 /* Close the old handle. */
4344 wtap_close(cf->wth);
4346 /* Open the new file. */
4347 /* XXX: this will go through all open_routines for a matching one. But right
4348 now rescan_file() is only used when a file is being saved to a different
4349 format than the original, and the user is not given a choice of which
4350 reader to use (only which format to save it in), so doing this makes
4352 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4353 if (cf->wth == NULL) {
4354 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4355 return CF_READ_ERROR;
4358 /* We're scanning a file whose contents should be the same as what
4359 we had before, so we don't discard dissection state etc.. */
4362 /* Set the file name because we need it to set the follow stream filter.
4363 XXX - is that still true? We need it for other reasons, though,
4365 cf->filename = g_strdup(fname);
4367 /* Indicate whether it's a permanent or temporary file. */
4368 cf->is_tempfile = is_tempfile;
4370 /* No user changes yet. */
4371 cf->unsaved_changes = FALSE;
4373 cf->cd_t = wtap_file_type_subtype(cf->wth);
4374 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4376 cf->snap = wtap_snapshot_length(cf->wth);
4377 if (cf->snap == 0) {
4378 /* Snapshot length not known. */
4379 cf->has_snap = FALSE;
4380 cf->snap = WTAP_MAX_PACKET_SIZE;
4382 cf->has_snap = TRUE;
4384 name_ptr = g_filename_display_basename(cf->filename);
4386 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4388 /* Record whether the file is compressed.
4389 XXX - do we know this at open time? */
4390 cf->iscompressed = wtap_iscompressed(cf->wth);
4392 /* Find the size of the file. */
4393 size = wtap_file_size(cf->wth, NULL);
4395 /* Update the progress bar when it gets to this value. */
4396 progbar_nextstep = 0;
4397 /* When we reach the value that triggers a progress bar update,
4398 bump that value by this amount. */
4400 progbar_quantum = size/N_PROGBAR_UPDATES;
4401 if (progbar_quantum < MIN_QUANTUM)
4402 progbar_quantum = MIN_QUANTUM;
4404 progbar_quantum = 0;
4407 g_get_current_time(&start_time);
4410 phdr = wtap_phdr(cf->wth);
4411 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4413 fdata = frame_data_sequence_find(cf->frames, framenum);
4414 fdata->file_off = data_offset;
4417 file_pos = wtap_read_so_far(cf->wth);
4419 /* Create the progress bar if necessary.
4420 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4422 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4423 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4424 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4425 TRUE, &stop_flag, &start_time, progbar_val);
4428 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4429 when we update it, we have to run the GTK+ main loop to get it
4430 to repaint what's pending, and doing so may involve an "ioctl()"
4431 to see if there's any pending input from an X server, and doing
4432 that for every packet can be costly, especially on a big file. */
4433 if (file_pos >= progbar_nextstep) {
4434 if (progbar != NULL) {
4435 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
4436 /* update the packet bar content on the first run or frequently on very large files */
4438 if (progbar_quantum > 500000 || displayed_once == 0) {
4439 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4441 packets_bar_update();
4444 #endif /* HAVE_LIBPCAP */
4445 update_progress_dlg(progbar, progbar_val, status_str);
4447 progbar_nextstep += progbar_quantum;
4452 /* Well, the user decided to abort the rescan. Sadly, as this
4453 isn't a reread, recovering is difficult, so we'll just
4454 close the current capture. */
4458 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4459 it's not already there.
4460 XXX - yes, this is O(N), so if every packet had a different
4461 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4462 there are probably going to be a small number of encapsulation types
4464 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4467 /* Free the display name */
4470 /* We're done reading the file; destroy the progress bar if it was created. */
4471 if (progbar != NULL)
4472 destroy_progress_dlg(progbar);
4474 /* We're done reading sequentially through the file. */
4475 cf->state = FILE_READ_DONE;
4477 /* Close the sequential I/O side, to free up memory it requires. */
4478 wtap_sequential_close(cf->wth);
4480 /* compute the time it took to load the file */
4481 compute_elapsed(cf, &start_time);
4483 /* Set the file encapsulation type now; we don't know what it is until
4484 we've looked at all the packets, as we don't know until then whether
4485 there's more than one type (and thus whether it's
4486 WTAP_ENCAP_PER_PACKET). */
4487 cf->lnk_t = wtap_file_encap(cf->wth);
4489 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4492 /* Our caller will give up at this point. */
4493 return CF_READ_ABORTED;
4497 /* Put up a message box noting that the read failed somewhere along
4498 the line. Don't throw out the stuff we managed to read, though,
4502 case WTAP_ERR_UNSUPPORTED:
4503 simple_error_message_box(
4504 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4509 case WTAP_ERR_UNSUPPORTED_ENCAP:
4510 simple_error_message_box(
4511 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
4516 case WTAP_ERR_CANT_READ:
4517 simple_error_message_box(
4518 "An attempt to read from the capture file failed for"
4519 " some unknown reason.");
4522 case WTAP_ERR_SHORT_READ:
4523 simple_error_message_box(
4524 "The capture file appears to have been cut short"
4525 " in the middle of a packet.");
4528 case WTAP_ERR_BAD_FILE:
4529 simple_error_message_box(
4530 "The capture file appears to be damaged or corrupt.\n(%s)",
4535 case WTAP_ERR_DECOMPRESS:
4536 simple_error_message_box(
4537 "The compressed capture file appears to be damaged or corrupt.\n"
4543 simple_error_message_box(
4544 "An error occurred while reading the"
4545 " capture file: %s.", wtap_strerror(*err));
4548 return CF_READ_ERROR;
4554 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4555 gboolean compressed, gboolean discard_comments,
4556 gboolean dont_reopen)
4559 gchar *fname_new = NULL;
4562 addrinfo_lists_t *addr_lists;
4566 gchar *display_basename;
4573 save_callback_args_t callback_args;
4575 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4577 addr_lists = get_addrinfo_list();
4579 if (save_format == cf->cd_t && compressed == cf->iscompressed
4580 && !discard_comments && !cf->unsaved_changes
4581 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4582 /* We're saving in the format it's already in, and we're
4583 not discarding comments, and there are no changes we have
4584 in memory that aren't saved to the file, and we have no name
4585 resolution blocks to write, so we can just move or copy the raw data. */
4587 if (cf->is_tempfile) {
4588 /* The file being saved is a temporary file from a live
4589 capture, so it doesn't need to stay around under that name;
4590 first, try renaming the capture buffer file to the new name.
4591 This acts as a "safe save", in that, if the file already
4592 exists, the existing file will be removed only if the rename
4595 Sadly, on Windows, as we have the current capture file
4596 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4597 (to cause the rename to remove an existing target), as
4598 done by ws_stdio_rename() (ws_rename() is #defined to
4599 be ws_stdio_rename() on Windows) will fail.
4601 According to the MSDN documentation for CreateFile(), if,
4602 when we open a capture file, we were to directly do a CreateFile(),
4603 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4604 convert it to a file descriptor with _open_osfhandle(),
4605 that would allow the file to be renamed out from under us.
4607 However, that doesn't work in practice. Perhaps the problem
4608 is that the process doing the rename is the process that
4609 has the file open. */
4611 if (ws_rename(cf->filename, fname) == 0) {
4612 /* That succeeded - there's no need to copy the source file. */
4613 how_to_save = SAVE_WITH_MOVE;
4615 if (errno == EXDEV) {
4616 /* They're on different file systems, so we have to copy the
4618 how_to_save = SAVE_WITH_COPY;
4620 /* The rename failed, but not because they're on different
4621 file systems - put up an error message. (Or should we
4622 just punt and try to copy? The only reason why I'd
4623 expect the rename to fail and the copy to succeed would
4624 be if we didn't have permission to remove the file from
4625 the temporary directory, and that might be fixable - but
4626 is it worth requiring the user to go off and fix it?) */
4627 cf_rename_failure_alert_box(fname, errno);
4632 how_to_save = SAVE_WITH_COPY;
4635 /* It's a permanent file, so we should copy it, and not remove the
4637 how_to_save = SAVE_WITH_COPY;
4640 if (how_to_save == SAVE_WITH_COPY) {
4641 /* Copy the file, if we haven't moved it. If we're overwriting
4642 an existing file, we do it with a "safe save", by writing
4643 to a new file and, if the write succeeds, renaming the
4644 new file on top of the old file. */
4645 if (file_exists(fname)) {
4646 fname_new = g_strdup_printf("%s~", fname);
4647 if (!copy_file_binary_mode(cf->filename, fname_new))
4650 if (!copy_file_binary_mode(cf->filename, fname))
4655 /* Either we're saving in a different format or we're saving changes,
4656 such as added, modified, or removed comments, that haven't yet
4657 been written to the underlying file; we can't do that by copying
4658 or moving the capture file, we have to do it by writing the packets
4661 wtapng_section_t *shb_hdr = NULL;
4662 wtapng_iface_descriptions_t *idb_inf = NULL;
4665 shb_hdr = wtap_file_get_shb_info(cf->wth);
4666 idb_inf = wtap_file_get_idb_info(cf->wth);
4668 /* Determine what file encapsulation type we should use. */
4669 encap = wtap_dump_file_encap_type(cf->linktypes);
4671 if (file_exists(fname)) {
4672 /* We're overwriting an existing file; write out to a new file,
4673 and, if that succeeds, rename the new file on top of the
4674 old file. That makes this a "safe save", so that we don't
4675 lose the old file if we have a problem writing out the new
4676 file. (If the existing file is the current capture file,
4677 we *HAVE* to do that, otherwise we're overwriting the file
4678 from which we're reading the packets that we're writing!) */
4679 fname_new = g_strdup_printf("%s~", fname);
4680 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4681 compressed, shb_hdr, idb_inf, &err);
4683 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4684 compressed, shb_hdr, idb_inf, &err);
4690 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4694 /* Add address resolution */
4695 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4697 /* Iterate through the list of packets, processing all the packets. */
4698 callback_args.pdh = pdh;
4699 callback_args.fname = fname;
4700 callback_args.file_type = save_format;
4701 switch (process_specified_records(cf, NULL, "Saving", "packets",
4702 TRUE, save_record, &callback_args)) {
4705 /* Completed successfully. */
4709 /* The user decided to abort the saving.
4710 If we're writing to a temporary file, remove it.
4711 XXX - should we do so even if we're not writing to a
4713 wtap_dump_close(pdh, &err);
4714 if (fname_new != NULL)
4715 ws_unlink(fname_new);
4716 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4717 return CF_WRITE_ABORTED;
4720 /* Error while saving.
4721 If we're writing to a temporary file, remove it. */
4722 if (fname_new != NULL)
4723 ws_unlink(fname_new);
4724 wtap_dump_close(pdh, &err);
4728 if (!wtap_dump_close(pdh, &err)) {
4729 cf_close_failure_alert_box(fname, err);
4733 how_to_save = SAVE_WITH_WTAP;
4736 if (fname_new != NULL) {
4737 /* We wrote out to fname_new, and should rename it on top of
4738 fname. fname_new is now closed, so that should be possible even
4739 on Windows. However, on Windows, we first need to close whatever
4740 file descriptors we have open for fname. */
4742 wtap_fdclose(cf->wth);
4744 /* Now do the rename. */
4745 if (ws_rename(fname_new, fname) == -1) {
4746 /* Well, the rename failed. */
4747 cf_rename_failure_alert_box(fname, errno);
4749 /* Attempt to reopen the random file descriptor using the
4750 current file's filename. (At this point, the sequential
4751 file descriptor is closed.) */
4752 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4753 /* Oh, well, we're screwed. */
4754 display_basename = g_filename_display_basename(cf->filename);
4755 simple_error_message_box(
4756 file_open_error_message(err, FALSE), display_basename);
4757 g_free(display_basename);
4764 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4765 cf->unsaved_changes = FALSE;
4768 switch (how_to_save) {
4770 case SAVE_WITH_MOVE:
4771 /* We just moved the file, so the wtap structure refers to the
4772 new file, and all the information other than the filename
4773 and the "is temporary" status applies to the new file; just
4775 g_free(cf->filename);
4776 cf->filename = g_strdup(fname);
4777 cf->is_tempfile = FALSE;
4778 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4781 case SAVE_WITH_COPY:
4782 /* We just copied the file, s all the information other than
4783 the wtap structure, the filename, and the "is temporary"
4784 status applies to the new file; just update that. */
4785 wtap_close(cf->wth);
4786 /* Although we're just "copying" and then opening the copy, it will
4787 try all open_routine readers to open the copy, so we need to
4788 reset the cfile's open_type. */
4789 cf->open_type = WTAP_TYPE_AUTO;
4790 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4791 if (cf->wth == NULL) {
4792 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4795 g_free(cf->filename);
4796 cf->filename = g_strdup(fname);
4797 cf->is_tempfile = FALSE;
4799 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4802 case SAVE_WITH_WTAP:
4803 /* Open and read the file we saved to.
4805 XXX - this is somewhat of a waste; we already have the
4806 packets, all this gets us is updated file type information
4807 (which we could just stuff into "cf"), and having the new
4808 file be the one we have opened and from which we're reading
4809 the data, and it means we have to spend time opening and
4810 reading the file, which could be a significant amount of
4811 time if the file is large.
4813 If the capture-file-writing code were to return the
4814 seek offset of each packet it writes, we could save that
4815 in the frame_data structure for the frame, and just open
4816 the file without reading it again...
4818 ...as long as, for gzipped files, the process of writing
4819 out the file *also* generates the information needed to
4820 support fast random access to the compressed file. */
4821 /* rescan_file will cause us to try all open_routines, so
4822 reset cfile's open_type */
4823 cf->open_type = WTAP_TYPE_AUTO;
4824 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4825 /* The rescan failed; just close the file. Either
4826 a dialog was popped up for the failure, so the
4827 user knows what happened, or they stopped the
4828 rescan, in which case they know what happened. */
4834 /* If we were told to discard the comments, do so. */
4835 if (discard_comments) {
4836 /* Remove SHB comment, if any. */
4837 wtap_write_shb_comment(cf->wth, NULL);
4839 /* remove all user comments */
4840 for (framenum = 1; framenum <= cf->count; framenum++) {
4841 fdata = frame_data_sequence_find(cf->frames, framenum);
4843 fdata->flags.has_phdr_comment = FALSE;
4844 fdata->flags.has_user_comment = FALSE;
4847 if (cf->frames_user_comments) {
4848 g_tree_destroy(cf->frames_user_comments);
4849 cf->frames_user_comments = NULL;
4852 cf->packet_comment_count = 0;
4858 if (fname_new != NULL) {
4859 /* We were trying to write to a temporary file; get rid of it if it
4860 exists. (We don't care whether this fails, as, if it fails,
4861 there's not much we can do about it. I guess if it failed for
4862 a reason other than "it doesn't exist", we could report an
4863 error, so the user knows there's a junk file that they might
4864 want to clean up.) */
4865 ws_unlink(fname_new);
4868 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4869 return CF_WRITE_ERROR;
4873 cf_export_specified_packets(capture_file *cf, const char *fname,
4874 packet_range_t *range, guint save_format,
4875 gboolean compressed)
4877 gchar *fname_new = NULL;
4880 save_callback_args_t callback_args;
4881 wtapng_section_t *shb_hdr;
4882 wtapng_iface_descriptions_t *idb_inf;
4885 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4887 packet_range_process_init(range);
4889 /* We're writing out specified packets from the specified capture
4890 file to another file. Even if all captured packets are to be
4891 written, don't special-case the operation - read each packet
4892 and then write it out if it's one of the specified ones. */
4894 shb_hdr = wtap_file_get_shb_info(cf->wth);
4895 idb_inf = wtap_file_get_idb_info(cf->wth);
4897 /* Determine what file encapsulation type we should use. */
4898 encap = wtap_dump_file_encap_type(cf->linktypes);
4900 if (file_exists(fname)) {
4901 /* We're overwriting an existing file; write out to a new file,
4902 and, if that succeeds, rename the new file on top of the
4903 old file. That makes this a "safe save", so that we don't
4904 lose the old file if we have a problem writing out the new
4905 file. (If the existing file is the current capture file,
4906 we *HAVE* to do that, otherwise we're overwriting the file
4907 from which we're reading the packets that we're writing!) */
4908 fname_new = g_strdup_printf("%s~", fname);
4909 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4910 compressed, shb_hdr, idb_inf, &err);
4912 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4913 compressed, shb_hdr, idb_inf, &err);
4919 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4923 /* Add address resolution */
4924 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4926 /* Iterate through the list of packets, processing the packets we were
4929 XXX - we've already called "packet_range_process_init(range)", but
4930 "process_specified_records()" will do it again. Fortunately,
4931 that's harmless in this case, as we haven't done anything to
4932 "range" since we initialized it. */
4933 callback_args.pdh = pdh;
4934 callback_args.fname = fname;
4935 callback_args.file_type = save_format;
4936 switch (process_specified_records(cf, range, "Writing", "specified records",
4937 TRUE, save_record, &callback_args)) {
4940 /* Completed successfully. */
4944 /* The user decided to abort the saving.
4945 If we're writing to a temporary file, remove it.
4946 XXX - should we do so even if we're not writing to a
4948 wtap_dump_close(pdh, &err);
4949 if (fname_new != NULL)
4950 ws_unlink(fname_new);
4951 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4952 return CF_WRITE_ABORTED;
4956 /* Error while saving.
4957 If we're writing to a temporary file, remove it. */
4958 if (fname_new != NULL)
4959 ws_unlink(fname_new);
4960 wtap_dump_close(pdh, &err);
4964 if (!wtap_dump_close(pdh, &err)) {
4965 cf_close_failure_alert_box(fname, err);
4969 if (fname_new != NULL) {
4970 /* We wrote out to fname_new, and should rename it on top of
4971 fname; fname is now closed, so that should be possible even
4972 on Windows. Do the rename. */
4973 if (ws_rename(fname_new, fname) == -1) {
4974 /* Well, the rename failed. */
4975 cf_rename_failure_alert_box(fname, errno);
4980 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4984 if (fname_new != NULL) {
4985 /* We were trying to write to a temporary file; get rid of it if it
4986 exists. (We don't care whether this fails, as, if it fails,
4987 there's not much we can do about it. I guess if it failed for
4988 a reason other than "it doesn't exist", we could report an
4989 error, so the user knows there's a junk file that they might
4990 want to clean up.) */
4991 ws_unlink(fname_new);
4994 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4995 return CF_WRITE_ERROR;
4999 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
5000 gboolean for_writing, int file_type)
5002 gchar *display_basename;
5005 /* Wiretap error. */
5006 display_basename = g_filename_display_basename(filename);
5009 case WTAP_ERR_NOT_REGULAR_FILE:
5010 simple_error_message_box(
5011 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
5015 case WTAP_ERR_RANDOM_OPEN_PIPE:
5016 /* Seen only when opening a capture file for reading. */
5017 simple_error_message_box(
5018 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
5019 "To capture from a pipe or FIFO use wireshark -i -",
5023 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
5024 /* Seen only when opening a capture file for reading. */
5025 simple_error_message_box(
5026 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
5030 case WTAP_ERR_UNSUPPORTED:
5031 /* Seen only when opening a capture file for reading. */
5032 simple_error_message_box(
5033 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
5035 display_basename, err_info);
5039 case WTAP_ERR_CANT_WRITE_TO_PIPE:
5040 /* Seen only when opening a capture file for writing. */
5041 simple_error_message_box(
5042 "The file \"%s\" is a pipe, and %s capture files can't be "
5043 "written to a pipe.",
5044 display_basename, wtap_file_type_subtype_string(file_type));
5047 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
5048 /* Seen only when opening a capture file for writing. */
5049 simple_error_message_box(
5050 "Wireshark doesn't support writing capture files in that format.");
5053 case WTAP_ERR_UNSUPPORTED_ENCAP:
5055 simple_error_message_box("Wireshark can't save this capture in that format.");
5057 simple_error_message_box(
5058 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
5060 display_basename, err_info);
5065 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
5067 simple_error_message_box(
5068 "Wireshark can't save this capture in that format.");
5070 simple_error_message_box(
5071 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
5076 case WTAP_ERR_BAD_FILE:
5077 /* Seen only when opening a capture file for reading. */
5078 simple_error_message_box(
5079 "The file \"%s\" appears to be damaged or corrupt.\n"
5081 display_basename, err_info);
5085 case WTAP_ERR_CANT_OPEN:
5087 simple_error_message_box(
5088 "The file \"%s\" could not be created for some unknown reason.",
5091 simple_error_message_box(
5092 "The file \"%s\" could not be opened for some unknown reason.",
5097 case WTAP_ERR_SHORT_READ:
5098 simple_error_message_box(
5099 "The file \"%s\" appears to have been cut short"
5100 " in the middle of a packet or other data.",
5104 case WTAP_ERR_SHORT_WRITE:
5105 simple_error_message_box(
5106 "A full header couldn't be written to the file \"%s\".",
5110 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
5111 simple_error_message_box(
5112 "This file type cannot be written as a compressed file.");
5115 case WTAP_ERR_DECOMPRESS:
5116 simple_error_message_box(
5117 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
5118 "(%s)", display_basename, err_info);
5123 simple_error_message_box(
5124 "The file \"%s\" could not be %s: %s.",
5126 for_writing ? "created" : "opened",
5127 wtap_strerror(err));
5130 g_free(display_basename);
5133 open_failure_alert_box(filename, err, for_writing);
5138 * XXX - whether we mention the source pathname, the target pathname,
5139 * or both depends on the error and on what we find if we look for
5140 * one or both of them.
5143 cf_rename_failure_alert_box(const char *filename, int err)
5145 gchar *display_basename;
5147 display_basename = g_filename_display_basename(filename);
5151 /* XXX - should check whether the source exists and, if not,
5152 report it as the problem and, if so, report the destination
5154 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
5159 /* XXX - if we're doing a rename after a safe save, we should
5160 probably say something else. */
5161 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
5166 /* XXX - this should probably mention both the source and destination
5168 simple_error_message_box("The file \"%s\" could not be moved: %s.",
5169 display_basename, wtap_strerror(err));
5172 g_free(display_basename);
5175 /* Check for write errors - if the file is being written to an NFS server,
5176 a write error may not show up until the file is closed, as NFS clients
5177 might not send writes to the server until the "write()" call finishes,
5178 so that the write may fail on the server but the "write()" may succeed. */
5180 cf_close_failure_alert_box(const char *filename, int err)
5182 gchar *display_basename;
5185 /* Wiretap error. */
5186 display_basename = g_filename_display_basename(filename);
5189 case WTAP_ERR_CANT_CLOSE:
5190 simple_error_message_box(
5191 "The file \"%s\" couldn't be closed for some unknown reason.",
5195 case WTAP_ERR_SHORT_WRITE:
5196 simple_error_message_box(
5197 "Not all the packets could be written to the file \"%s\".",
5202 simple_error_message_box(
5203 "An error occurred while closing the file \"%s\": %s.",
5204 display_basename, wtap_strerror(err));
5207 g_free(display_basename);
5210 We assume that a close error from the OS is really a write error. */
5211 write_failure_alert_box(filename, err);
5215 /* Reload the current capture file. */
5217 cf_reload(capture_file *cf) {
5219 gboolean is_tempfile;
5222 /* If the file could be opened, "cf_open()" calls "cf_close()"
5223 to get rid of state for the old capture file before filling in state
5224 for the new capture file. "cf_close()" will remove the file if
5225 it's a temporary file; we don't want that to happen (for one thing,
5226 it'd prevent subsequent reopens from working). Remember whether it's
5227 a temporary file, mark it as not being a temporary file, and then
5228 reopen it as the type of file it was.
5230 Also, "cf_close()" will free "cf->filename", so we must make
5231 a copy of it first. */
5232 filename = g_strdup(cf->filename);
5233 is_tempfile = cf->is_tempfile;
5234 cf->is_tempfile = FALSE;
5235 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5236 switch (cf_read(cf, TRUE)) {
5240 /* Just because we got an error, that doesn't mean we were unable
5241 to read any of the file; we handle what we could get from the
5245 case CF_READ_ABORTED:
5246 /* The user bailed out of re-reading the capture file; the
5247 capture file has been closed - just free the capture file name
5248 string and return (without changing the last containing
5254 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5255 Instead, the file was left open, so we should restore "cf->is_tempfile"
5258 XXX - change the menu? Presumably "cf_open()" will do that;
5259 make sure it does! */
5260 cf->is_tempfile = is_tempfile;
5262 /* "cf_open()" made a copy of the file name we handed it, so
5263 we should free up our copy. */
5273 * indent-tabs-mode: nil
5276 * ex: set shiftwidth=2 tabstop=8 expandtab:
5277 * :indentSize=2:tabSize=8:noTabs=true: