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.
41 #include <wsutil/tempfile.h>
42 #include <wsutil/file_util.h>
43 #include <wsutil/filesystem.h>
44 #include <wsutil/ws_version_info.h>
46 #include <wiretap/merge.h>
48 #include <epan/exceptions.h>
49 #include <epan/epan-int.h>
50 #include <epan/epan.h>
51 #include <epan/column.h>
52 #include <epan/packet.h>
53 #include <epan/column-utils.h>
54 #include <epan/expert.h>
55 #include <epan/prefs.h>
56 #include <epan/dfilter/dfilter.h>
57 #include <epan/epan_dissect.h>
59 #include <epan/dissectors/packet-ber.h>
60 #include <epan/timestamp.h>
61 #include <epan/dfilter/dfilter-macro.h>
62 #include <epan/strutil.h>
63 #include <epan/addr_resolv.h>
66 #include "color_filters.h"
70 #include "frame_tvbuff.h"
72 #include "ui/alert_box.h"
73 #include "ui/simple_dialog.h"
74 #include "ui/main_statusbar.h"
75 #include "ui/progress_dlg.h"
76 #include "ui/ui_util.h"
78 /* Needed for addrinfo */
79 #ifdef HAVE_SYS_TYPES_H
80 # include <sys/types.h>
83 #ifdef HAVE_SYS_SOCKET_H
84 #include <sys/socket.h>
87 #ifdef HAVE_NETINET_IN_H
88 # include <netinet/in.h>
95 #ifdef HAVE_WINSOCK2_H
96 # include <winsock2.h>
99 #if defined(_WIN32) && defined(INET6)
100 # include <ws2tcpip.h>
104 gboolean auto_scroll_live; /* GTK+ only? */
107 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
108 column_info *cinfo, gint64 offset);
110 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
117 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
119 static void match_subtree_text(proto_node *node, gpointer data);
120 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
122 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
124 static match_result match_narrow(capture_file *cf, frame_data *fdata,
126 static match_result match_wide(capture_file *cf, frame_data *fdata,
128 static match_result match_binary(capture_file *cf, frame_data *fdata,
130 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
132 static match_result match_marked(capture_file *cf, frame_data *fdata,
134 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
136 static gboolean find_packet(capture_file *cf,
137 match_result (*match_function)(capture_file *, frame_data *, void *),
138 void *criterion, search_direction dir);
140 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
142 static void cf_open_failure_alert_box(const char *filename, int err,
143 gchar *err_info, gboolean for_writing,
145 static void cf_rename_failure_alert_box(const char *filename, int err);
146 static void cf_close_failure_alert_box(const char *filename, int err);
147 static void ref_time_packets(capture_file *cf);
148 /* Update the progress bar this many times when reading a file. */
149 #define N_PROGBAR_UPDATES 100
150 /* We read around 200k/100ms don't update the progress bar more often than that */
151 #define MIN_QUANTUM 200000
152 #define MIN_NUMBER_OF_PACKET 1500
155 * We could probably use g_signal_...() instead of the callbacks below but that
156 * would require linking our CLI programs to libgobject and creating an object
157 * instance for the signals.
160 cf_callback_t cb_fct;
162 } cf_callback_data_t;
164 static GList *cf_callbacks = NULL;
167 cf_callback_invoke(int event, gpointer data)
169 cf_callback_data_t *cb;
170 GList *cb_item = cf_callbacks;
172 /* there should be at least one interested */
173 g_assert(cb_item != NULL);
175 while (cb_item != NULL) {
176 cb = (cf_callback_data_t *)cb_item->data;
177 cb->cb_fct(event, data, cb->user_data);
178 cb_item = g_list_next(cb_item);
184 cf_callback_add(cf_callback_t func, gpointer user_data)
186 cf_callback_data_t *cb;
188 cb = g_new(cf_callback_data_t,1);
190 cb->user_data = user_data;
192 cf_callbacks = g_list_prepend(cf_callbacks, cb);
196 cf_callback_remove(cf_callback_t func, gpointer user_data)
198 cf_callback_data_t *cb;
199 GList *cb_item = cf_callbacks;
201 while (cb_item != NULL) {
202 cb = (cf_callback_data_t *)cb_item->data;
203 if (cb->cb_fct == func && cb->user_data == user_data) {
204 cf_callbacks = g_list_remove(cf_callbacks, cb);
208 cb_item = g_list_next(cb_item);
211 g_assert_not_reached();
215 cf_timestamp_auto_precision(capture_file *cf)
219 /* don't try to get the file's precision if none is opened */
220 if (cf->state == FILE_CLOSED) {
224 /* Set the column widths of those columns that show the time in
225 "command-line-specified" format. */
226 for (i = 0; i < cf->cinfo.num_cols; i++) {
227 if (col_has_time_fmt(&cf->cinfo, i)) {
228 packet_list_resize_column(i);
234 cf_get_computed_elapsed(capture_file *cf)
236 return cf->computed_elapsed;
240 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
243 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
248 g_get_current_time(&time_now);
250 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
251 time_now.tv_usec - start_time->tv_usec;
253 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
256 static const nstime_t *
257 ws_get_frame_ts(void *data, guint32 frame_num)
259 capture_file *cf = (capture_file *) data;
261 if (cf->prev_dis && cf->prev_dis->num == frame_num)
262 return &cf->prev_dis->abs_ts;
264 if (cf->prev_cap && cf->prev_cap->num == frame_num)
265 return &cf->prev_cap->abs_ts;
268 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
270 return (fd) ? &fd->abs_ts : NULL;
277 ws_get_user_comment(void *data, const frame_data *fd)
279 capture_file *cf = (capture_file *) data;
281 return cf_get_user_packet_comment(cf, fd);
285 ws_epan_new(capture_file *cf)
287 epan_t *epan = epan_new();
290 epan->get_frame_ts = ws_get_frame_ts;
291 epan->get_interface_name = cap_file_get_interface_name;
292 epan->get_user_comment = ws_get_user_comment;
298 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
303 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
307 /* The open succeeded. Close whatever capture file we had open,
308 and fill in the information for this file. */
311 /* Initialize the packet header. */
312 wtap_phdr_init(&cf->phdr);
314 /* XXX - we really want to initialize this after we've read all
315 the packets, so we know how much we'll ultimately need. */
316 ws_buffer_init(&cf->buf, 1500);
318 /* Create new epan session for dissection.
319 * (The old one was freed in cf_close().)
321 cf->epan = ws_epan_new(cf);
323 /* We're about to start reading the file. */
324 cf->state = FILE_READ_IN_PROGRESS;
329 /* Set the file name because we need it to set the follow stream filter.
330 XXX - is that still true? We need it for other reasons, though,
332 cf->filename = g_strdup(fname);
334 /* Indicate whether it's a permanent or temporary file. */
335 cf->is_tempfile = is_tempfile;
337 /* No user changes yet. */
338 cf->unsaved_changes = FALSE;
340 cf->computed_elapsed = 0;
342 cf->cd_t = wtap_file_type_subtype(cf->wth);
343 cf->open_type = type;
344 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
346 cf->packet_comment_count = 0;
347 cf->displayed_count = 0;
348 cf->marked_count = 0;
349 cf->ignored_count = 0;
350 cf->ref_time_count = 0;
351 cf->drops_known = FALSE;
353 cf->snap = wtap_snapshot_length(cf->wth);
355 /* Snapshot length not known. */
356 cf->has_snap = FALSE;
357 cf->snap = WTAP_MAX_PACKET_SIZE;
361 /* Allocate a frame_data_sequence for the frames in this file */
362 cf->frames = new_frame_data_sequence();
364 nstime_set_zero(&cf->elapsed_time);
370 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
371 cf_timestamp_auto_precision(cf);
373 packet_list_queue_draw();
374 cf_callback_invoke(cf_cb_file_opened, cf);
376 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
377 /* tell the BER dissector the file name */
378 ber_set_filename(cf->filename);
381 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
382 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
387 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
392 * Add an encapsulation type to cf->linktypes.
395 cf_add_encapsulation_type(capture_file *cf, int encap)
399 for (i = 0; i < cf->linktypes->len; i++) {
400 if (g_array_index(cf->linktypes, gint, i) == encap)
401 return; /* it's already there */
403 /* It's not already there - add it. */
404 g_array_append_val(cf->linktypes, encap);
407 /* Reset everything to a pristine state */
409 cf_close(capture_file *cf)
411 cf->stop_flag = FALSE;
412 if (cf->state == FILE_CLOSED)
413 return; /* Nothing to do */
415 /* Die if we're in the middle of reading a file. */
416 g_assert(cf->state != FILE_READ_IN_PROGRESS);
418 cf_callback_invoke(cf_cb_file_closing, cf);
420 /* close things, if not already closed before */
421 color_filters_cleanup();
427 /* We have no file open... */
428 if (cf->filename != NULL) {
429 /* If it's a temporary file, remove it. */
431 ws_unlink(cf->filename);
432 g_free(cf->filename);
435 /* ...which means we have no changes to that file to save. */
436 cf->unsaved_changes = FALSE;
438 /* no open_routine type */
439 cf->open_type = WTAP_TYPE_AUTO;
441 /* Clean up the packet header. */
442 wtap_phdr_cleanup(&cf->phdr);
444 /* Free up the packet buffer. */
445 ws_buffer_free(&cf->buf);
447 dfilter_free(cf->rfcode);
449 if (cf->frames != NULL) {
450 free_frame_data_sequence(cf->frames);
453 #ifdef WANT_PACKET_EDITOR
454 if (cf->edited_frames) {
455 g_tree_destroy(cf->edited_frames);
456 cf->edited_frames = NULL;
459 if (cf->frames_user_comments) {
460 g_tree_destroy(cf->frames_user_comments);
461 cf->frames_user_comments = NULL;
463 cf_unselect_packet(cf); /* nothing to select */
464 cf->first_displayed = 0;
465 cf->last_displayed = 0;
467 /* No frames, no frame selected, no field in that frame selected. */
469 cf->current_frame = 0;
471 cf->finfo_selected = NULL;
473 /* No frame link-layer types, either. */
474 if (cf->linktypes != NULL) {
475 g_array_free(cf->linktypes, TRUE);
476 cf->linktypes = NULL;
479 /* Clear the packet list. */
480 packet_list_freeze();
485 nstime_set_zero(&cf->elapsed_time);
487 reset_tap_listeners();
492 /* We have no file open. */
493 cf->state = FILE_CLOSED;
495 cf_callback_invoke(cf_cb_file_closed, cf);
499 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
503 progbar_val = (gfloat) file_pos / (gfloat) size;
504 if (progbar_val > 1.0) {
506 /* The file probably grew while we were reading it.
507 * Update file size, and try again.
509 size = wtap_file_size(cf->wth, NULL);
512 progbar_val = (gfloat) file_pos / (gfloat) size;
514 /* If it's still > 1, either "wtap_file_size()" failed (in which
515 * case there's not much we can do about it), or the file
516 * *shrank* (in which case there's not much we can do about
517 * it); just clip the progress value at 1.0.
519 if (progbar_val > 1.0f)
523 g_snprintf(status_str, status_size,
524 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
525 file_pos / 1024, size / 1024);
531 cf_read(capture_file *cf, gboolean reloading)
536 progdlg_t *progbar = NULL;
540 volatile gboolean create_proto_tree;
544 /* Compile the current display filter.
545 * We assume this will not fail since cf->dfilter is only set in
546 * cf_filter IFF the filter was valid.
548 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
549 g_assert(!cf->dfilter || (compiled && dfcode));
551 /* Get the union of the flags for all tap listeners. */
552 tap_flags = union_of_tap_listener_flags();
554 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
556 reset_tap_listeners();
558 name_ptr = g_filename_display_basename(cf->filename);
561 cf_callback_invoke(cf_cb_file_reload_started, cf);
563 cf_callback_invoke(cf_cb_file_read_started, cf);
565 /* Record whether the file is compressed.
566 XXX - do we know this at open time? */
567 cf->iscompressed = wtap_iscompressed(cf->wth);
569 /* The packet list window will be empty until the file is completly loaded */
570 packet_list_freeze();
572 cf->stop_flag = FALSE;
573 g_get_current_time(&start_time);
575 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
579 int displayed_once = 0;
587 gint64 progbar_quantum;
588 gint64 progbar_nextstep;
590 gchar status_str[100];
594 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
596 /* Find the size of the file. */
597 size = wtap_file_size(cf->wth, NULL);
599 /* Update the progress bar when it gets to this value. */
600 progbar_nextstep = 0;
601 /* When we reach the value that triggers a progress bar update,
602 bump that value by this amount. */
604 progbar_quantum = size/N_PROGBAR_UPDATES;
605 if (progbar_quantum < MIN_QUANTUM)
606 progbar_quantum = MIN_QUANTUM;
610 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
613 file_pos = wtap_read_so_far(cf->wth);
615 /* Create the progress bar if necessary.
616 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
618 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
619 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
621 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
622 TRUE, &cf->stop_flag, &start_time, progbar_val);
624 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
625 TRUE, &cf->stop_flag, &start_time, progbar_val);
628 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
629 when we update it, we have to run the GTK+ main loop to get it
630 to repaint what's pending, and doing so may involve an "ioctl()"
631 to see if there's any pending input from an X server, and doing
632 that for every packet can be costly, especially on a big file. */
633 if (file_pos >= progbar_nextstep) {
634 if (progbar != NULL) {
635 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
636 /* update the packet bar content on the first run or frequently on very large files */
638 if (progbar_quantum > 500000 || displayed_once == 0) {
639 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
641 packets_bar_update();
644 #endif /* HAVE_LIBPCAP */
645 update_progress_dlg(progbar, progbar_val, status_str);
647 progbar_nextstep += progbar_quantum;
652 /* Well, the user decided to abort the read. He/She will be warned and
653 it might be enough for him/her to work with the already loaded
655 This is especially true for very large capture files, where you don't
656 want to wait loading the whole file (which may last minutes or even
657 hours even on fast machines) just to see that it was the wrong file. */
660 read_packet(cf, dfcode, &edt, cinfo, data_offset);
663 CATCH(OutOfMemoryError) {
664 simple_message_box(ESD_TYPE_ERROR, NULL,
665 "More information and workarounds can be found at\n"
666 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
667 "Sorry, but Wireshark has run out of memory and has to terminate now.");
669 /* Could we close the current capture and free up memory from that? */
671 /* we have to terminate, as we cannot recover from the memory error */
677 /* Free the display name */
680 /* Cleanup and release all dfilter resources */
681 if (dfcode != NULL) {
682 dfilter_free(dfcode);
685 epan_dissect_cleanup(&edt);
687 /* We're done reading the file; destroy the progress bar if it was created. */
689 destroy_progress_dlg(progbar);
691 /* We're done reading sequentially through the file. */
692 cf->state = FILE_READ_DONE;
694 /* Close the sequential I/O side, to free up memory it requires. */
695 wtap_sequential_close(cf->wth);
697 /* Allow the protocol dissectors to free up memory that they
698 * don't need after the sequential run-through of the packets. */
699 postseq_cleanup_all_protocols();
701 /* compute the time it took to load the file */
702 compute_elapsed(cf, &start_time);
704 /* Set the file encapsulation type now; we don't know what it is until
705 we've looked at all the packets, as we don't know until then whether
706 there's more than one type (and thus whether it's
707 WTAP_ENCAP_PER_PACKET). */
708 cf->lnk_t = wtap_file_encap(cf->wth);
710 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
715 cf_callback_invoke(cf_cb_file_reload_finished, cf);
717 cf_callback_invoke(cf_cb_file_read_finished, cf);
719 /* If we have any displayed packets to select, select the first of those
720 packets by making the first row the selected row. */
721 if (cf->first_displayed != 0) {
722 packet_list_select_first_row();
726 simple_message_box(ESD_TYPE_WARN, NULL,
727 "The remaining packets in the file were discarded.\n"
729 "As a lot of packets from the original file will be missing,\n"
730 "remember to be careful when saving the current content to a file.\n",
731 "File loading was cancelled.");
732 return CF_READ_ERROR;
736 /* Put up a message box noting that the read failed somewhere along
737 the line. Don't throw out the stuff we managed to read, though,
741 case WTAP_ERR_UNSUPPORTED:
742 simple_error_message_box(
743 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
744 err_info != NULL ? err_info : "no information supplied");
748 case WTAP_ERR_SHORT_READ:
749 simple_error_message_box(
750 "The capture file appears to have been cut short"
751 " in the middle of a packet.");
754 case WTAP_ERR_BAD_FILE:
755 simple_error_message_box(
756 "The capture file appears to be damaged or corrupt.\n(%s)",
757 err_info != NULL ? err_info : "no information supplied");
761 case WTAP_ERR_DECOMPRESS:
762 simple_error_message_box(
763 "The compressed capture file appears to be damaged or corrupt.\n(%s)",
764 err_info != NULL ? err_info : "no information supplied");
769 simple_error_message_box(
770 "An error occurred while reading the"
771 " capture file: %s.", wtap_strerror(err));
774 return CF_READ_ERROR;
781 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
784 volatile int newly_displayed_packets = 0;
787 gboolean create_proto_tree;
791 /* Compile the current display filter.
792 * We assume this will not fail since cf->dfilter is only set in
793 * cf_filter IFF the filter was valid.
795 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
796 g_assert(!cf->dfilter || (compiled && dfcode));
798 /* Get the union of the flags for all tap listeners. */
799 tap_flags = union_of_tap_listener_flags();
801 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
805 packet_list_check_end();
806 /* Don't freeze/thaw the list when doing live capture */
807 /*packet_list_freeze();*/
809 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
811 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
814 gint64 data_offset = 0;
817 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
819 while (to_read != 0) {
820 wtap_cleareof(cf->wth);
821 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
824 if (cf->state == FILE_READ_ABORTED) {
825 /* Well, the user decided to exit Wireshark. Break out of the
826 loop, and let the code below (which is called even if there
827 aren't any packets left to read) exit. */
830 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
831 newly_displayed_packets++;
836 CATCH(OutOfMemoryError) {
837 simple_message_box(ESD_TYPE_ERROR, NULL,
838 "More information and workarounds can be found at\n"
839 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
840 "Sorry, but Wireshark has run out of memory and has to terminate now.");
842 /* Could we close the current capture and free up memory from that? */
843 return CF_READ_ABORTED;
845 /* we have to terminate, as we cannot recover from the memory error */
851 /* Update the file encapsulation; it might have changed based on the
852 packets we've read. */
853 cf->lnk_t = wtap_file_encap(cf->wth);
855 /* Cleanup and release all dfilter resources */
856 if (dfcode != NULL) {
857 dfilter_free(dfcode);
860 epan_dissect_cleanup(&edt);
862 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
863 cf->count, cf->state, *err);*/
865 /* Don't freeze/thaw the list when doing live capture */
866 /*packet_list_thaw();*/
867 /* With the new packet list the first packet
868 * isn't automatically selected.
870 if (!cf->current_frame)
871 packet_list_select_first_row();
873 /* moving to the end of the packet list - if the user requested so and
874 we have some new packets. */
875 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
876 packet_list_moveto_end();
878 if (cf->state == FILE_READ_ABORTED) {
879 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
880 so that our caller can kill off the capture child process;
881 this will cause an EOF on the pipe from the child, so
882 "cf_finish_tail()" will be called, and it will clean up
884 return CF_READ_ABORTED;
885 } else if (*err != 0) {
886 /* We got an error reading the capture file.
887 XXX - pop up a dialog box instead? */
888 if (err_info != NULL) {
889 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
890 wtap_strerror(*err), cf->filename, err_info);
893 g_warning("Error \"%s\" while reading \"%s\"",
894 wtap_strerror(*err), cf->filename);
896 return CF_READ_ERROR;
902 cf_fake_continue_tail(capture_file *cf) {
903 cf->state = FILE_READ_DONE;
907 cf_finish_tail(capture_file *cf, int *err)
914 gboolean create_proto_tree;
918 /* Compile the current display filter.
919 * We assume this will not fail since cf->dfilter is only set in
920 * cf_filter IFF the filter was valid.
922 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
923 g_assert(!cf->dfilter || (compiled && dfcode));
925 /* Get the union of the flags for all tap listeners. */
926 tap_flags = union_of_tap_listener_flags();
927 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
929 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
931 if (cf->wth == NULL) {
933 return CF_READ_ERROR;
936 packet_list_check_end();
937 /* Don't freeze/thaw the list when doing live capture */
938 /*packet_list_freeze();*/
940 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
942 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
943 if (cf->state == FILE_READ_ABORTED) {
944 /* Well, the user decided to abort the read. Break out of the
945 loop, and let the code below (which is called even if there
946 aren't any packets left to read) exit. */
949 read_packet(cf, dfcode, &edt, cinfo, data_offset);
952 /* Cleanup and release all dfilter resources */
953 if (dfcode != NULL) {
954 dfilter_free(dfcode);
957 epan_dissect_cleanup(&edt);
959 /* Don't freeze/thaw the list when doing live capture */
960 /*packet_list_thaw();*/
962 if (cf->state == FILE_READ_ABORTED) {
963 /* Well, the user decided to abort the read. We're only called
964 when the child capture process closes the pipe to us (meaning
965 it's probably exited), so we can just close the capture
966 file; we return CF_READ_ABORTED so our caller can do whatever
967 is appropriate when that happens. */
969 return CF_READ_ABORTED;
972 if (auto_scroll_live && cf->count != 0)
973 packet_list_moveto_end();
975 /* We're done reading sequentially through the file. */
976 cf->state = FILE_READ_DONE;
978 /* We're done reading sequentially through the file; close the
979 sequential I/O side, to free up memory it requires. */
980 wtap_sequential_close(cf->wth);
982 /* Allow the protocol dissectors to free up memory that they
983 * don't need after the sequential run-through of the packets. */
984 postseq_cleanup_all_protocols();
986 /* Update the file encapsulation; it might have changed based on the
987 packets we've read. */
988 cf->lnk_t = wtap_file_encap(cf->wth);
990 /* Update the details in the file-set dialog, as the capture file
991 * has likely grown since we first stat-ed it */
992 fileset_update_file(cf->filename);
995 /* We got an error reading the capture file.
996 XXX - pop up a dialog box? */
997 if (err_info != NULL) {
998 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
999 wtap_strerror(*err), cf->filename, err_info);
1002 g_warning("Error \"%s\" while reading \"%s\"",
1003 wtap_strerror(*err), cf->filename);
1005 return CF_READ_ERROR;
1010 #endif /* HAVE_LIBPCAP */
1013 cf_get_display_name(capture_file *cf)
1017 /* Return a name to use in displays */
1018 if (!cf->is_tempfile) {
1019 /* Get the last component of the file name, and use that. */
1021 displayname = g_filename_display_basename(cf->filename);
1023 displayname=g_strdup("(No file)");
1026 /* The file we read is a temporary file from a live capture or
1027 a merge operation; we don't mention its name, but, if it's
1028 from a capture, give the source of the capture. */
1030 displayname = g_strdup(cf->source);
1032 displayname = g_strdup("(Untitled)");
1038 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1044 cf->source = g_strdup(source);
1046 cf->source = g_strdup("");
1050 const gchar *cf_get_tempfile_source(capture_file *cf) {
1058 /* XXX - use a macro instead? */
1060 cf_get_packet_count(capture_file *cf)
1065 /* XXX - use a macro instead? */
1067 cf_is_tempfile(capture_file *cf)
1069 return cf->is_tempfile;
1072 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1074 cf->is_tempfile = is_tempfile;
1078 /* XXX - use a macro instead? */
1079 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1081 cf->drops_known = drops_known;
1084 /* XXX - use a macro instead? */
1085 void cf_set_drops(capture_file *cf, guint32 drops)
1090 /* XXX - use a macro instead? */
1091 gboolean cf_get_drops_known(capture_file *cf)
1093 return cf->drops_known;
1096 /* XXX - use a macro instead? */
1097 guint32 cf_get_drops(capture_file *cf)
1102 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1104 cf->rfcode = rfcode;
1108 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1109 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1110 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1114 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1115 &cf->ref, cf->prev_dis);
1116 cf->prev_cap = fdata;
1118 if (dfcode != NULL) {
1119 epan_dissect_prime_dfilter(edt, dfcode);
1122 /* Dissect the frame. */
1123 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1125 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1126 if (dfcode != NULL) {
1127 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1129 if (fdata->flags.passed_dfilter) {
1130 /* This frame passed the display filter but it may depend on other
1131 * (potentially not displayed) frames. Find those frames and mark them
1134 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1137 fdata->flags.passed_dfilter = 1;
1139 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1140 cf->displayed_count++;
1142 if (add_to_packet_list) {
1143 /* We fill the needed columns from new_packet_list */
1144 row = packet_list_append(cinfo, fdata);
1147 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1149 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1150 cf->prev_dis = fdata;
1152 /* If we haven't yet seen the first frame, this is it.
1154 XXX - we must do this before we add the row to the display,
1155 as, if the display's GtkCList's selection mode is
1156 GTK_SELECTION_BROWSE, when the first entry is added to it,
1157 "cf_select_packet()" will be called, and it will fetch the row
1158 data for the 0th row, and will get a null pointer rather than
1159 "fdata", as "gtk_clist_append()" won't yet have returned and
1160 thus "gtk_clist_set_row_data()" won't yet have been called.
1162 We thus need to leave behind bread crumbs so that
1163 "cf_select_packet()" can find this frame. See the comment
1164 in "cf_select_packet()". */
1165 if (cf->first_displayed == 0)
1166 cf->first_displayed = fdata->num;
1168 /* This is the last frame we've seen so far. */
1169 cf->last_displayed = fdata->num;
1172 epan_dissect_reset(edt);
1176 /* read in a new packet */
1177 /* returns the row of the new packet in the packet list or -1 if not displayed */
1179 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1180 column_info *cinfo, gint64 offset)
1182 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1183 const guint8 *buf = wtap_buf_ptr(cf->wth);
1190 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1191 it's not already there.
1192 XXX - yes, this is O(N), so if every packet had a different
1193 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1194 there are probably going to be a small number of encapsulation types
1196 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1198 /* The frame number of this packet is one more than the count of
1199 frames in the file so far. */
1200 framenum = cf->count + 1;
1202 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1206 epan_dissect_t rf_edt;
1208 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1209 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1210 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1211 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1212 epan_dissect_cleanup(&rf_edt);
1216 /* This does a shallow copy of fdlocal, which is good enough. */
1217 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1220 if (phdr->opt_comment != NULL)
1221 cf->packet_comment_count++;
1222 cf->f_datalen = offset + fdlocal.cap_len;
1224 if (!cf->redissecting) {
1225 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1226 cinfo, phdr, buf, TRUE);
1234 typedef struct _callback_data_t {
1236 gint64 progbar_nextstep;
1237 gint64 progbar_quantum;
1238 GTimeVal start_time;
1245 merge_callback(merge_event event, int num _U_,
1246 const merge_in_file_t in_files[], const guint in_file_count,
1250 callback_data_t *cb_data = (callback_data_t*) data;
1252 g_assert(cb_data != NULL);
1256 case MERGE_EVENT_INPUT_FILES_OPENED:
1260 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1264 case MERGE_EVENT_READY_TO_MERGE:
1265 /* Get the sum of the sizes of all the files. */
1266 for (i = 0; i < in_file_count; i++)
1267 cb_data->f_len += in_files[i].size;
1269 /* When we reach the value that triggers a progress bar update,
1270 bump that value by this amount. */
1271 cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES;
1273 g_get_current_time(&cb_data->start_time);
1276 case MERGE_EVENT_PACKET_WAS_READ:
1278 gint64 data_offset = 0;
1280 /* Get the sum of the data offsets in all of the files. */
1282 for (i = 0; i < in_file_count; i++)
1283 data_offset += in_files[i].data_offset;
1285 /* Create the progress bar if necessary.
1286 We check on every iteration of the loop, so that it takes no
1287 longer than the standard time to create it (otherwise, for a
1288 large file, we might take considerably longer than that standard
1289 time in order to get to the next progress bar step). */
1290 if (cb_data->progbar == NULL) {
1291 cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1292 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1295 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1296 when we update it, we have to run the GTK+ main loop to get it
1297 to repaint what's pending, and doing so may involve an "ioctl()"
1298 to see if there's any pending input from an X server, and doing
1299 that for every packet can be costly, especially on a big file. */
1300 if (data_offset >= cb_data->progbar_nextstep) {
1302 gint64 file_pos = 0;
1303 /* Get the sum of the seek positions in all of the files. */
1304 for (i = 0; i < in_file_count; i++)
1305 file_pos += wtap_read_so_far(in_files[i].wth);
1307 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1308 if (progbar_val > 1.0f) {
1309 /* Some file probably grew while we were reading it.
1310 That "shouldn't happen", so we'll just clip the progress
1315 if (cb_data->progbar != NULL) {
1316 gchar status_str[100];
1317 g_snprintf(status_str, sizeof(status_str),
1318 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1319 file_pos / 1024, cb_data->f_len / 1024);
1320 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1322 cb_data->progbar_nextstep += cb_data->progbar_quantum;
1327 case MERGE_EVENT_DONE:
1328 /* We're done merging the files; destroy the progress bar if it was created. */
1329 if (cb_data->progbar != NULL)
1330 destroy_progress_dlg(cb_data->progbar);
1334 return cb_data->stop_flag;
1340 cf_merge_files(char **out_filenamep, int in_file_count,
1341 char *const *in_filenames, int file_type, gboolean do_append)
1347 gchar *err_info = NULL;
1349 merge_result status;
1350 merge_progress_callback_t cb;
1353 if (*out_filenamep != NULL) {
1354 out_filename = *out_filenamep;
1355 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1359 out_fd = create_tempfile(&tmpname, "wireshark");
1362 out_filename = g_strdup(tmpname);
1363 *out_filenamep = out_filename;
1366 cf_open_failure_alert_box(out_filename, err, NULL, TRUE, file_type);
1370 /* prepare our callback routine */
1371 cb.callback_func = merge_callback;
1372 cb.data = g_malloc0(sizeof(callback_data_t));
1374 /* merge the files */
1375 status = merge_files(out_fd, out_filename, file_type,
1376 (const char *const *) in_filenames, in_file_count,
1377 do_append, IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1378 "Wireshark", &cb, &err, &err_info, &err_fileno);
1386 case MERGE_USER_ABORTED:
1387 /* this isn't really an error, though we will return CF_ERROR later */
1390 case MERGE_ERR_CANT_OPEN_INFILE:
1391 cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
1395 case MERGE_ERR_CANT_OPEN_OUTFILE:
1396 cf_open_failure_alert_box(out_filename, err, err_info, TRUE,
1401 case MERGE_ERR_CANT_READ_INFILE: /* fall through */
1402 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1403 case MERGE_ERR_CANT_WRITE_OUTFILE:
1404 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1406 simple_error_message_box("%s", err_info ? err_info : "unknown error");
1412 if (status != MERGE_OK) {
1413 /* Callers aren't expected to treat an error or an explicit abort
1414 differently - we put up error dialogs ourselves, so they don't
1422 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1424 const char *filter_new = dftext ? dftext : "";
1425 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1428 GTimeVal start_time;
1430 /* if new filter equals old one, do nothing unless told to do so */
1431 if (!force && strcmp(filter_new, filter_old) == 0) {
1437 if (dftext == NULL) {
1438 /* The new filter is an empty filter (i.e., display all packets).
1439 * so leave dfcode==NULL
1443 * We have a filter; make a copy of it (as we'll be saving it),
1444 * and try to compile it.
1446 dftext = g_strdup(dftext);
1447 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1448 /* The attempt failed; report an error. */
1449 simple_message_box(ESD_TYPE_ERROR, NULL,
1450 "See the help for a description of the display filter syntax.",
1451 "\"%s\" isn't a valid display filter: %s",
1459 if (dfcode == NULL) {
1460 /* Yes - free the filter text, and set it to null. */
1466 /* We have a valid filter. Replace the current filter. */
1467 g_free(cf->dfilter);
1468 cf->dfilter = dftext;
1469 g_get_current_time(&start_time);
1472 /* Now rescan the packet list, applying the new filter, but not
1473 throwing away information constructed on a previous pass. */
1474 if (dftext == NULL) {
1475 rescan_packets(cf, "Resetting", "Filter", FALSE);
1477 rescan_packets(cf, "Filtering", dftext, FALSE);
1480 /* Cleanup and release all dfilter resources */
1481 dfilter_free(dfcode);
1487 cf_reftime_packets(capture_file *cf)
1489 ref_time_packets(cf);
1493 cf_redissect_packets(capture_file *cf)
1495 if (cf->state != FILE_CLOSED) {
1496 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1501 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1502 struct wtap_pkthdr *phdr, Buffer *buf)
1506 gchar *display_basename;
1508 #ifdef WANT_PACKET_EDITOR
1509 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1510 if (G_UNLIKELY(fdata->file_off == -1)) {
1511 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1514 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1518 *phdr = frame->phdr;
1519 ws_buffer_assure_space(buf, frame->phdr.caplen);
1520 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1525 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1526 display_basename = g_filename_display_basename(cf->filename);
1529 case WTAP_ERR_BAD_FILE:
1530 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1531 display_basename, wtap_strerror(err),
1532 err_info != NULL ? err_info : "no information supplied");
1537 simple_error_message_box(
1538 "An error occurred while reading from the file \"%s\": %s.",
1539 display_basename, wtap_strerror(err));
1542 g_free(display_basename);
1549 cf_read_record(capture_file *cf, frame_data *fdata)
1551 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1554 /* Rescan the list of packets, reconstructing the CList.
1556 "action" describes why we're doing this; it's used in the progress
1559 "action_item" describes what we're doing; it's used in the progress
1562 "redissect" is TRUE if we need to make the dissectors reconstruct
1563 any state information they have (because a preference that affects
1564 some dissector has changed, meaning some dissector might construct
1565 its state differently from the way it was constructed the last time). */
1567 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1569 /* Rescan packets new packet list */
1572 progdlg_t *progbar = NULL;
1574 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1575 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1576 gboolean selected_frame_seen;
1578 GTimeVal start_time;
1579 gchar status_str[100];
1580 int progbar_nextstep;
1581 int progbar_quantum;
1585 gboolean create_proto_tree;
1587 gboolean add_to_packet_list = FALSE;
1589 guint32 frames_count;
1591 /* Compile the current display filter.
1592 * We assume this will not fail since cf->dfilter is only set in
1593 * cf_filter IFF the filter was valid.
1595 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1596 g_assert(!cf->dfilter || (compiled && dfcode));
1598 /* Get the union of the flags for all tap listeners. */
1599 tap_flags = union_of_tap_listener_flags();
1600 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1602 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1604 reset_tap_listeners();
1605 /* Which frame, if any, is the currently selected frame?
1606 XXX - should the selected frame or the focus frame be the "current"
1607 frame, that frame being the one from which "Find Frame" searches
1609 selected_frame = cf->current_frame;
1611 /* Mark frame num as not found */
1612 selected_frame_num = -1;
1614 /* Freeze the packet list while we redo it, so we don't get any
1615 screen updates while it happens. */
1616 packet_list_freeze();
1619 /* We need to re-initialize all the state information that protocols
1620 keep, because some preference that controls a dissector has changed,
1621 which might cause the state information to be constructed differently
1622 by that dissector. */
1624 /* We might receive new packets while redissecting, and we don't
1625 want to dissect those before their time. */
1626 cf->redissecting = TRUE;
1628 /* 'reset' dissection session */
1629 epan_free(cf->epan);
1630 cf->epan = ws_epan_new(cf);
1631 cf->cinfo.epan = cf->epan;
1633 /* We need to redissect the packets so we have to discard our old
1634 * packet list store. */
1635 packet_list_clear();
1636 add_to_packet_list = TRUE;
1639 /* We don't yet know which will be the first and last frames displayed. */
1640 cf->first_displayed = 0;
1641 cf->last_displayed = 0;
1643 /* We currently don't display any packets */
1644 cf->displayed_count = 0;
1646 /* Iterate through the list of frames. Call a routine for each frame
1647 to check whether it should be displayed and, if so, add it to
1648 the display list. */
1650 cf->prev_dis = NULL;
1651 cf->prev_cap = NULL;
1654 /* Update the progress bar when it gets to this value. */
1655 progbar_nextstep = 0;
1656 /* When we reach the value that triggers a progress bar update,
1657 bump that value by this amount. */
1658 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1659 /* Count of packets at which we've looked. */
1661 /* Progress so far. */
1664 cf->stop_flag = FALSE;
1665 g_get_current_time(&start_time);
1667 /* no previous row yet */
1668 prev_frame_num = -1;
1671 preceding_frame_num = -1;
1672 preceding_frame = NULL;
1673 following_frame_num = -1;
1674 following_frame = NULL;
1676 selected_frame_seen = FALSE;
1678 frames_count = cf->count;
1680 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1682 for (framenum = 1; framenum <= frames_count; framenum++) {
1683 fdata = frame_data_sequence_find(cf->frames, framenum);
1685 /* Create the progress bar if necessary.
1686 We check on every iteration of the loop, so that it takes no
1687 longer than the standard time to create it (otherwise, for a
1688 large file, we might take considerably longer than that standard
1689 time in order to get to the next progress bar step). */
1690 if (progbar == NULL)
1691 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1696 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1697 when we update it, we have to run the GTK+ main loop to get it
1698 to repaint what's pending, and doing so may involve an "ioctl()"
1699 to see if there's any pending input from an X server, and doing
1700 that for every packet can be costly, especially on a big file. */
1701 if (count >= progbar_nextstep) {
1702 /* let's not divide by zero. I should never be started
1703 * with count == 0, so let's assert that
1705 g_assert(cf->count > 0);
1706 progbar_val = (gfloat) count / frames_count;
1708 if (progbar != NULL) {
1709 g_snprintf(status_str, sizeof(status_str),
1710 "%4u of %u frames", count, frames_count);
1711 update_progress_dlg(progbar, progbar_val, status_str);
1714 progbar_nextstep += progbar_quantum;
1717 if (cf->stop_flag) {
1718 /* Well, the user decided to abort the filtering. Just stop.
1720 XXX - go back to the previous filter? Users probably just
1721 want not to wait for a filtering operation to finish;
1722 unless we cancel by having no filter, reverting to the
1723 previous filter will probably be even more expensive than
1724 continuing the filtering, as it involves going back to the
1725 beginning and filtering, and even with no filter we currently
1726 have to re-generate the entire clist, which is also expensive.
1728 I'm not sure what Network Monitor does, but it doesn't appear
1729 to give you an unfiltered display if you cancel. */
1736 /* Since all state for the frame was destroyed, mark the frame
1737 * as not visited, free the GSList referring to the state
1738 * data (the per-frame data itself was freed by
1739 * "init_dissection()"), and null out the GSList pointer. */
1740 frame_data_reset(fdata);
1741 frames_count = cf->count;
1744 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1745 fdata->flags.dependent_of_displayed = 0;
1747 if (!cf_read_record(cf, fdata))
1748 break; /* error reading the frame */
1750 /* If the previous frame is displayed, and we haven't yet seen the
1751 selected frame, remember that frame - it's the closest one we've
1752 yet seen before the selected frame. */
1753 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1754 preceding_frame_num = prev_frame_num;
1755 preceding_frame = prev_frame;
1758 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1760 ws_buffer_start_ptr(&cf->buf),
1761 add_to_packet_list);
1763 /* If this frame is displayed, and this is the first frame we've
1764 seen displayed after the selected frame, remember this frame -
1765 it's the closest one we've yet seen at or after the selected
1767 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1768 following_frame_num = fdata->num;
1769 following_frame = fdata;
1771 if (fdata == selected_frame) {
1772 selected_frame_seen = TRUE;
1773 if (fdata->flags.passed_dfilter)
1774 selected_frame_num = fdata->num;
1777 /* Remember this frame - it'll be the previous frame
1778 on the next pass through the loop. */
1779 prev_frame_num = fdata->num;
1783 epan_dissect_cleanup(&edt);
1785 /* We are done redissecting the packet list. */
1786 cf->redissecting = FALSE;
1789 frames_count = cf->count;
1790 /* Clear out what remains of the visited flags and per-frame data
1793 XXX - that may cause various forms of bogosity when dissecting
1794 these frames, as they won't have been seen by this sequential
1795 pass, but the only alternative I see is to keep scanning them
1796 even though the user requested that the scan stop, and that
1797 would leave the user stuck with an Wireshark grinding on
1798 until it finishes. Should we just stick them with that? */
1799 for (; framenum <= frames_count; framenum++) {
1800 fdata = frame_data_sequence_find(cf->frames, framenum);
1801 frame_data_reset(fdata);
1805 /* We're done filtering the packets; destroy the progress bar if it
1807 if (progbar != NULL)
1808 destroy_progress_dlg(progbar);
1810 /* Unfreeze the packet list. */
1811 if (!add_to_packet_list)
1812 packet_list_recreate_visible_rows();
1814 /* Compute the time it took to filter the file */
1815 compute_elapsed(cf, &start_time);
1819 if (selected_frame_num == -1) {
1820 /* The selected frame didn't pass the filter. */
1821 if (selected_frame == NULL) {
1822 /* That's because there *was* no selected frame. Make the first
1823 displayed frame the current frame. */
1824 selected_frame_num = 0;
1826 /* Find the nearest displayed frame to the selected frame (whether
1827 it's before or after that frame) and make that the current frame.
1828 If the next and previous displayed frames are equidistant from the
1829 selected frame, choose the next one. */
1830 g_assert(following_frame == NULL ||
1831 following_frame->num >= selected_frame->num);
1832 g_assert(preceding_frame == NULL ||
1833 preceding_frame->num <= selected_frame->num);
1834 if (following_frame == NULL) {
1835 /* No frame after the selected frame passed the filter, so we
1836 have to select the last displayed frame before the selected
1838 selected_frame_num = preceding_frame_num;
1839 selected_frame = preceding_frame;
1840 } else if (preceding_frame == NULL) {
1841 /* No frame before the selected frame passed the filter, so we
1842 have to select the first displayed frame after the selected
1844 selected_frame_num = following_frame_num;
1845 selected_frame = following_frame;
1847 /* Frames before and after the selected frame passed the filter, so
1848 we'll select the previous frame */
1849 selected_frame_num = preceding_frame_num;
1850 selected_frame = preceding_frame;
1855 if (selected_frame_num == -1) {
1856 /* There are no frames displayed at all. */
1857 cf_unselect_packet(cf);
1859 /* Either the frame that was selected passed the filter, or we've
1860 found the nearest displayed frame to that frame. Select it, make
1861 it the focus row, and make it visible. */
1862 /* Set to invalid to force update of packet list and packet details */
1863 cf->current_row = -1;
1864 if (selected_frame_num == 0) {
1865 packet_list_select_first_row();
1867 if (!packet_list_select_row_from_data(selected_frame)) {
1868 /* We didn't find a row corresponding to this frame.
1869 This means that the frame isn't being displayed currently,
1870 so we can't select it. */
1871 simple_message_box(ESD_TYPE_INFO, NULL,
1872 "The capture file is probably not fully dissected.",
1873 "End of capture exceeded.");
1878 /* Cleanup and release all dfilter resources */
1879 dfilter_free(dfcode);
1884 * Scan trough all frame data and recalculate the ref time
1885 * without rereading the file.
1886 * XXX - do we need a progres bar or is this fast enough?
1889 ref_time_packets(capture_file *cf)
1896 cf->prev_dis = NULL;
1899 for (framenum = 1; framenum <= cf->count; framenum++) {
1900 fdata = frame_data_sequence_find(cf->frames, framenum);
1902 /* just add some value here until we know if it is being displayed or not */
1903 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1909 /* If we don't have the time stamp of the first packet in the
1910 capture, it's because this is the first packet. Save the time
1911 stamp of this packet as the time stamp of the first packet. */
1912 if (cf->ref == NULL)
1914 /* if this frames is marked as a reference time frame, reset
1915 firstsec and firstusec to this frame */
1916 if (fdata->flags.ref_time)
1919 /* If we don't have the time stamp of the previous displayed packet,
1920 it's because this is the first displayed packet. Save the time
1921 stamp of this packet as the time stamp of the previous displayed
1923 if (cf->prev_dis == NULL) {
1924 cf->prev_dis = fdata;
1927 /* Get the time elapsed between the first packet and this packet. */
1928 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1929 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1931 /* If it's greater than the current elapsed time, set the elapsed time
1932 to it (we check for "greater than" so as not to be confused by
1933 time moving backwards). */
1934 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1935 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1936 cf->elapsed_time = rel_ts;
1939 /* If this frame is displayed, get the time elapsed between the
1940 previous displayed packet and this packet. */
1941 if ( fdata->flags.passed_dfilter ) {
1942 fdata->prev_dis_num = cf->prev_dis->num;
1943 cf->prev_dis = fdata;
1949 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1950 /* This frame either passed the display filter list or is marked as
1951 a time reference frame. All time reference frames are displayed
1952 even if they don't pass the display filter */
1953 if (fdata->flags.ref_time) {
1954 /* if this was a TIME REF frame we should reset the cum_bytes field */
1955 cf->cum_bytes = fdata->pkt_len;
1956 fdata->cum_bytes = cf->cum_bytes;
1958 /* increase cum_bytes with this packets length */
1959 cf->cum_bytes += fdata->pkt_len;
1972 process_specified_records(capture_file *cf, packet_range_t *range,
1973 const char *string1, const char *string2, gboolean terminate_is_stop,
1974 gboolean (*callback)(capture_file *, frame_data *,
1975 struct wtap_pkthdr *, const guint8 *, void *),
1976 void *callback_args)
1981 psp_return_t ret = PSP_FINISHED;
1983 progdlg_t *progbar = NULL;
1986 GTimeVal progbar_start_time;
1987 gchar progbar_status_str[100];
1988 int progbar_nextstep;
1989 int progbar_quantum;
1990 range_process_e process_this;
1991 struct wtap_pkthdr phdr;
1993 wtap_phdr_init(&phdr);
1994 ws_buffer_init(&buf, 1500);
1996 /* Update the progress bar when it gets to this value. */
1997 progbar_nextstep = 0;
1998 /* When we reach the value that triggers a progress bar update,
1999 bump that value by this amount. */
2000 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2001 /* Count of packets at which we've looked. */
2003 /* Progress so far. */
2006 cf->stop_flag = FALSE;
2007 g_get_current_time(&progbar_start_time);
2010 packet_range_process_init(range);
2012 /* Iterate through all the packets, printing the packets that
2013 were selected by the current display filter. */
2014 for (framenum = 1; framenum <= cf->count; framenum++) {
2015 fdata = frame_data_sequence_find(cf->frames, framenum);
2017 /* Create the progress bar if necessary.
2018 We check on every iteration of the loop, so that it takes no
2019 longer than the standard time to create it (otherwise, for a
2020 large file, we might take considerably longer than that standard
2021 time in order to get to the next progress bar step). */
2022 if (progbar == NULL)
2023 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2026 &progbar_start_time,
2029 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2030 when we update it, we have to run the GTK+ main loop to get it
2031 to repaint what's pending, and doing so may involve an "ioctl()"
2032 to see if there's any pending input from an X server, and doing
2033 that for every packet can be costly, especially on a big file. */
2034 if (progbar_count >= progbar_nextstep) {
2035 /* let's not divide by zero. I should never be started
2036 * with count == 0, so let's assert that
2038 g_assert(cf->count > 0);
2039 progbar_val = (gfloat) progbar_count / cf->count;
2041 if (progbar != NULL) {
2042 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2043 "%4u of %u packets", progbar_count, cf->count);
2044 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2047 progbar_nextstep += progbar_quantum;
2050 if (cf->stop_flag) {
2051 /* Well, the user decided to abort the operation. Just stop,
2052 and arrange to return PSP_STOPPED to our caller, so they know
2053 it was stopped explicitly. */
2060 if (range != NULL) {
2061 /* do we have to process this packet? */
2062 process_this = packet_range_process_packet(range, fdata);
2063 if (process_this == range_process_next) {
2064 /* this packet uninteresting, continue with next one */
2066 } else if (process_this == range_processing_finished) {
2067 /* all interesting packets processed, stop the loop */
2072 /* Get the packet */
2073 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2074 /* Attempt to get the packet failed. */
2078 /* Process the packet */
2079 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2080 /* Callback failed. We assume it reported the error appropriately. */
2086 /* We're done printing the packets; destroy the progress bar if
2088 if (progbar != NULL)
2089 destroy_progress_dlg(progbar);
2091 wtap_phdr_cleanup(&phdr);
2092 ws_buffer_free(&buf);
2100 } retap_callback_args_t;
2103 retap_packet(capture_file *cf, frame_data *fdata,
2104 struct wtap_pkthdr *phdr, const guint8 *pd,
2107 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2109 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2110 epan_dissect_reset(&args->edt);
2116 cf_retap_packets(capture_file *cf)
2118 packet_range_t range;
2119 retap_callback_args_t callback_args;
2120 gboolean construct_protocol_tree;
2121 gboolean filtering_tap_listeners;
2125 /* Presumably the user closed the capture file. */
2127 return CF_READ_ABORTED;
2130 cf_callback_invoke(cf_cb_file_retap_started, cf);
2132 /* Do we have any tap listeners with filters? */
2133 filtering_tap_listeners = have_filtering_tap_listeners();
2135 tap_flags = union_of_tap_listener_flags();
2137 /* If any tap listeners have filters, or require the protocol tree,
2138 construct the protocol tree. */
2139 construct_protocol_tree = filtering_tap_listeners ||
2140 (tap_flags & TL_REQUIRES_PROTO_TREE);
2142 /* If any tap listeners require the columns, construct them. */
2143 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2145 /* Reset the tap listeners. */
2146 reset_tap_listeners();
2148 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2150 /* Iterate through the list of packets, dissecting all packets and
2151 re-running the taps. */
2152 packet_range_init(&range, cf);
2153 packet_range_process_init(&range);
2155 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2156 "all packets", TRUE, retap_packet,
2159 epan_dissect_cleanup(&callback_args.edt);
2161 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2165 /* Completed successfully. */
2169 /* Well, the user decided to abort the refiltering.
2170 Return CF_READ_ABORTED so our caller knows they did that. */
2171 return CF_READ_ABORTED;
2174 /* Error while retapping. */
2175 return CF_READ_ERROR;
2178 g_assert_not_reached();
2183 print_args_t *print_args;
2184 gboolean print_header_line;
2185 char *header_line_buf;
2186 int header_line_buf_len;
2187 gboolean print_formfeed;
2188 gboolean print_separator;
2192 int num_visible_cols;
2195 } print_callback_args_t;
2198 print_packet(capture_file *cf, frame_data *fdata,
2199 struct wtap_pkthdr *phdr, const guint8 *pd,
2202 print_callback_args_t *args = (print_callback_args_t *)argsp;
2208 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2209 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2210 col_item_t* col_item;
2212 /* Fill in the column information if we're printing the summary
2214 if (args->print_args->print_summary) {
2215 col_custom_prime_edt(&args->edt, &cf->cinfo);
2216 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2217 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2219 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2221 if (args->print_formfeed) {
2222 if (!new_page(args->print_args->stream))
2225 if (args->print_separator) {
2226 if (!print_line(args->print_args->stream, 0, ""))
2232 * We generate bookmarks, if the output format supports them.
2233 * The name is "__frameN__".
2235 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2237 if (args->print_args->print_summary) {
2238 if (!args->print_args->print_col_headings)
2239 args->print_header_line = FALSE;
2240 if (args->print_header_line) {
2241 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2243 args->print_header_line = FALSE; /* we might not need to print any more */
2245 cp = &args->line_buf[0];
2247 for (i = 0; i < args->num_visible_cols; i++) {
2248 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2249 /* Find the length of the string for this column. */
2250 column_len = (int) strlen(col_item->col_data);
2251 if (args->col_widths[i] > column_len)
2252 column_len = args->col_widths[i];
2254 /* Make sure there's room in the line buffer for the column; if not,
2255 double its length. */
2256 line_len += column_len + 1; /* "+1" for space */
2257 if (line_len > args->line_buf_len) {
2258 cp_off = (int) (cp - args->line_buf);
2259 args->line_buf_len = 2 * line_len;
2260 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2261 cp = args->line_buf + cp_off;
2264 /* Right-justify the packet number column. */
2265 if (col_item->col_fmt == COL_NUMBER)
2266 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2268 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2270 if (i != args->num_visible_cols - 1)
2276 * Generate a bookmark, using the summary line as the title.
2278 if (!print_bookmark(args->print_args->stream, bookmark_name,
2282 if (!print_line(args->print_args->stream, 0, args->line_buf))
2286 * Generate a bookmark, using "Frame N" as the title, as we're not
2287 * printing the summary line.
2289 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2290 if (!print_bookmark(args->print_args->stream, bookmark_name,
2293 } /* if (print_summary) */
2295 if (args->print_args->print_dissections != print_dissections_none) {
2296 if (args->print_args->print_summary) {
2297 /* Separate the summary line from the tree with a blank line. */
2298 if (!print_line(args->print_args->stream, 0, ""))
2302 /* Print the information in that tree. */
2303 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2306 /* Print a blank line if we print anything after this (aka more than one packet). */
2307 args->print_separator = TRUE;
2309 /* Print a header line if we print any more packet summaries */
2310 if (args->print_args->print_col_headings)
2311 args->print_header_line = TRUE;
2314 if (args->print_args->print_hex) {
2315 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2316 if (!print_line(args->print_args->stream, 0, ""))
2319 /* Print the full packet data as hex. */
2320 if (!print_hex_data(args->print_args->stream, &args->edt))
2323 /* Print a blank line if we print anything after this (aka more than one packet). */
2324 args->print_separator = TRUE;
2326 /* Print a header line if we print any more packet summaries */
2327 if (args->print_args->print_col_headings)
2328 args->print_header_line = TRUE;
2329 } /* if (args->print_args->print_dissections != print_dissections_none) */
2331 epan_dissect_reset(&args->edt);
2333 /* do we want to have a formfeed between each packet from now on? */
2334 if (args->print_args->print_formfeed) {
2335 args->print_formfeed = TRUE;
2341 epan_dissect_reset(&args->edt);
2346 cf_print_packets(capture_file *cf, print_args_t *print_args)
2348 print_callback_args_t callback_args;
2351 int i, cp_off, column_len, line_len;
2352 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2356 gboolean proto_tree_needed;
2358 callback_args.print_args = print_args;
2359 callback_args.print_header_line = print_args->print_col_headings;
2360 callback_args.header_line_buf = NULL;
2361 callback_args.header_line_buf_len = 256;
2362 callback_args.print_formfeed = FALSE;
2363 callback_args.print_separator = FALSE;
2364 callback_args.line_buf = NULL;
2365 callback_args.line_buf_len = 256;
2366 callback_args.col_widths = NULL;
2367 callback_args.num_visible_cols = 0;
2368 callback_args.visible_cols = NULL;
2370 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2371 destroy_print_stream(print_args->stream);
2372 return CF_PRINT_WRITE_ERROR;
2375 if (print_args->print_summary) {
2376 /* We're printing packet summaries. Allocate the header line buffer
2377 and get the column widths. */
2378 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2380 /* Find the number of visible columns and the last visible column */
2381 for (i = 0; i < prefs.num_cols; i++) {
2383 clp = g_list_nth(prefs.col_list, i);
2384 if (clp == NULL) /* Sanity check, Invalid column requested */
2387 cfmt = (fmt_data *) clp->data;
2388 if (cfmt->visible) {
2390 last_visible_col = i;
2394 /* Find the widths for each of the columns - maximum of the
2395 width of the title and the width of the data - and construct
2396 a buffer with a line containing the column titles. */
2397 callback_args.num_visible_cols = num_visible_col;
2398 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2399 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2400 cp = &callback_args.header_line_buf[0];
2402 visible_col_count = 0;
2403 for (i = 0; i < cf->cinfo.num_cols; i++) {
2405 clp = g_list_nth(prefs.col_list, i);
2406 if (clp == NULL) /* Sanity check, Invalid column requested */
2409 cfmt = (fmt_data *) clp->data;
2410 if (cfmt->visible == FALSE)
2413 /* Save the order of visible columns */
2414 callback_args.visible_cols[visible_col_count] = i;
2416 /* Don't pad the last column. */
2417 if (i == last_visible_col)
2418 callback_args.col_widths[visible_col_count] = 0;
2420 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2421 data_width = get_column_char_width(get_column_format(i));
2422 if (data_width > callback_args.col_widths[visible_col_count])
2423 callback_args.col_widths[visible_col_count] = data_width;
2426 /* Find the length of the string for this column. */
2427 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2428 if (callback_args.col_widths[i] > column_len)
2429 column_len = callback_args.col_widths[visible_col_count];
2431 /* Make sure there's room in the line buffer for the column; if not,
2432 double its length. */
2433 line_len += column_len + 1; /* "+1" for space */
2434 if (line_len > callback_args.header_line_buf_len) {
2435 cp_off = (int) (cp - callback_args.header_line_buf);
2436 callback_args.header_line_buf_len = 2 * line_len;
2437 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2438 callback_args.header_line_buf_len + 1);
2439 cp = callback_args.header_line_buf + cp_off;
2442 /* Right-justify the packet number column. */
2443 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2444 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2446 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2448 if (i != cf->cinfo.num_cols - 1)
2451 visible_col_count++;
2455 /* Now start out the main line buffer with the same length as the
2456 header line buffer. */
2457 callback_args.line_buf_len = callback_args.header_line_buf_len;
2458 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2459 } /* if (print_summary) */
2461 /* Create the protocol tree, and make it visible, if we're printing
2462 the dissection or the hex data.
2463 XXX - do we need it if we're just printing the hex data? */
2465 callback_args.print_args->print_dissections != print_dissections_none ||
2466 callback_args.print_args->print_hex ||
2467 have_custom_cols(&cf->cinfo);
2468 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2470 /* Iterate through the list of packets, printing the packets we were
2472 ret = process_specified_records(cf, &print_args->range, "Printing",
2473 "selected packets", TRUE, print_packet,
2475 epan_dissect_cleanup(&callback_args.edt);
2476 g_free(callback_args.header_line_buf);
2477 g_free(callback_args.line_buf);
2478 g_free(callback_args.col_widths);
2479 g_free(callback_args.visible_cols);
2484 /* Completed successfully. */
2488 /* Well, the user decided to abort the printing.
2490 XXX - note that what got generated before they did that
2491 will get printed if we're piping to a print program; we'd
2492 have to write to a file and then hand that to the print
2493 program to make it actually not print anything. */
2497 /* Error while printing.
2499 XXX - note that what got generated before they did that
2500 will get printed if we're piping to a print program; we'd
2501 have to write to a file and then hand that to the print
2502 program to make it actually not print anything. */
2503 destroy_print_stream(print_args->stream);
2504 return CF_PRINT_WRITE_ERROR;
2507 if (!print_finale(print_args->stream)) {
2508 destroy_print_stream(print_args->stream);
2509 return CF_PRINT_WRITE_ERROR;
2512 if (!destroy_print_stream(print_args->stream))
2513 return CF_PRINT_WRITE_ERROR;
2521 } write_packet_callback_args_t;
2524 write_pdml_packet(capture_file *cf, frame_data *fdata,
2525 struct wtap_pkthdr *phdr, const guint8 *pd,
2528 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2530 /* Create the protocol tree, but don't fill in the column information. */
2531 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2533 /* Write out the information in that tree. */
2534 write_pdml_proto_tree(&args->edt, args->fh);
2536 epan_dissect_reset(&args->edt);
2538 return !ferror(args->fh);
2542 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2544 write_packet_callback_args_t callback_args;
2548 fh = ws_fopen(print_args->file, "w");
2550 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2552 write_pdml_preamble(fh, cf->filename);
2555 return CF_PRINT_WRITE_ERROR;
2558 callback_args.fh = fh;
2559 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2561 /* Iterate through the list of packets, printing the packets we were
2563 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2564 "selected packets", TRUE,
2565 write_pdml_packet, &callback_args);
2567 epan_dissect_cleanup(&callback_args.edt);
2572 /* Completed successfully. */
2576 /* Well, the user decided to abort the printing. */
2580 /* Error while printing. */
2582 return CF_PRINT_WRITE_ERROR;
2585 write_pdml_finale(fh);
2588 return CF_PRINT_WRITE_ERROR;
2591 /* XXX - check for an error */
2598 write_psml_packet(capture_file *cf, frame_data *fdata,
2599 struct wtap_pkthdr *phdr, const guint8 *pd,
2602 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2604 /* Fill in the column information */
2605 col_custom_prime_edt(&args->edt, &cf->cinfo);
2606 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2607 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2609 /* Write out the column information. */
2610 write_psml_columns(&args->edt, args->fh);
2612 epan_dissect_reset(&args->edt);
2614 return !ferror(args->fh);
2618 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2620 write_packet_callback_args_t callback_args;
2624 gboolean proto_tree_needed;
2626 fh = ws_fopen(print_args->file, "w");
2628 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2630 write_psml_preamble(&cf->cinfo, fh);
2633 return CF_PRINT_WRITE_ERROR;
2636 callback_args.fh = fh;
2638 /* Fill in the column information, only create the protocol tree
2639 if having custom columns. */
2640 proto_tree_needed = have_custom_cols(&cf->cinfo);
2641 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2643 /* Iterate through the list of packets, printing the packets we were
2645 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2646 "selected packets", TRUE,
2647 write_psml_packet, &callback_args);
2649 epan_dissect_cleanup(&callback_args.edt);
2654 /* Completed successfully. */
2658 /* Well, the user decided to abort the printing. */
2662 /* Error while printing. */
2664 return CF_PRINT_WRITE_ERROR;
2667 write_psml_finale(fh);
2670 return CF_PRINT_WRITE_ERROR;
2673 /* XXX - check for an error */
2680 write_csv_packet(capture_file *cf, frame_data *fdata,
2681 struct wtap_pkthdr *phdr, const guint8 *pd,
2684 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2686 /* Fill in the column information */
2687 col_custom_prime_edt(&args->edt, &cf->cinfo);
2688 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2689 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2691 /* Write out the column information. */
2692 write_csv_columns(&args->edt, args->fh);
2694 epan_dissect_reset(&args->edt);
2696 return !ferror(args->fh);
2700 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2702 write_packet_callback_args_t callback_args;
2703 gboolean proto_tree_needed;
2707 fh = ws_fopen(print_args->file, "w");
2709 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2711 write_csv_column_titles(&cf->cinfo, fh);
2714 return CF_PRINT_WRITE_ERROR;
2717 callback_args.fh = fh;
2719 /* only create the protocol tree if having custom columns. */
2720 proto_tree_needed = have_custom_cols(&cf->cinfo);
2721 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2723 /* Iterate through the list of packets, printing the packets we were
2725 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2726 "selected packets", TRUE,
2727 write_csv_packet, &callback_args);
2729 epan_dissect_cleanup(&callback_args.edt);
2734 /* Completed successfully. */
2738 /* Well, the user decided to abort the printing. */
2742 /* Error while printing. */
2744 return CF_PRINT_WRITE_ERROR;
2747 /* XXX - check for an error */
2754 carrays_write_packet(capture_file *cf, frame_data *fdata,
2755 struct wtap_pkthdr *phdr,
2756 const guint8 *pd, void *argsp)
2758 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2760 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2761 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2762 epan_dissect_reset(&args->edt);
2764 return !ferror(args->fh);
2768 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2770 write_packet_callback_args_t callback_args;
2774 fh = ws_fopen(print_args->file, "w");
2777 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2781 return CF_PRINT_WRITE_ERROR;
2784 callback_args.fh = fh;
2785 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2787 /* Iterate through the list of packets, printing the packets we were
2789 ret = process_specified_records(cf, &print_args->range,
2791 "selected packets", TRUE,
2792 carrays_write_packet, &callback_args);
2794 epan_dissect_cleanup(&callback_args.edt);
2798 /* Completed successfully. */
2801 /* Well, the user decided to abort the printing. */
2804 /* Error while printing. */
2806 return CF_PRINT_WRITE_ERROR;
2814 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2815 search_direction dir)
2819 mdata.string = string;
2820 mdata.string_len = strlen(string);
2821 return find_packet(cf, match_protocol_tree, &mdata, dir);
2825 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2827 mdata->frame_matched = FALSE;
2828 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2829 mdata->string_len = strlen(mdata->string);
2831 /* Iterate through all the nodes looking for matching text */
2832 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2833 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2837 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2839 match_data *mdata = (match_data *)criterion;
2842 /* Load the frame's data. */
2843 if (!cf_read_record(cf, fdata)) {
2844 /* Attempt to get the packet failed. */
2848 /* Construct the protocol tree, including the displayed text */
2849 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2850 /* We don't need the column information */
2851 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2853 /* Iterate through all the nodes, seeing if they have text that matches. */
2855 mdata->frame_matched = FALSE;
2856 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2857 epan_dissect_cleanup(&edt);
2858 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2862 match_subtree_text(proto_node *node, gpointer data)
2864 match_data *mdata = (match_data *) data;
2865 const gchar *string = mdata->string;
2866 size_t string_len = mdata->string_len;
2867 capture_file *cf = mdata->cf;
2868 field_info *fi = PNODE_FINFO(node);
2869 gchar label_str[ITEM_LABEL_LENGTH];
2876 /* dissection with an invisible proto tree? */
2879 if (mdata->frame_matched) {
2880 /* We already had a match; don't bother doing any more work. */
2884 /* Don't match invisible entries. */
2885 if (PROTO_ITEM_IS_HIDDEN(node))
2888 /* was a free format label produced? */
2890 label_ptr = fi->rep->representation;
2892 /* no, make a generic label */
2893 label_ptr = label_str;
2894 proto_item_fill_label(fi, label_str);
2897 /* Does that label match? */
2898 label_len = strlen(label_ptr);
2899 for (i = 0; i < label_len; i++) {
2900 c_char = label_ptr[i];
2902 c_char = g_ascii_toupper(c_char);
2903 if (c_char == string[c_match]) {
2905 if (c_match == string_len) {
2906 /* No need to look further; we have a match */
2907 mdata->frame_matched = TRUE;
2915 /* Recurse into the subtree, if it exists */
2916 if (node->first_child != NULL)
2917 proto_tree_children_foreach(node, match_subtree_text, mdata);
2921 cf_find_packet_summary_line(capture_file *cf, const char *string,
2922 search_direction dir)
2926 mdata.string = string;
2927 mdata.string_len = strlen(string);
2928 return find_packet(cf, match_summary_line, &mdata, dir);
2932 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2934 match_data *mdata = (match_data *)criterion;
2935 const gchar *string = mdata->string;
2936 size_t string_len = mdata->string_len;
2938 const char *info_column;
2939 size_t info_column_len;
2940 match_result result = MR_NOTMATCHED;
2946 /* Load the frame's data. */
2947 if (!cf_read_record(cf, fdata)) {
2948 /* Attempt to get the packet failed. */
2952 /* Don't bother constructing the protocol tree */
2953 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
2954 /* Get the column information */
2955 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
2958 /* Find the Info column */
2959 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2960 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
2961 /* Found it. See if we match. */
2962 info_column = edt.pi.cinfo->columns[colx].col_data;
2963 info_column_len = strlen(info_column);
2964 for (i = 0; i < info_column_len; i++) {
2965 c_char = info_column[i];
2967 c_char = g_ascii_toupper(c_char);
2968 if (c_char == string[c_match]) {
2970 if (c_match == string_len) {
2971 result = MR_MATCHED;
2980 epan_dissect_cleanup(&edt);
2987 } cbs_t; /* "Counted byte string" */
2991 * The current match_* routines only support ASCII case insensitivity and don't
2992 * convert UTF-8 inputs to UTF-16 for matching.
2994 * We could modify them to use the GLib Unicode routines or the International
2995 * Components for Unicode library but it's not apparent that we could do so
2996 * without consuming a lot more CPU and memory or that searching would be
2997 * significantly better.
3001 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
3002 search_direction dir)
3007 info.data_len = string_size;
3009 /* String or hex search? */
3011 /* String search - what type of string? */
3012 switch (cf->scs_type) {
3014 case SCS_NARROW_AND_WIDE:
3015 return find_packet(cf, match_narrow_and_wide, &info, dir);
3018 return find_packet(cf, match_narrow, &info, dir);
3021 return find_packet(cf, match_wide, &info, dir);
3024 g_assert_not_reached();
3028 return find_packet(cf, match_binary, &info, dir);
3032 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3034 cbs_t *info = (cbs_t *)criterion;
3035 const guint8 *ascii_text = info->data;
3036 size_t textlen = info->data_len;
3037 match_result result;
3044 /* Load the frame's data. */
3045 if (!cf_read_record(cf, fdata)) {
3046 /* Attempt to get the packet failed. */
3050 result = MR_NOTMATCHED;
3051 buf_len = fdata->cap_len;
3052 pd = ws_buffer_start_ptr(&cf->buf);
3054 while (i < buf_len) {
3057 c_char = g_ascii_toupper(c_char);
3058 if (c_char != '\0') {
3059 if (c_char == ascii_text[c_match]) {
3061 if (c_match == textlen) {
3062 result = MR_MATCHED;
3063 cf->search_pos = i; /* Save the position of the last character
3064 for highlighting the field. */
3069 g_assert(i>=c_match);
3070 i -= (guint32)c_match;
3080 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3083 cbs_t *info = (cbs_t *)criterion;
3084 const guint8 *ascii_text = info->data;
3085 size_t textlen = info->data_len;
3086 match_result result;
3092 /* Load the frame's data. */
3093 if (!cf_read_record(cf, fdata)) {
3094 /* Attempt to get the packet failed. */
3098 result = MR_NOTMATCHED;
3099 buf_len = fdata->cap_len;
3100 pd = ws_buffer_start_ptr(&cf->buf);
3102 while (i < buf_len) {
3105 c_char = g_ascii_toupper(c_char);
3106 if (c_char == ascii_text[c_match]) {
3108 if (c_match == textlen) {
3109 result = MR_MATCHED;
3110 cf->search_pos = i; /* Save the position of the last character
3111 for highlighting the field. */
3116 g_assert(i>=c_match);
3117 i -= (guint32)c_match;
3127 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3129 cbs_t *info = (cbs_t *)criterion;
3130 const guint8 *ascii_text = info->data;
3131 size_t textlen = info->data_len;
3132 match_result result;
3139 /* Load the frame's data. */
3140 if (!cf_read_record(cf, fdata)) {
3141 /* Attempt to get the packet failed. */
3145 result = MR_NOTMATCHED;
3146 buf_len = fdata->cap_len;
3147 pd = ws_buffer_start_ptr(&cf->buf);
3149 while (i < buf_len) {
3152 c_char = g_ascii_toupper(c_char);
3153 if (c_char == ascii_text[c_match]) {
3155 if (c_match == textlen) {
3156 result = MR_MATCHED;
3157 cf->search_pos = i; /* Save the position of the last character
3158 for highlighting the field. */
3164 g_assert(i>=(c_match*2));
3165 i -= (guint32)c_match*2;
3174 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3176 cbs_t *info = (cbs_t *)criterion;
3177 const guint8 *binary_data = info->data;
3178 size_t datalen = info->data_len;
3179 match_result result;
3185 /* Load the frame's data. */
3186 if (!cf_read_record(cf, fdata)) {
3187 /* Attempt to get the packet failed. */
3191 result = MR_NOTMATCHED;
3192 buf_len = fdata->cap_len;
3193 pd = ws_buffer_start_ptr(&cf->buf);
3195 while (i < buf_len) {
3196 if (pd[i] == binary_data[c_match]) {
3198 if (c_match == datalen) {
3199 result = MR_MATCHED;
3200 cf->search_pos = i; /* Save the position of the last character
3201 for highlighting the field. */
3206 g_assert(i>=c_match);
3207 i -= (guint32)c_match;
3216 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3217 search_direction dir)
3219 return find_packet(cf, match_dfilter, sfcode, dir);
3223 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3224 search_direction dir)
3229 if (!dfilter_compile(filter, &sfcode, NULL)) {
3231 * XXX - this shouldn't happen, as the filter string is machine
3236 if (sfcode == NULL) {
3238 * XXX - this shouldn't happen, as the filter string is machine
3243 result = find_packet(cf, match_dfilter, sfcode, dir);
3244 dfilter_free(sfcode);
3249 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3251 dfilter_t *sfcode = (dfilter_t *)criterion;
3253 match_result result;
3255 /* Load the frame's data. */
3256 if (!cf_read_record(cf, fdata)) {
3257 /* Attempt to get the packet failed. */
3261 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3262 epan_dissect_prime_dfilter(&edt, sfcode);
3263 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3264 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3265 epan_dissect_cleanup(&edt);
3270 cf_find_packet_marked(capture_file *cf, search_direction dir)
3272 return find_packet(cf, match_marked, NULL, dir);
3276 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3278 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3282 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3284 return find_packet(cf, match_time_reference, NULL, dir);
3288 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3290 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3294 find_packet(capture_file *cf,
3295 match_result (*match_function)(capture_file *, frame_data *, void *),
3296 void *criterion, search_direction dir)
3298 frame_data *start_fd;
3301 frame_data *new_fd = NULL;
3302 progdlg_t *progbar = NULL;
3306 GTimeVal start_time;
3307 gchar status_str[100];
3308 int progbar_nextstep;
3309 int progbar_quantum;
3311 match_result result;
3313 start_fd = cf->current_frame;
3314 if (start_fd != NULL) {
3315 /* Iterate through the list of packets, starting at the packet we've
3316 picked, calling a routine to run the filter on the packet, see if
3317 it matches, and stop if so. */
3319 framenum = start_fd->num;
3321 /* Update the progress bar when it gets to this value. */
3322 progbar_nextstep = 0;
3323 /* When we reach the value that triggers a progress bar update,
3324 bump that value by this amount. */
3325 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3326 /* Progress so far. */
3329 cf->stop_flag = FALSE;
3330 g_get_current_time(&start_time);
3332 title = cf->sfilter?cf->sfilter:"";
3334 /* Create the progress bar if necessary.
3335 We check on every iteration of the loop, so that it takes no
3336 longer than the standard time to create it (otherwise, for a
3337 large file, we might take considerably longer than that standard
3338 time in order to get to the next progress bar step). */
3339 if (progbar == NULL)
3340 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3341 FALSE, &cf->stop_flag, &start_time, progbar_val);
3343 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3344 when we update it, we have to run the GTK+ main loop to get it
3345 to repaint what's pending, and doing so may involve an "ioctl()"
3346 to see if there's any pending input from an X server, and doing
3347 that for every packet can be costly, especially on a big file. */
3348 if (count >= progbar_nextstep) {
3349 /* let's not divide by zero. I should never be started
3350 * with count == 0, so let's assert that
3352 g_assert(cf->count > 0);
3354 progbar_val = (gfloat) count / cf->count;
3356 if (progbar != NULL) {
3357 g_snprintf(status_str, sizeof(status_str),
3358 "%4u of %u packets", count, cf->count);
3359 update_progress_dlg(progbar, progbar_val, status_str);
3362 progbar_nextstep += progbar_quantum;
3365 if (cf->stop_flag) {
3366 /* Well, the user decided to abort the search. Go back to the
3367 frame where we started. */
3372 /* Go past the current frame. */
3373 if (dir == SD_BACKWARD) {
3374 /* Go on to the previous frame. */
3375 if (framenum == 1) {
3377 * XXX - other apps have a bit more of a detailed message
3378 * for this, and instead of offering "OK" and "Cancel",
3379 * they offer things such as "Continue" and "Cancel";
3380 * we need an API for popping up alert boxes with
3381 * {Verb} and "Cancel".
3384 if (prefs.gui_find_wrap)
3386 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3387 framenum = cf->count; /* wrap around */
3391 statusbar_push_temporary_msg("Search reached the beginning.");
3392 framenum = start_fd->num; /* stay on previous packet */
3397 /* Go on to the next frame. */
3398 if (framenum == cf->count) {
3399 if (prefs.gui_find_wrap)
3401 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3402 framenum = 1; /* wrap around */
3406 statusbar_push_temporary_msg("Search reached the end.");
3407 framenum = start_fd->num; /* stay on previous packet */
3412 fdata = frame_data_sequence_find(cf->frames, framenum);
3416 /* Is this packet in the display? */
3417 if (fdata->flags.passed_dfilter) {
3418 /* Yes. Does it match the search criterion? */
3419 result = (*match_function)(cf, fdata, criterion);
3420 if (result == MR_ERROR) {
3421 /* Error; our caller has reported the error. Go back to the frame
3422 where we started. */
3425 } else if (result == MR_MATCHED) {
3426 /* Yes. Go to the new frame. */
3432 if (fdata == start_fd) {
3433 /* We're back to the frame we were on originally, and that frame
3434 doesn't match the search filter. The search failed. */
3439 /* We're done scanning the packets; destroy the progress bar if it
3441 if (progbar != NULL)
3442 destroy_progress_dlg(progbar);
3445 if (new_fd != NULL) {
3446 /* Find and select */
3447 cf->search_in_progress = TRUE;
3448 found = packet_list_select_row_from_data(new_fd);
3449 cf->search_in_progress = FALSE;
3450 cf->search_pos = 0; /* Reset the position */
3452 /* We didn't find a row corresponding to this frame.
3453 This means that the frame isn't being displayed currently,
3454 so we can't select it. */
3455 simple_message_box(ESD_TYPE_INFO, NULL,
3456 "The capture file is probably not fully dissected.",
3457 "End of capture exceeded.");
3460 return TRUE; /* success */
3462 return FALSE; /* failure */
3466 cf_goto_frame(capture_file *cf, guint fnumber)
3470 fdata = frame_data_sequence_find(cf->frames, fnumber);
3472 if (fdata == NULL) {
3473 /* we didn't find a packet with that packet number */
3474 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3475 return FALSE; /* we failed to go to that packet */
3477 if (!fdata->flags.passed_dfilter) {
3478 /* that packet currently isn't displayed */
3479 /* XXX - add it to the set of displayed packets? */
3480 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3481 return FALSE; /* we failed to go to that packet */
3484 if (!packet_list_select_row_from_data(fdata)) {
3485 /* We didn't find a row corresponding to this frame.
3486 This means that the frame isn't being displayed currently,
3487 so we can't select it. */
3488 simple_message_box(ESD_TYPE_INFO, NULL,
3489 "The capture file is probably not fully dissected.",
3490 "End of capture exceeded.");
3493 return TRUE; /* we got to that packet */
3497 cf_goto_top_frame(void)
3499 /* Find and select */
3500 packet_list_select_first_row();
3501 return TRUE; /* we got to that packet */
3505 cf_goto_bottom_frame(void)
3507 /* Find and select */
3508 packet_list_select_last_row();
3509 return TRUE; /* we got to that packet */
3513 * Go to frame specified by currently selected protocol tree item.
3516 cf_goto_framenum(capture_file *cf)
3518 header_field_info *hfinfo;
3521 if (cf->finfo_selected) {
3522 hfinfo = cf->finfo_selected->hfinfo;
3524 if (hfinfo->type == FT_FRAMENUM) {
3525 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3527 return cf_goto_frame(cf, framenum);
3534 /* Select the packet on a given row. */
3536 cf_select_packet(capture_file *cf, int row)
3538 epan_dissect_t *old_edt;
3541 /* Get the frame data struct pointer for this frame */
3542 fdata = packet_list_get_row_data(row);
3544 if (fdata == NULL) {
3545 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3546 the first entry is added to it by "real_insert_row()", that row
3547 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3548 our version and the vanilla GTK+ version).
3550 This means that a "select-row" signal is emitted; this causes
3551 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3554 "cf_select_packet()" fetches, above, the data associated with the
3555 row that was selected; however, as "gtk_clist_append()", which
3556 called "real_insert_row()", hasn't yet returned, we haven't yet
3557 associated any data with that row, so we get back a null pointer.
3559 We can't assume that there's only one frame in the frame list,
3560 either, as we may be filtering the display.
3562 We therefore assume that, if "row" is 0, i.e. the first row
3563 is being selected, and "cf->first_displayed" equals
3564 "cf->last_displayed", i.e. there's only one frame being
3565 displayed, that frame is the frame we want.
3567 This means we have to set "cf->first_displayed" and
3568 "cf->last_displayed" before adding the row to the
3569 GtkCList; see the comment in "add_packet_to_packet_list()". */
3571 if (row == 0 && cf->first_displayed == cf->last_displayed)
3572 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3575 /* If fdata _still_ isn't set simply give up. */
3576 if (fdata == NULL) {
3580 /* Get the data in that frame. */
3581 if (!cf_read_record (cf, fdata)) {
3585 /* Record that this frame is the current frame. */
3586 cf->current_frame = fdata;
3587 cf->current_row = row;
3590 /* Create the logical protocol tree. */
3591 /* We don't need the columns here. */
3592 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3594 tap_build_interesting(cf->edt);
3595 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3596 cf->current_frame, NULL);
3598 dfilter_macro_build_ftv_cache(cf->edt->tree);
3600 cf_callback_invoke(cf_cb_packet_selected, cf);
3602 if (old_edt != NULL)
3603 epan_dissect_free(old_edt);
3607 /* Unselect the selected packet, if any. */
3609 cf_unselect_packet(capture_file *cf)
3611 epan_dissect_t *old_edt = cf->edt;
3615 /* No packet is selected. */
3616 cf->current_frame = NULL;
3617 cf->current_row = 0;
3619 cf_callback_invoke(cf_cb_packet_unselected, cf);
3621 /* No protocol tree means no selected field. */
3622 cf_unselect_field(cf);
3624 /* Destroy the epan_dissect_t for the unselected packet. */
3625 if (old_edt != NULL)
3626 epan_dissect_free(old_edt);
3629 /* Unset the selected protocol tree field, if any. */
3631 cf_unselect_field(capture_file *cf)
3633 cf->finfo_selected = NULL;
3635 cf_callback_invoke(cf_cb_field_unselected, cf);
3639 * Mark a particular frame.
3642 cf_mark_frame(capture_file *cf, frame_data *frame)
3644 if (! frame->flags.marked) {
3645 frame->flags.marked = TRUE;
3646 if (cf->count > cf->marked_count)
3652 * Unmark a particular frame.
3655 cf_unmark_frame(capture_file *cf, frame_data *frame)
3657 if (frame->flags.marked) {
3658 frame->flags.marked = FALSE;
3659 if (cf->marked_count > 0)
3665 * Ignore a particular frame.
3668 cf_ignore_frame(capture_file *cf, frame_data *frame)
3670 if (! frame->flags.ignored) {
3671 frame->flags.ignored = TRUE;
3672 if (cf->count > cf->ignored_count)
3673 cf->ignored_count++;
3678 * Un-ignore a particular frame.
3681 cf_unignore_frame(capture_file *cf, frame_data *frame)
3683 if (frame->flags.ignored) {
3684 frame->flags.ignored = FALSE;
3685 if (cf->ignored_count > 0)
3686 cf->ignored_count--;
3691 * Read the comment in SHB block
3695 cf_read_shb_comment(capture_file *cf)
3697 /* Get info from SHB */
3698 return wtap_file_get_shb_comment(cf->wth);
3702 cf_update_capture_comment(capture_file *cf, gchar *comment)
3704 const gchar *shb_comment;
3706 /* Get info from SHB */
3707 shb_comment = wtap_file_get_shb_comment(cf->wth);
3709 /* See if the comment has changed or not */
3711 if (strcmp(shb_comment, comment) == 0) {
3717 /* The comment has changed, let's update it */
3718 wtap_write_shb_comment(cf->wth, comment);
3719 /* Mark the file as having unsaved changes */
3720 cf->unsaved_changes = TRUE;
3724 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3726 if (cf->frames_user_comments)
3727 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3734 cf_get_comment(capture_file *cf, const frame_data *fd)
3738 /* fetch user comment */
3739 if (fd->flags.has_user_comment)
3740 return g_strdup(cf_get_user_packet_comment(cf, fd));
3742 /* fetch phdr comment */
3743 if (fd->flags.has_phdr_comment) {
3744 struct wtap_pkthdr phdr; /* Packet header */
3745 Buffer buf; /* Packet data */
3747 wtap_phdr_init(&phdr);
3748 ws_buffer_init(&buf, 1500);
3750 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3751 { /* XXX, what we can do here? */ }
3753 comment = phdr.opt_comment;
3754 wtap_phdr_cleanup(&phdr);
3755 ws_buffer_free(&buf);
3762 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3764 const frame_data *fdata1 = (const frame_data *) a;
3765 const frame_data *fdata2 = (const frame_data *) b;
3767 return (fdata1->num < fdata2->num) ? -1 :
3768 (fdata1->num > fdata2->num) ? 1 :
3773 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3775 char *pkt_comment = cf_get_comment(cf, fd);
3777 /* Check if the comment has changed */
3778 if (!g_strcmp0(pkt_comment, new_comment)) {
3779 g_free(pkt_comment);
3782 g_free(pkt_comment);
3785 cf->packet_comment_count--;
3788 cf->packet_comment_count++;
3790 fd->flags.has_user_comment = TRUE;
3792 if (!cf->frames_user_comments)
3793 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3795 /* insert new packet comment */
3796 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3798 expert_update_comment_count(cf->packet_comment_count);
3800 /* OK, we have unsaved changes. */
3801 cf->unsaved_changes = TRUE;
3806 * What types of comments does this capture file have?
3809 cf_comment_types(capture_file *cf)
3811 guint32 comment_types = 0;
3813 if (cf_read_shb_comment(cf) != NULL)
3814 comment_types |= WTAP_COMMENT_PER_SECTION;
3815 if (cf->packet_comment_count != 0)
3816 comment_types |= WTAP_COMMENT_PER_PACKET;
3817 return comment_types;
3820 #ifdef WANT_PACKET_EDITOR
3822 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3833 modified_frame_data_free(gpointer data)
3835 modified_frame_data *mfd = (modified_frame_data *)data;
3842 * Give a frame new, edited data.
3845 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3846 struct wtap_pkthdr *phdr, guint8 *pd)
3848 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3853 if (cf->edited_frames == NULL)
3854 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3855 modified_frame_data_free);
3856 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3859 /* Mark the file as having unsaved changes */
3860 cf->unsaved_changes = TRUE;
3868 } save_callback_args_t;
3871 * Save a capture to a file, in a particular format, saving either
3872 * all packets, all currently-displayed packets, or all marked packets.
3874 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3875 * up a message box for the failure.
3878 save_record(capture_file *cf, frame_data *fdata,
3879 struct wtap_pkthdr *phdr, const guint8 *pd,
3882 save_callback_args_t *args = (save_callback_args_t *)argsp;
3883 struct wtap_pkthdr hdr;
3886 gchar *display_basename;
3887 const char *pkt_comment;
3889 if (fdata->flags.has_user_comment)
3890 pkt_comment = cf_get_user_packet_comment(cf, fdata);
3892 pkt_comment = phdr->opt_comment;
3894 /* init the wtap header for saving */
3895 /* TODO: reuse phdr */
3896 /* XXX - these are the only flags that correspond to data that we have
3897 in the frame_data structure and that matter on a per-packet basis.
3899 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3900 and "on the wire" lengths, or it doesn't.
3902 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3905 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3906 from the packet flags. */
3907 hdr.rec_type = phdr->rec_type;
3908 hdr.presence_flags = 0;
3909 if (fdata->flags.has_ts)
3910 hdr.presence_flags |= WTAP_HAS_TS;
3911 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3912 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3913 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
3914 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
3915 hdr.ts.secs = fdata->abs_ts.secs;
3916 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3917 hdr.caplen = phdr->caplen;
3918 hdr.len = phdr->len;
3919 hdr.pkt_encap = fdata->lnk_t;
3921 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
3923 hdr.pack_flags = phdr->pack_flags;
3924 hdr.opt_comment = g_strdup(pkt_comment);
3927 hdr.pseudo_header = phdr->pseudo_header;
3930 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3932 /* and save the packet */
3933 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
3935 /* Wiretap error. */
3938 case WTAP_ERR_UNWRITABLE_ENCAP:
3940 * This is a problem with the particular frame we're writing and
3941 * the file type and subtype we're writing; note that, and report
3942 * the frame number and file type/subtype.
3944 simple_error_message_box(
3945 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3946 fdata->num, wtap_file_type_subtype_string(args->file_type));
3949 case WTAP_ERR_PACKET_TOO_LARGE:
3951 * This is a problem with the particular frame we're writing and
3952 * the file type and subtype we're writing; note that, and report
3953 * the frame number and file type/subtype.
3955 simple_error_message_box(
3956 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
3957 fdata->num, wtap_file_type_subtype_string(args->file_type));
3960 case WTAP_ERR_UNWRITABLE_REC_TYPE:
3962 * This is a problem with the particular record we're writing and
3963 * the file type and subtype we're writing; note that, and report
3964 * the record number and file type/subtype.
3966 simple_error_message_box(
3967 "Record %u has a record type that can't be saved in a \"%s\" file.",
3968 fdata->num, wtap_file_type_subtype_string(args->file_type));
3971 case WTAP_ERR_UNWRITABLE_REC_DATA:
3973 * This is a problem with the particular frame we're writing and
3974 * the file type and subtype we're writing; note that, and report
3975 * the frame number and file type/subtype.
3977 simple_error_message_box(
3978 "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
3979 fdata->num, wtap_file_type_subtype_string(args->file_type),
3980 err_info != NULL ? err_info : "no information supplied");
3985 display_basename = g_filename_display_basename(args->fname);
3986 simple_error_message_box(
3987 "An error occurred while writing to the file \"%s\": %s.",
3988 display_basename, wtap_strerror(err));
3989 g_free(display_basename);
3994 write_failure_alert_box(args->fname, err);
3999 g_free(hdr.opt_comment);
4004 * Can this capture file be written out in any format using Wiretap
4005 * rather than by copying the raw data?
4008 cf_can_write_with_wiretap(capture_file *cf)
4010 /* We don't care whether we support the comments in this file or not;
4011 if we can't, we'll offer the user the option of discarding the
4013 return wtap_dump_can_write(cf->linktypes, 0);
4017 * Should we let the user do a save?
4021 * the file has unsaved changes, and we can save it in some
4022 * format through Wiretap
4026 * the file is a temporary file and has no unsaved changes (so
4027 * that "saving" it just means copying it).
4029 * XXX - we shouldn't allow files to be edited if they can't be saved,
4030 * so cf->unsaved_changes should be true only if the file can be saved.
4032 * We don't care whether we support the comments in this file or not;
4033 * if we can't, we'll offer the user the option of discarding the
4037 cf_can_save(capture_file *cf)
4039 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4040 /* Saved changes, and we can write it out with Wiretap. */
4044 if (cf->is_tempfile && !cf->unsaved_changes) {
4046 * Temporary file with no unsaved changes, so we can just do a
4052 /* Nothing to save. */
4057 * Should we let the user do a "save as"?
4061 * we can save it in some format through Wiretap
4065 * the file is a temporary file and has no unsaved changes (so
4066 * that "saving" it just means copying it).
4068 * XXX - we shouldn't allow files to be edited if they can't be saved,
4069 * so cf->unsaved_changes should be true only if the file can be saved.
4071 * We don't care whether we support the comments in this file or not;
4072 * if we can't, we'll offer the user the option of discarding the
4076 cf_can_save_as(capture_file *cf)
4078 if (wtap_dump_can_write(cf->linktypes, 0)) {
4079 /* We can write it out with Wiretap. */
4083 if (cf->is_tempfile && !cf->unsaved_changes) {
4085 * Temporary file with no unsaved changes, so we can just do a
4091 /* Nothing to save. */
4096 * Does this file have unsaved data?
4099 cf_has_unsaved_data(capture_file *cf)
4102 * If this is a temporary file, or a file with unsaved changes, it
4105 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4109 * Quick scan to find packet offsets.
4111 static cf_read_status_t
4112 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4114 const struct wtap_pkthdr *phdr;
4118 progdlg_t *progbar = NULL;
4121 GTimeVal start_time;
4122 gchar status_str[100];
4123 gint64 progbar_nextstep;
4124 gint64 progbar_quantum;
4129 int displayed_once = 0;
4132 /* Close the old handle. */
4133 wtap_close(cf->wth);
4135 /* Open the new file. */
4136 /* XXX: this will go through all open_routines for a matching one. But right
4137 now rescan_file() is only used when a file is being saved to a different
4138 format than the original, and the user is not given a choice of which
4139 reader to use (only which format to save it in), so doing this makes
4141 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4142 if (cf->wth == NULL) {
4143 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4144 return CF_READ_ERROR;
4147 /* We're scanning a file whose contents should be the same as what
4148 we had before, so we don't discard dissection state etc.. */
4151 /* Set the file name because we need it to set the follow stream filter.
4152 XXX - is that still true? We need it for other reasons, though,
4154 cf->filename = g_strdup(fname);
4156 /* Indicate whether it's a permanent or temporary file. */
4157 cf->is_tempfile = is_tempfile;
4159 /* No user changes yet. */
4160 cf->unsaved_changes = FALSE;
4162 cf->cd_t = wtap_file_type_subtype(cf->wth);
4163 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4165 cf->snap = wtap_snapshot_length(cf->wth);
4166 if (cf->snap == 0) {
4167 /* Snapshot length not known. */
4168 cf->has_snap = FALSE;
4169 cf->snap = WTAP_MAX_PACKET_SIZE;
4171 cf->has_snap = TRUE;
4173 name_ptr = g_filename_display_basename(cf->filename);
4175 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4177 /* Record whether the file is compressed.
4178 XXX - do we know this at open time? */
4179 cf->iscompressed = wtap_iscompressed(cf->wth);
4181 /* Find the size of the file. */
4182 size = wtap_file_size(cf->wth, NULL);
4184 /* Update the progress bar when it gets to this value. */
4185 progbar_nextstep = 0;
4186 /* When we reach the value that triggers a progress bar update,
4187 bump that value by this amount. */
4189 progbar_quantum = size/N_PROGBAR_UPDATES;
4190 if (progbar_quantum < MIN_QUANTUM)
4191 progbar_quantum = MIN_QUANTUM;
4193 progbar_quantum = 0;
4195 cf->stop_flag = FALSE;
4196 g_get_current_time(&start_time);
4199 phdr = wtap_phdr(cf->wth);
4200 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4202 fdata = frame_data_sequence_find(cf->frames, framenum);
4203 fdata->file_off = data_offset;
4206 cf->f_datalen = wtap_read_so_far(cf->wth);
4208 /* Create the progress bar if necessary.
4209 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4211 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4212 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4213 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4214 TRUE, &cf->stop_flag, &start_time, progbar_val);
4217 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4218 when we update it, we have to run the GTK+ main loop to get it
4219 to repaint what's pending, and doing so may involve an "ioctl()"
4220 to see if there's any pending input from an X server, and doing
4221 that for every packet can be costly, especially on a big file. */
4222 if (cf->f_datalen >= progbar_nextstep) {
4223 if (progbar != NULL) {
4224 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4225 /* update the packet bar content on the first run or frequently on very large files */
4227 if (progbar_quantum > 500000 || displayed_once == 0) {
4228 if ((auto_scroll_live || displayed_once == 0 || cf->displayed_count < 1000) && cf->count != 0) {
4230 packets_bar_update();
4233 #endif /* HAVE_LIBPCAP */
4234 update_progress_dlg(progbar, progbar_val, status_str);
4236 progbar_nextstep += progbar_quantum;
4240 if (cf->stop_flag) {
4241 /* Well, the user decided to abort the rescan. Sadly, as this
4242 isn't a reread, recovering is difficult, so we'll just
4243 close the current capture. */
4247 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4248 it's not already there.
4249 XXX - yes, this is O(N), so if every packet had a different
4250 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4251 there are probably going to be a small number of encapsulation types
4253 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4256 /* Free the display name */
4259 /* We're done reading the file; destroy the progress bar if it was created. */
4260 if (progbar != NULL)
4261 destroy_progress_dlg(progbar);
4263 /* We're done reading sequentially through the file. */
4264 cf->state = FILE_READ_DONE;
4266 /* Close the sequential I/O side, to free up memory it requires. */
4267 wtap_sequential_close(cf->wth);
4269 /* compute the time it took to load the file */
4270 compute_elapsed(cf, &start_time);
4272 /* Set the file encapsulation type now; we don't know what it is until
4273 we've looked at all the packets, as we don't know until then whether
4274 there's more than one type (and thus whether it's
4275 WTAP_ENCAP_PER_PACKET). */
4276 cf->lnk_t = wtap_file_encap(cf->wth);
4278 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4280 if (cf->stop_flag) {
4281 /* Our caller will give up at this point. */
4282 return CF_READ_ABORTED;
4286 /* Put up a message box noting that the read failed somewhere along
4287 the line. Don't throw out the stuff we managed to read, though,
4291 case WTAP_ERR_UNSUPPORTED:
4292 simple_error_message_box(
4293 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4294 err_info != NULL ? err_info : "no information supplied");
4298 case WTAP_ERR_SHORT_READ:
4299 simple_error_message_box(
4300 "The capture file appears to have been cut short"
4301 " in the middle of a packet.");
4304 case WTAP_ERR_BAD_FILE:
4305 simple_error_message_box(
4306 "The capture file appears to be damaged or corrupt.\n(%s)",
4307 err_info != NULL ? err_info : "no information supplied");
4311 case WTAP_ERR_DECOMPRESS:
4312 simple_error_message_box(
4313 "The compressed capture file appears to be damaged or corrupt.\n"
4315 err_info != NULL ? err_info : "no information supplied");
4320 simple_error_message_box(
4321 "An error occurred while reading the"
4322 " capture file: %s.", wtap_strerror(*err));
4325 return CF_READ_ERROR;
4331 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4332 gboolean compressed, gboolean discard_comments,
4333 gboolean dont_reopen)
4336 gchar *fname_new = NULL;
4339 addrinfo_lists_t *addr_lists;
4343 gchar *display_basename;
4350 save_callback_args_t callback_args;
4352 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4354 addr_lists = get_addrinfo_list();
4356 if (save_format == cf->cd_t && compressed == cf->iscompressed
4357 && !discard_comments && !cf->unsaved_changes
4358 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4359 /* We're saving in the format it's already in, and we're
4360 not discarding comments, and there are no changes we have
4361 in memory that aren't saved to the file, and we have no name
4362 resolution blocks to write, so we can just move or copy the raw data. */
4364 if (cf->is_tempfile) {
4365 /* The file being saved is a temporary file from a live
4366 capture, so it doesn't need to stay around under that name;
4367 first, try renaming the capture buffer file to the new name.
4368 This acts as a "safe save", in that, if the file already
4369 exists, the existing file will be removed only if the rename
4372 Sadly, on Windows, as we have the current capture file
4373 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4374 (to cause the rename to remove an existing target), as
4375 done by ws_stdio_rename() (ws_rename() is #defined to
4376 be ws_stdio_rename() on Windows) will fail.
4378 According to the MSDN documentation for CreateFile(), if,
4379 when we open a capture file, we were to directly do a CreateFile(),
4380 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4381 convert it to a file descriptor with _open_osfhandle(),
4382 that would allow the file to be renamed out from under us.
4384 However, that doesn't work in practice. Perhaps the problem
4385 is that the process doing the rename is the process that
4386 has the file open. */
4388 if (ws_rename(cf->filename, fname) == 0) {
4389 /* That succeeded - there's no need to copy the source file. */
4390 how_to_save = SAVE_WITH_MOVE;
4392 if (errno == EXDEV) {
4393 /* They're on different file systems, so we have to copy the
4395 how_to_save = SAVE_WITH_COPY;
4397 /* The rename failed, but not because they're on different
4398 file systems - put up an error message. (Or should we
4399 just punt and try to copy? The only reason why I'd
4400 expect the rename to fail and the copy to succeed would
4401 be if we didn't have permission to remove the file from
4402 the temporary directory, and that might be fixable - but
4403 is it worth requiring the user to go off and fix it?) */
4404 cf_rename_failure_alert_box(fname, errno);
4409 how_to_save = SAVE_WITH_COPY;
4412 /* It's a permanent file, so we should copy it, and not remove the
4414 how_to_save = SAVE_WITH_COPY;
4417 if (how_to_save == SAVE_WITH_COPY) {
4418 /* Copy the file, if we haven't moved it. If we're overwriting
4419 an existing file, we do it with a "safe save", by writing
4420 to a new file and, if the write succeeds, renaming the
4421 new file on top of the old file. */
4422 if (file_exists(fname)) {
4423 fname_new = g_strdup_printf("%s~", fname);
4424 if (!copy_file_binary_mode(cf->filename, fname_new))
4427 if (!copy_file_binary_mode(cf->filename, fname))
4432 /* Either we're saving in a different format or we're saving changes,
4433 such as added, modified, or removed comments, that haven't yet
4434 been written to the underlying file; we can't do that by copying
4435 or moving the capture file, we have to do it by writing the packets
4438 wtapng_section_t *shb_hdr = NULL;
4439 wtapng_iface_descriptions_t *idb_inf = NULL;
4440 wtapng_name_res_t *nrb_hdr = NULL;
4443 /* XXX: what free's this shb_hdr? */
4444 shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
4445 idb_inf = wtap_file_get_idb_info(cf->wth);
4446 nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
4448 /* Determine what file encapsulation type we should use. */
4449 encap = wtap_dump_file_encap_type(cf->linktypes);
4451 if (file_exists(fname)) {
4452 /* We're overwriting an existing file; write out to a new file,
4453 and, if that succeeds, rename the new file on top of the
4454 old file. That makes this a "safe save", so that we don't
4455 lose the old file if we have a problem writing out the new
4456 file. (If the existing file is the current capture file,
4457 we *HAVE* to do that, otherwise we're overwriting the file
4458 from which we're reading the packets that we're writing!) */
4459 fname_new = g_strdup_printf("%s~", fname);
4460 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4461 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4463 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4464 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4470 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4474 /* Add address resolution */
4475 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4477 /* Iterate through the list of packets, processing all the packets. */
4478 callback_args.pdh = pdh;
4479 callback_args.fname = fname;
4480 callback_args.file_type = save_format;
4481 switch (process_specified_records(cf, NULL, "Saving", "packets",
4482 TRUE, save_record, &callback_args)) {
4485 /* Completed successfully. */
4489 /* The user decided to abort the saving.
4490 If we're writing to a temporary file, remove it.
4491 XXX - should we do so even if we're not writing to a
4493 wtap_dump_close(pdh, &err);
4494 if (fname_new != NULL)
4495 ws_unlink(fname_new);
4496 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4497 return CF_WRITE_ABORTED;
4500 /* Error while saving.
4501 If we're writing to a temporary file, remove it. */
4502 if (fname_new != NULL)
4503 ws_unlink(fname_new);
4504 wtap_dump_close(pdh, &err);
4508 if (!wtap_dump_close(pdh, &err)) {
4509 cf_close_failure_alert_box(fname, err);
4513 how_to_save = SAVE_WITH_WTAP;
4516 if (fname_new != NULL) {
4517 /* We wrote out to fname_new, and should rename it on top of
4518 fname. fname_new is now closed, so that should be possible even
4519 on Windows. However, on Windows, we first need to close whatever
4520 file descriptors we have open for fname. */
4522 wtap_fdclose(cf->wth);
4524 /* Now do the rename. */
4525 if (ws_rename(fname_new, fname) == -1) {
4526 /* Well, the rename failed. */
4527 cf_rename_failure_alert_box(fname, errno);
4529 /* Attempt to reopen the random file descriptor using the
4530 current file's filename. (At this point, the sequential
4531 file descriptor is closed.) */
4532 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4533 /* Oh, well, we're screwed. */
4534 display_basename = g_filename_display_basename(cf->filename);
4535 simple_error_message_box(
4536 file_open_error_message(err, FALSE), display_basename);
4537 g_free(display_basename);
4544 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4545 cf->unsaved_changes = FALSE;
4548 switch (how_to_save) {
4550 case SAVE_WITH_MOVE:
4551 /* We just moved the file, so the wtap structure refers to the
4552 new file, and all the information other than the filename
4553 and the "is temporary" status applies to the new file; just
4555 g_free(cf->filename);
4556 cf->filename = g_strdup(fname);
4557 cf->is_tempfile = FALSE;
4558 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4561 case SAVE_WITH_COPY:
4562 /* We just copied the file, s all the information other than
4563 the wtap structure, the filename, and the "is temporary"
4564 status applies to the new file; just update that. */
4565 wtap_close(cf->wth);
4566 /* Although we're just "copying" and then opening the copy, it will
4567 try all open_routine readers to open the copy, so we need to
4568 reset the cfile's open_type. */
4569 cf->open_type = WTAP_TYPE_AUTO;
4570 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4571 if (cf->wth == NULL) {
4572 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4575 g_free(cf->filename);
4576 cf->filename = g_strdup(fname);
4577 cf->is_tempfile = FALSE;
4579 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4582 case SAVE_WITH_WTAP:
4583 /* Open and read the file we saved to.
4585 XXX - this is somewhat of a waste; we already have the
4586 packets, all this gets us is updated file type information
4587 (which we could just stuff into "cf"), and having the new
4588 file be the one we have opened and from which we're reading
4589 the data, and it means we have to spend time opening and
4590 reading the file, which could be a significant amount of
4591 time if the file is large.
4593 If the capture-file-writing code were to return the
4594 seek offset of each packet it writes, we could save that
4595 in the frame_data structure for the frame, and just open
4596 the file without reading it again...
4598 ...as long as, for gzipped files, the process of writing
4599 out the file *also* generates the information needed to
4600 support fast random access to the compressed file. */
4601 /* rescan_file will cause us to try all open_routines, so
4602 reset cfile's open_type */
4603 cf->open_type = WTAP_TYPE_AUTO;
4604 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4605 /* The rescan failed; just close the file. Either
4606 a dialog was popped up for the failure, so the
4607 user knows what happened, or they stopped the
4608 rescan, in which case they know what happened. */
4614 /* If we were told to discard the comments, do so. */
4615 if (discard_comments) {
4616 /* Remove SHB comment, if any. */
4617 wtap_write_shb_comment(cf->wth, NULL);
4619 /* remove all user comments */
4620 for (framenum = 1; framenum <= cf->count; framenum++) {
4621 fdata = frame_data_sequence_find(cf->frames, framenum);
4623 fdata->flags.has_phdr_comment = FALSE;
4624 fdata->flags.has_user_comment = FALSE;
4627 if (cf->frames_user_comments) {
4628 g_tree_destroy(cf->frames_user_comments);
4629 cf->frames_user_comments = NULL;
4632 cf->packet_comment_count = 0;
4638 if (fname_new != NULL) {
4639 /* We were trying to write to a temporary file; get rid of it if it
4640 exists. (We don't care whether this fails, as, if it fails,
4641 there's not much we can do about it. I guess if it failed for
4642 a reason other than "it doesn't exist", we could report an
4643 error, so the user knows there's a junk file that they might
4644 want to clean up.) */
4645 ws_unlink(fname_new);
4648 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4649 return CF_WRITE_ERROR;
4653 cf_export_specified_packets(capture_file *cf, const char *fname,
4654 packet_range_t *range, guint save_format,
4655 gboolean compressed)
4657 gchar *fname_new = NULL;
4660 save_callback_args_t callback_args;
4661 wtapng_section_t *shb_hdr = NULL;
4662 wtapng_iface_descriptions_t *idb_inf = NULL;
4663 wtapng_name_res_t *nrb_hdr = NULL;
4666 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4668 packet_range_process_init(range);
4670 /* We're writing out specified packets from the specified capture
4671 file to another file. Even if all captured packets are to be
4672 written, don't special-case the operation - read each packet
4673 and then write it out if it's one of the specified ones. */
4675 /* XXX: what free's this shb_hdr? */
4676 shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
4677 idb_inf = wtap_file_get_idb_info(cf->wth);
4678 nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
4680 /* Determine what file encapsulation type we should use. */
4681 encap = wtap_dump_file_encap_type(cf->linktypes);
4683 if (file_exists(fname)) {
4684 /* We're overwriting an existing file; write out to a new file,
4685 and, if that succeeds, rename the new file on top of the
4686 old file. That makes this a "safe save", so that we don't
4687 lose the old file if we have a problem writing out the new
4688 file. (If the existing file is the current capture file,
4689 we *HAVE* to do that, otherwise we're overwriting the file
4690 from which we're reading the packets that we're writing!) */
4691 fname_new = g_strdup_printf("%s~", fname);
4692 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4693 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4695 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4696 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4702 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4706 /* Add address resolution */
4707 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4709 /* Iterate through the list of packets, processing the packets we were
4712 XXX - we've already called "packet_range_process_init(range)", but
4713 "process_specified_records()" will do it again. Fortunately,
4714 that's harmless in this case, as we haven't done anything to
4715 "range" since we initialized it. */
4716 callback_args.pdh = pdh;
4717 callback_args.fname = fname;
4718 callback_args.file_type = save_format;
4719 switch (process_specified_records(cf, range, "Writing", "specified records",
4720 TRUE, save_record, &callback_args)) {
4723 /* Completed successfully. */
4727 /* The user decided to abort the saving.
4728 If we're writing to a temporary file, remove it.
4729 XXX - should we do so even if we're not writing to a
4731 wtap_dump_close(pdh, &err);
4732 if (fname_new != NULL)
4733 ws_unlink(fname_new);
4734 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4735 return CF_WRITE_ABORTED;
4739 /* Error while saving.
4740 If we're writing to a temporary file, remove it. */
4741 if (fname_new != NULL)
4742 ws_unlink(fname_new);
4743 wtap_dump_close(pdh, &err);
4747 if (!wtap_dump_close(pdh, &err)) {
4748 cf_close_failure_alert_box(fname, err);
4752 if (fname_new != NULL) {
4753 /* We wrote out to fname_new, and should rename it on top of
4754 fname; fname is now closed, so that should be possible even
4755 on Windows. Do the rename. */
4756 if (ws_rename(fname_new, fname) == -1) {
4757 /* Well, the rename failed. */
4758 cf_rename_failure_alert_box(fname, errno);
4763 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4767 if (fname_new != NULL) {
4768 /* We were trying to write to a temporary file; get rid of it if it
4769 exists. (We don't care whether this fails, as, if it fails,
4770 there's not much we can do about it. I guess if it failed for
4771 a reason other than "it doesn't exist", we could report an
4772 error, so the user knows there's a junk file that they might
4773 want to clean up.) */
4774 ws_unlink(fname_new);
4777 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4778 return CF_WRITE_ERROR;
4782 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4783 gboolean for_writing, int file_type)
4785 gchar *display_basename;
4788 /* Wiretap error. */
4789 display_basename = g_filename_display_basename(filename);
4792 case WTAP_ERR_NOT_REGULAR_FILE:
4793 simple_error_message_box(
4794 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4798 case WTAP_ERR_RANDOM_OPEN_PIPE:
4799 /* Seen only when opening a capture file for reading. */
4800 simple_error_message_box(
4801 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4802 "To capture from a pipe or FIFO use wireshark -i -",
4806 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4807 /* Seen only when opening a capture file for reading. */
4808 simple_error_message_box(
4809 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4813 case WTAP_ERR_UNSUPPORTED:
4814 /* Seen only when opening a capture file for reading. */
4815 simple_error_message_box(
4816 "The file \"%s\" contains record data that Wireshark doesn't support.\n"
4819 err_info != NULL ? err_info : "no information supplied");
4823 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4824 /* Seen only when opening a capture file for writing. */
4825 simple_error_message_box(
4826 "The file \"%s\" is a pipe, and %s capture files can't be "
4827 "written to a pipe.",
4828 display_basename, wtap_file_type_subtype_string(file_type));
4831 case WTAP_ERR_UNWRITABLE_FILE_TYPE:
4832 /* Seen only when opening a capture file for writing. */
4833 simple_error_message_box(
4834 "Wireshark doesn't support writing capture files in that format.");
4837 case WTAP_ERR_UNWRITABLE_ENCAP:
4838 /* Seen only when opening a capture file for writing. */
4839 simple_error_message_box("Wireshark can't save this capture in that format.");
4842 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4844 simple_error_message_box(
4845 "Wireshark can't save this capture in that format.");
4847 simple_error_message_box(
4848 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4853 case WTAP_ERR_BAD_FILE:
4854 /* Seen only when opening a capture file for reading. */
4855 simple_error_message_box(
4856 "The file \"%s\" appears to be damaged or corrupt.\n"
4859 err_info != NULL ? err_info : "no information supplied");
4863 case WTAP_ERR_CANT_OPEN:
4865 simple_error_message_box(
4866 "The file \"%s\" could not be created for some unknown reason.",
4869 simple_error_message_box(
4870 "The file \"%s\" could not be opened for some unknown reason.",
4875 case WTAP_ERR_SHORT_READ:
4876 simple_error_message_box(
4877 "The file \"%s\" appears to have been cut short"
4878 " in the middle of a packet or other data.",
4882 case WTAP_ERR_SHORT_WRITE:
4883 simple_error_message_box(
4884 "A full header couldn't be written to the file \"%s\".",
4888 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4889 simple_error_message_box(
4890 "This file type cannot be written as a compressed file.");
4893 case WTAP_ERR_DECOMPRESS:
4894 simple_error_message_box(
4895 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4896 "(%s)", display_basename,
4897 err_info != NULL ? err_info : "no information supplied");
4902 simple_error_message_box(
4903 "The file \"%s\" could not be %s: %s.",
4905 for_writing ? "created" : "opened",
4906 wtap_strerror(err));
4909 g_free(display_basename);
4912 open_failure_alert_box(filename, err, for_writing);
4917 * XXX - whether we mention the source pathname, the target pathname,
4918 * or both depends on the error and on what we find if we look for
4919 * one or both of them.
4922 cf_rename_failure_alert_box(const char *filename, int err)
4924 gchar *display_basename;
4926 display_basename = g_filename_display_basename(filename);
4930 /* XXX - should check whether the source exists and, if not,
4931 report it as the problem and, if so, report the destination
4933 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4938 /* XXX - if we're doing a rename after a safe save, we should
4939 probably say something else. */
4940 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4945 /* XXX - this should probably mention both the source and destination
4947 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4948 display_basename, wtap_strerror(err));
4951 g_free(display_basename);
4954 /* Check for write errors - if the file is being written to an NFS server,
4955 a write error may not show up until the file is closed, as NFS clients
4956 might not send writes to the server until the "write()" call finishes,
4957 so that the write may fail on the server but the "write()" may succeed. */
4959 cf_close_failure_alert_box(const char *filename, int err)
4961 gchar *display_basename;
4964 /* Wiretap error. */
4965 display_basename = g_filename_display_basename(filename);
4968 case WTAP_ERR_CANT_CLOSE:
4969 simple_error_message_box(
4970 "The file \"%s\" couldn't be closed for some unknown reason.",
4974 case WTAP_ERR_SHORT_WRITE:
4975 simple_error_message_box(
4976 "Not all the packets could be written to the file \"%s\".",
4981 simple_error_message_box(
4982 "An error occurred while closing the file \"%s\": %s.",
4983 display_basename, wtap_strerror(err));
4986 g_free(display_basename);
4989 We assume that a close error from the OS is really a write error. */
4990 write_failure_alert_box(filename, err);
4994 /* Reload the current capture file. */
4996 cf_reload(capture_file *cf) {
4998 gboolean is_tempfile;
5001 /* If the file could be opened, "cf_open()" calls "cf_close()"
5002 to get rid of state for the old capture file before filling in state
5003 for the new capture file. "cf_close()" will remove the file if
5004 it's a temporary file; we don't want that to happen (for one thing,
5005 it'd prevent subsequent reopens from working). Remember whether it's
5006 a temporary file, mark it as not being a temporary file, and then
5007 reopen it as the type of file it was.
5009 Also, "cf_close()" will free "cf->filename", so we must make
5010 a copy of it first. */
5011 filename = g_strdup(cf->filename);
5012 is_tempfile = cf->is_tempfile;
5013 cf->is_tempfile = FALSE;
5014 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5015 switch (cf_read(cf, TRUE)) {
5019 /* Just because we got an error, that doesn't mean we were unable
5020 to read any of the file; we handle what we could get from the
5024 case CF_READ_ABORTED:
5025 /* The user bailed out of re-reading the capture file; the
5026 capture file has been closed - just free the capture file name
5027 string and return (without changing the last containing
5033 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5034 Instead, the file was left open, so we should restore "cf->is_tempfile"
5037 XXX - change the menu? Presumably "cf_open()" will do that;
5038 make sure it does! */
5039 cf->is_tempfile = is_tempfile;
5041 /* "cf_open()" made a copy of the file name we handed it, so
5042 we should free up our copy. */
5052 * indent-tabs-mode: nil
5055 * ex: set shiftwidth=2 tabstop=8 expandtab:
5056 * :indentSize=2:tabSize=8:noTabs=true: