4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <wsutil/tempfile.h>
34 #include <wsutil/file_util.h>
35 #include <wsutil/filesystem.h>
36 #include <wsutil/ws_version_info.h>
38 #include <wiretap/merge.h>
40 #include <epan/exceptions.h>
41 #include <epan/epan-int.h>
42 #include <epan/epan.h>
43 #include <epan/column.h>
44 #include <epan/packet.h>
45 #include <epan/column-utils.h>
46 #include <epan/expert.h>
47 #include <epan/prefs.h>
48 #include <epan/dfilter/dfilter.h>
49 #include <epan/epan_dissect.h>
51 #include <epan/dissectors/packet-ber.h>
52 #include <epan/timestamp.h>
53 #include <epan/dfilter/dfilter-macro.h>
54 #include <epan/strutil.h>
55 #include <epan/addr_resolv.h>
56 #include <epan/color_filters.h>
61 #include "frame_tvbuff.h"
63 #include "ui/alert_box.h"
64 #include "ui/simple_dialog.h"
65 #include "ui/main_statusbar.h"
66 #include "ui/progress_dlg.h"
67 #include "ui/ui_util.h"
69 /* Needed for addrinfo */
70 #ifdef HAVE_SYS_TYPES_H
71 # include <sys/types.h>
74 #ifdef HAVE_SYS_SOCKET_H
75 #include <sys/socket.h>
78 #ifdef HAVE_NETINET_IN_H
79 # include <netinet/in.h>
86 #ifdef HAVE_WINSOCK2_H
87 # include <winsock2.h>
91 # include <ws2tcpip.h>
95 gboolean auto_scroll_live; /* GTK+ only? */
98 static int read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
99 column_info *cinfo, gint64 offset);
101 static void rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect);
108 static match_result match_protocol_tree(capture_file *cf, frame_data *fdata,
110 static void match_subtree_text(proto_node *node, gpointer data);
111 static match_result match_summary_line(capture_file *cf, frame_data *fdata,
113 static match_result match_narrow_and_wide(capture_file *cf, frame_data *fdata,
115 static match_result match_narrow(capture_file *cf, frame_data *fdata,
117 static match_result match_wide(capture_file *cf, frame_data *fdata,
119 static match_result match_binary(capture_file *cf, frame_data *fdata,
121 static match_result match_dfilter(capture_file *cf, frame_data *fdata,
123 static match_result match_marked(capture_file *cf, frame_data *fdata,
125 static match_result match_time_reference(capture_file *cf, frame_data *fdata,
127 static gboolean find_packet(capture_file *cf,
128 match_result (*match_function)(capture_file *, frame_data *, void *),
129 void *criterion, search_direction dir);
131 static const char *cf_get_user_packet_comment(capture_file *cf, const frame_data *fd);
133 static void cf_open_failure_alert_box(const char *filename, int err,
134 gchar *err_info, gboolean for_writing,
136 static void cf_rename_failure_alert_box(const char *filename, int err);
137 static void cf_close_failure_alert_box(const char *filename, int err);
138 static void ref_time_packets(capture_file *cf);
139 /* Update the progress bar this many times when reading a file. */
140 #define N_PROGBAR_UPDATES 100
141 /* We read around 200k/100ms don't update the progress bar more often than that */
142 #define MIN_QUANTUM 200000
143 #define MIN_NUMBER_OF_PACKET 1500
146 * We could probably use g_signal_...() instead of the callbacks below but that
147 * would require linking our CLI programs to libgobject and creating an object
148 * instance for the signals.
151 cf_callback_t cb_fct;
153 } cf_callback_data_t;
155 static GList *cf_callbacks = NULL;
158 cf_callback_invoke(int event, gpointer data)
160 cf_callback_data_t *cb;
161 GList *cb_item = cf_callbacks;
163 /* there should be at least one interested */
164 g_assert(cb_item != NULL);
166 while (cb_item != NULL) {
167 cb = (cf_callback_data_t *)cb_item->data;
168 cb->cb_fct(event, data, cb->user_data);
169 cb_item = g_list_next(cb_item);
175 cf_callback_add(cf_callback_t func, gpointer user_data)
177 cf_callback_data_t *cb;
179 cb = g_new(cf_callback_data_t,1);
181 cb->user_data = user_data;
183 cf_callbacks = g_list_prepend(cf_callbacks, cb);
187 cf_callback_remove(cf_callback_t func, gpointer user_data)
189 cf_callback_data_t *cb;
190 GList *cb_item = cf_callbacks;
192 while (cb_item != NULL) {
193 cb = (cf_callback_data_t *)cb_item->data;
194 if (cb->cb_fct == func && cb->user_data == user_data) {
195 cf_callbacks = g_list_remove(cf_callbacks, cb);
199 cb_item = g_list_next(cb_item);
202 g_assert_not_reached();
206 cf_timestamp_auto_precision(capture_file *cf)
210 /* don't try to get the file's precision if none is opened */
211 if (cf->state == FILE_CLOSED) {
215 /* Set the column widths of those columns that show the time in
216 "command-line-specified" format. */
217 for (i = 0; i < cf->cinfo.num_cols; i++) {
218 if (col_has_time_fmt(&cf->cinfo, i)) {
219 packet_list_resize_column(i);
225 cf_get_computed_elapsed(capture_file *cf)
227 return cf->computed_elapsed;
231 * GLIB_CHECK_VERSION(2,28,0) adds g_get_real_time which could minimize or
234 static void compute_elapsed(capture_file *cf, GTimeVal *start_time)
239 g_get_current_time(&time_now);
241 delta_time = (time_now.tv_sec - start_time->tv_sec) * 1e6 +
242 time_now.tv_usec - start_time->tv_usec;
244 cf->computed_elapsed = (gulong) (delta_time / 1000); /* ms */
247 static const nstime_t *
248 ws_get_frame_ts(void *data, guint32 frame_num)
250 capture_file *cf = (capture_file *) data;
252 if (cf->prev_dis && cf->prev_dis->num == frame_num)
253 return &cf->prev_dis->abs_ts;
255 if (cf->prev_cap && cf->prev_cap->num == frame_num)
256 return &cf->prev_cap->abs_ts;
259 frame_data *fd = frame_data_sequence_find(cf->frames, frame_num);
261 return (fd) ? &fd->abs_ts : NULL;
268 ws_get_user_comment(void *data, const frame_data *fd)
270 capture_file *cf = (capture_file *) data;
272 return cf_get_user_packet_comment(cf, fd);
276 ws_epan_new(capture_file *cf)
278 epan_t *epan = epan_new();
281 epan->get_frame_ts = ws_get_frame_ts;
282 epan->get_interface_name = cap_file_get_interface_name;
283 epan->get_user_comment = ws_get_user_comment;
289 cf_open(capture_file *cf, const char *fname, unsigned int type, gboolean is_tempfile, int *err)
294 wth = wtap_open_offline(fname, type, err, &err_info, TRUE);
298 /* The open succeeded. Close whatever capture file we had open,
299 and fill in the information for this file. */
302 /* Initialize the packet header. */
303 wtap_phdr_init(&cf->phdr);
305 /* XXX - we really want to initialize this after we've read all
306 the packets, so we know how much we'll ultimately need. */
307 ws_buffer_init(&cf->buf, 1500);
309 /* Create new epan session for dissection.
310 * (The old one was freed in cf_close().)
312 cf->epan = ws_epan_new(cf);
314 /* We're about to start reading the file. */
315 cf->state = FILE_READ_IN_PROGRESS;
320 /* Set the file name because we need it to set the follow stream filter.
321 XXX - is that still true? We need it for other reasons, though,
323 cf->filename = g_strdup(fname);
325 /* Indicate whether it's a permanent or temporary file. */
326 cf->is_tempfile = is_tempfile;
328 /* No user changes yet. */
329 cf->unsaved_changes = FALSE;
331 cf->computed_elapsed = 0;
333 cf->cd_t = wtap_file_type_subtype(cf->wth);
334 cf->open_type = type;
335 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
337 cf->packet_comment_count = 0;
338 cf->displayed_count = 0;
339 cf->marked_count = 0;
340 cf->ignored_count = 0;
341 cf->ref_time_count = 0;
342 cf->drops_known = FALSE;
344 cf->snap = wtap_snapshot_length(cf->wth);
346 /* Snapshot length not known. */
347 cf->has_snap = FALSE;
348 cf->snap = WTAP_MAX_PACKET_SIZE;
352 /* Allocate a frame_data_sequence for the frames in this file */
353 cf->frames = new_frame_data_sequence();
355 nstime_set_zero(&cf->elapsed_time);
361 /* Adjust timestamp precision if auto is selected, col width will be adjusted */
362 cf_timestamp_auto_precision(cf);
364 packet_list_queue_draw();
365 cf_callback_invoke(cf_cb_file_opened, cf);
367 if (cf->cd_t == WTAP_FILE_TYPE_SUBTYPE_BER) {
368 /* tell the BER dissector the file name */
369 ber_set_filename(cf->filename);
372 wtap_set_cb_new_ipv4(cf->wth, add_ipv4_name);
373 wtap_set_cb_new_ipv6(cf->wth, (wtap_new_ipv6_callback_t) add_ipv6_name);
378 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
383 * Add an encapsulation type to cf->linktypes.
386 cf_add_encapsulation_type(capture_file *cf, int encap)
390 for (i = 0; i < cf->linktypes->len; i++) {
391 if (g_array_index(cf->linktypes, gint, i) == encap)
392 return; /* it's already there */
394 /* It's not already there - add it. */
395 g_array_append_val(cf->linktypes, encap);
398 /* Reset everything to a pristine state */
400 cf_close(capture_file *cf)
402 cf->stop_flag = FALSE;
403 if (cf->state == FILE_CLOSED)
404 return; /* Nothing to do */
406 /* Die if we're in the middle of reading a file. */
407 g_assert(cf->state != FILE_READ_IN_PROGRESS);
409 cf_callback_invoke(cf_cb_file_closing, cf);
411 /* close things, if not already closed before */
412 color_filters_cleanup();
418 /* We have no file open... */
419 if (cf->filename != NULL) {
420 /* If it's a temporary file, remove it. */
422 ws_unlink(cf->filename);
423 g_free(cf->filename);
426 /* ...which means we have no changes to that file to save. */
427 cf->unsaved_changes = FALSE;
429 /* no open_routine type */
430 cf->open_type = WTAP_TYPE_AUTO;
432 /* Clean up the packet header. */
433 wtap_phdr_cleanup(&cf->phdr);
435 /* Free up the packet buffer. */
436 ws_buffer_free(&cf->buf);
438 dfilter_free(cf->rfcode);
440 if (cf->frames != NULL) {
441 free_frame_data_sequence(cf->frames);
444 #ifdef WANT_PACKET_EDITOR
445 if (cf->edited_frames) {
446 g_tree_destroy(cf->edited_frames);
447 cf->edited_frames = NULL;
450 if (cf->frames_user_comments) {
451 g_tree_destroy(cf->frames_user_comments);
452 cf->frames_user_comments = NULL;
454 cf_unselect_packet(cf); /* nothing to select */
455 cf->first_displayed = 0;
456 cf->last_displayed = 0;
458 /* No frames, no frame selected, no field in that frame selected. */
460 cf->current_frame = 0;
462 cf->finfo_selected = NULL;
464 /* No frame link-layer types, either. */
465 if (cf->linktypes != NULL) {
466 g_array_free(cf->linktypes, TRUE);
467 cf->linktypes = NULL;
470 /* Clear the packet list. */
471 packet_list_freeze();
476 nstime_set_zero(&cf->elapsed_time);
478 reset_tap_listeners();
483 /* We have no file open. */
484 cf->state = FILE_CLOSED;
486 cf_callback_invoke(cf_cb_file_closed, cf);
490 calc_progbar_val(capture_file *cf, gint64 size, gint64 file_pos, gchar *status_str, gulong status_size)
494 progbar_val = (gfloat) file_pos / (gfloat) size;
495 if (progbar_val > 1.0) {
497 /* The file probably grew while we were reading it.
498 * Update file size, and try again.
500 size = wtap_file_size(cf->wth, NULL);
503 progbar_val = (gfloat) file_pos / (gfloat) size;
505 /* If it's still > 1, either "wtap_file_size()" failed (in which
506 * case there's not much we can do about it), or the file
507 * *shrank* (in which case there's not much we can do about
508 * it); just clip the progress value at 1.0.
510 if (progbar_val > 1.0f)
514 g_snprintf(status_str, status_size,
515 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
516 file_pos / 1024, size / 1024);
522 cf_read(capture_file *cf, gboolean reloading)
525 gchar *err_info = NULL;
527 progdlg_t *progbar = NULL;
531 volatile gboolean create_proto_tree;
535 /* Compile the current display filter.
536 * We assume this will not fail since cf->dfilter is only set in
537 * cf_filter IFF the filter was valid.
539 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
540 g_assert(!cf->dfilter || (compiled && dfcode));
542 /* Get the union of the flags for all tap listeners. */
543 tap_flags = union_of_tap_listener_flags();
545 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
547 reset_tap_listeners();
549 name_ptr = g_filename_display_basename(cf->filename);
552 cf_callback_invoke(cf_cb_file_reload_started, cf);
554 cf_callback_invoke(cf_cb_file_read_started, cf);
556 /* Record whether the file is compressed.
557 XXX - do we know this at open time? */
558 cf->iscompressed = wtap_iscompressed(cf->wth);
560 /* The packet list window will be empty until the file is completly loaded */
561 packet_list_freeze();
563 cf->stop_flag = FALSE;
564 g_get_current_time(&start_time);
566 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
575 gint64 progbar_quantum;
576 gint64 progbar_nextstep;
578 gchar status_str[100];
582 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
584 /* Find the size of the file. */
585 size = wtap_file_size(cf->wth, NULL);
587 /* Update the progress bar when it gets to this value. */
588 progbar_nextstep = 0;
589 /* When we reach the value that triggers a progress bar update,
590 bump that value by this amount. */
592 progbar_quantum = size/N_PROGBAR_UPDATES;
593 if (progbar_quantum < MIN_QUANTUM)
594 progbar_quantum = MIN_QUANTUM;
598 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
601 file_pos = wtap_read_so_far(cf->wth);
603 /* Create the progress bar if necessary.
604 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
606 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
607 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
609 progbar = delayed_create_progress_dlg(cf->window, "Reloading", name_ptr,
610 TRUE, &cf->stop_flag, &start_time, progbar_val);
612 progbar = delayed_create_progress_dlg(cf->window, "Loading", name_ptr,
613 TRUE, &cf->stop_flag, &start_time, progbar_val);
616 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
617 when we update it, we have to run the GTK+ main loop to get it
618 to repaint what's pending, and doing so may involve an "ioctl()"
619 to see if there's any pending input from an X server, and doing
620 that for every packet can be costly, especially on a big file. */
621 if (file_pos >= progbar_nextstep) {
622 if (progbar != NULL) {
623 progbar_val = calc_progbar_val(cf, size, file_pos, status_str, sizeof(status_str));
624 /* update the packet bar content on the first run or frequently on very large files */
625 update_progress_dlg(progbar, progbar_val, status_str);
626 packets_bar_update();
628 progbar_nextstep += progbar_quantum;
633 /* Well, the user decided to abort the read. He/She will be warned and
634 it might be enough for him/her to work with the already loaded
636 This is especially true for very large capture files, where you don't
637 want to wait loading the whole file (which may last minutes or even
638 hours even on fast machines) just to see that it was the wrong file. */
641 read_packet(cf, dfcode, &edt, cinfo, data_offset);
644 CATCH(OutOfMemoryError) {
645 simple_message_box(ESD_TYPE_ERROR, NULL,
646 "More information and workarounds can be found at\n"
647 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
648 "Sorry, but Wireshark has run out of memory and has to terminate now.");
650 /* Could we close the current capture and free up memory from that? */
652 /* we have to terminate, as we cannot recover from the memory error */
658 /* Free the display name */
661 /* Cleanup and release all dfilter resources */
662 if (dfcode != NULL) {
663 dfilter_free(dfcode);
666 epan_dissect_cleanup(&edt);
668 /* We're done reading the file; destroy the progress bar if it was created. */
670 destroy_progress_dlg(progbar);
672 /* We're done reading sequentially through the file. */
673 cf->state = FILE_READ_DONE;
675 /* Close the sequential I/O side, to free up memory it requires. */
676 wtap_sequential_close(cf->wth);
678 /* Allow the protocol dissectors to free up memory that they
679 * don't need after the sequential run-through of the packets. */
680 postseq_cleanup_all_protocols();
682 /* compute the time it took to load the file */
683 compute_elapsed(cf, &start_time);
685 /* Set the file encapsulation type now; we don't know what it is until
686 we've looked at all the packets, as we don't know until then whether
687 there's more than one type (and thus whether it's
688 WTAP_ENCAP_PER_PACKET). */
689 cf->lnk_t = wtap_file_encap(cf->wth);
691 cf->current_frame = frame_data_sequence_find(cf->frames, cf->first_displayed);
696 cf_callback_invoke(cf_cb_file_reload_finished, cf);
698 cf_callback_invoke(cf_cb_file_read_finished, cf);
700 /* If we have any displayed packets to select, select the first of those
701 packets by making the first row the selected row. */
702 if (cf->first_displayed != 0) {
703 packet_list_select_first_row();
707 simple_message_box(ESD_TYPE_WARN, NULL,
708 "The remaining packets in the file were discarded.\n"
710 "As a lot of packets from the original file will be missing,\n"
711 "remember to be careful when saving the current content to a file.\n",
712 "File loading was cancelled.");
713 return CF_READ_ERROR;
717 /* Put up a message box noting that the read failed somewhere along
718 the line. Don't throw out the stuff we managed to read, though,
722 case WTAP_ERR_UNSUPPORTED:
723 simple_error_message_box(
724 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
725 err_info != NULL ? err_info : "no information supplied");
729 case WTAP_ERR_SHORT_READ:
730 simple_error_message_box(
731 "The capture file appears to have been cut short"
732 " in the middle of a packet.");
735 case WTAP_ERR_BAD_FILE:
736 simple_error_message_box(
737 "The capture file appears to be damaged or corrupt.\n(%s)",
738 err_info != NULL ? err_info : "no information supplied");
742 case WTAP_ERR_DECOMPRESS:
743 simple_error_message_box(
744 "The compressed capture file appears to be damaged or corrupt.\n(%s)",
745 err_info != NULL ? err_info : "no information supplied");
750 simple_error_message_box(
751 "An error occurred while reading the"
752 " capture file: %s.", wtap_strerror(err));
755 return CF_READ_ERROR;
762 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
765 volatile int newly_displayed_packets = 0;
768 gboolean create_proto_tree;
772 /* Compile the current display filter.
773 * We assume this will not fail since cf->dfilter is only set in
774 * cf_filter IFF the filter was valid.
776 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
777 g_assert(!cf->dfilter || (compiled && dfcode));
779 /* Get the union of the flags for all tap listeners. */
780 tap_flags = union_of_tap_listener_flags();
782 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
786 packet_list_check_end();
787 /* Don't freeze/thaw the list when doing live capture */
788 /*packet_list_freeze();*/
790 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
792 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
795 gint64 data_offset = 0;
798 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
800 while (to_read != 0) {
801 wtap_cleareof(cf->wth);
802 if (!wtap_read(cf->wth, err, &err_info, &data_offset)) {
805 if (cf->state == FILE_READ_ABORTED) {
806 /* Well, the user decided to exit Wireshark. Break out of the
807 loop, and let the code below (which is called even if there
808 aren't any packets left to read) exit. */
811 if (read_packet(cf, dfcode, &edt, (column_info *) cinfo, data_offset) != -1) {
812 newly_displayed_packets++;
817 CATCH(OutOfMemoryError) {
818 simple_message_box(ESD_TYPE_ERROR, NULL,
819 "More information and workarounds can be found at\n"
820 "https://wiki.wireshark.org/KnownBugs/OutOfMemory",
821 "Sorry, but Wireshark has run out of memory and has to terminate now.");
823 /* Could we close the current capture and free up memory from that? */
824 return CF_READ_ABORTED;
826 /* we have to terminate, as we cannot recover from the memory error */
832 /* Update the file encapsulation; it might have changed based on the
833 packets we've read. */
834 cf->lnk_t = wtap_file_encap(cf->wth);
836 /* Cleanup and release all dfilter resources */
837 if (dfcode != NULL) {
838 dfilter_free(dfcode);
841 epan_dissect_cleanup(&edt);
843 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
844 cf->count, cf->state, *err);*/
846 /* Don't freeze/thaw the list when doing live capture */
847 /*packet_list_thaw();*/
848 /* With the new packet list the first packet
849 * isn't automatically selected.
851 if (!cf->current_frame)
852 packet_list_select_first_row();
854 /* moving to the end of the packet list - if the user requested so and
855 we have some new packets. */
856 if (newly_displayed_packets && auto_scroll_live && cf->count != 0)
857 packet_list_moveto_end();
859 if (cf->state == FILE_READ_ABORTED) {
860 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
861 so that our caller can kill off the capture child process;
862 this will cause an EOF on the pipe from the child, so
863 "cf_finish_tail()" will be called, and it will clean up
865 return CF_READ_ABORTED;
866 } else if (*err != 0) {
867 /* We got an error reading the capture file.
868 XXX - pop up a dialog box instead? */
869 if (err_info != NULL) {
870 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
871 wtap_strerror(*err), cf->filename, err_info);
874 g_warning("Error \"%s\" while reading \"%s\"",
875 wtap_strerror(*err), cf->filename);
877 return CF_READ_ERROR;
883 cf_fake_continue_tail(capture_file *cf) {
884 cf->state = FILE_READ_DONE;
888 cf_finish_tail(capture_file *cf, int *err)
895 gboolean create_proto_tree;
899 /* Compile the current display filter.
900 * We assume this will not fail since cf->dfilter is only set in
901 * cf_filter IFF the filter was valid.
903 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
904 g_assert(!cf->dfilter || (compiled && dfcode));
906 /* Get the union of the flags for all tap listeners. */
907 tap_flags = union_of_tap_listener_flags();
908 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
910 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
912 if (cf->wth == NULL) {
914 return CF_READ_ERROR;
917 packet_list_check_end();
918 /* Don't freeze/thaw the list when doing live capture */
919 /*packet_list_freeze();*/
921 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
923 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
924 if (cf->state == FILE_READ_ABORTED) {
925 /* Well, the user decided to abort the read. Break out of the
926 loop, and let the code below (which is called even if there
927 aren't any packets left to read) exit. */
930 read_packet(cf, dfcode, &edt, cinfo, data_offset);
933 /* Cleanup and release all dfilter resources */
934 if (dfcode != NULL) {
935 dfilter_free(dfcode);
938 epan_dissect_cleanup(&edt);
940 /* Don't freeze/thaw the list when doing live capture */
941 /*packet_list_thaw();*/
943 if (cf->state == FILE_READ_ABORTED) {
944 /* Well, the user decided to abort the read. We're only called
945 when the child capture process closes the pipe to us (meaning
946 it's probably exited), so we can just close the capture
947 file; we return CF_READ_ABORTED so our caller can do whatever
948 is appropriate when that happens. */
950 return CF_READ_ABORTED;
953 if (auto_scroll_live && cf->count != 0)
954 packet_list_moveto_end();
956 /* We're done reading sequentially through the file. */
957 cf->state = FILE_READ_DONE;
959 /* We're done reading sequentially through the file; close the
960 sequential I/O side, to free up memory it requires. */
961 wtap_sequential_close(cf->wth);
963 /* Allow the protocol dissectors to free up memory that they
964 * don't need after the sequential run-through of the packets. */
965 postseq_cleanup_all_protocols();
967 /* Update the file encapsulation; it might have changed based on the
968 packets we've read. */
969 cf->lnk_t = wtap_file_encap(cf->wth);
971 /* Update the details in the file-set dialog, as the capture file
972 * has likely grown since we first stat-ed it */
973 fileset_update_file(cf->filename);
976 /* We got an error reading the capture file.
977 XXX - pop up a dialog box? */
978 if (err_info != NULL) {
979 g_warning("Error \"%s\" while reading \"%s\" (\"%s\")",
980 wtap_strerror(*err), cf->filename, err_info);
983 g_warning("Error \"%s\" while reading \"%s\"",
984 wtap_strerror(*err), cf->filename);
986 return CF_READ_ERROR;
991 #endif /* HAVE_LIBPCAP */
994 cf_get_display_name(capture_file *cf)
998 /* Return a name to use in displays */
999 if (!cf->is_tempfile) {
1000 /* Get the last component of the file name, and use that. */
1002 displayname = g_filename_display_basename(cf->filename);
1004 displayname=g_strdup("(No file)");
1007 /* The file we read is a temporary file from a live capture or
1008 a merge operation; we don't mention its name, but, if it's
1009 from a capture, give the source of the capture. */
1011 displayname = g_strdup(cf->source);
1013 displayname = g_strdup("(Untitled)");
1019 void cf_set_tempfile_source(capture_file *cf, gchar *source) {
1025 cf->source = g_strdup(source);
1027 cf->source = g_strdup("");
1031 const gchar *cf_get_tempfile_source(capture_file *cf) {
1039 /* XXX - use a macro instead? */
1041 cf_get_packet_count(capture_file *cf)
1046 /* XXX - use a macro instead? */
1048 cf_is_tempfile(capture_file *cf)
1050 return cf->is_tempfile;
1053 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
1055 cf->is_tempfile = is_tempfile;
1059 /* XXX - use a macro instead? */
1060 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
1062 cf->drops_known = drops_known;
1065 /* XXX - use a macro instead? */
1066 void cf_set_drops(capture_file *cf, guint32 drops)
1071 /* XXX - use a macro instead? */
1072 gboolean cf_get_drops_known(capture_file *cf)
1074 return cf->drops_known;
1077 /* XXX - use a macro instead? */
1078 guint32 cf_get_drops(capture_file *cf)
1083 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
1085 cf->rfcode = rfcode;
1089 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
1090 epan_dissect_t *edt, dfilter_t *dfcode, column_info *cinfo,
1091 struct wtap_pkthdr *phdr, const guint8 *buf, gboolean add_to_packet_list)
1095 frame_data_set_before_dissect(fdata, &cf->elapsed_time,
1096 &cf->ref, cf->prev_dis);
1097 cf->prev_cap = fdata;
1099 if (dfcode != NULL) {
1100 epan_dissect_prime_dfilter(edt, dfcode);
1103 /* Dissect the frame. */
1104 epan_dissect_run_with_taps(edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, buf), fdata, cinfo);
1106 /* If we don't have a display filter, set "passed_dfilter" to 1. */
1107 if (dfcode != NULL) {
1108 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
1110 if (fdata->flags.passed_dfilter) {
1111 /* This frame passed the display filter but it may depend on other
1112 * (potentially not displayed) frames. Find those frames and mark them
1115 g_slist_foreach(edt->pi.dependent_frames, find_and_mark_frame_depended_upon, cf->frames);
1118 fdata->flags.passed_dfilter = 1;
1120 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1121 cf->displayed_count++;
1123 if (add_to_packet_list) {
1124 /* We fill the needed columns from new_packet_list */
1125 row = packet_list_append(cinfo, fdata);
1128 if (fdata->flags.passed_dfilter || fdata->flags.ref_time)
1130 frame_data_set_after_dissect(fdata, &cf->cum_bytes);
1131 cf->prev_dis = fdata;
1133 /* If we haven't yet seen the first frame, this is it.
1135 XXX - we must do this before we add the row to the display,
1136 as, if the display's GtkCList's selection mode is
1137 GTK_SELECTION_BROWSE, when the first entry is added to it,
1138 "cf_select_packet()" will be called, and it will fetch the row
1139 data for the 0th row, and will get a null pointer rather than
1140 "fdata", as "gtk_clist_append()" won't yet have returned and
1141 thus "gtk_clist_set_row_data()" won't yet have been called.
1143 We thus need to leave behind bread crumbs so that
1144 "cf_select_packet()" can find this frame. See the comment
1145 in "cf_select_packet()". */
1146 if (cf->first_displayed == 0)
1147 cf->first_displayed = fdata->num;
1149 /* This is the last frame we've seen so far. */
1150 cf->last_displayed = fdata->num;
1153 epan_dissect_reset(edt);
1157 /* read in a new packet */
1158 /* returns the row of the new packet in the packet list or -1 if not displayed */
1160 read_packet(capture_file *cf, dfilter_t *dfcode, epan_dissect_t *edt,
1161 column_info *cinfo, gint64 offset)
1163 struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1164 const guint8 *buf = wtap_buf_ptr(cf->wth);
1171 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
1172 it's not already there.
1173 XXX - yes, this is O(N), so if every packet had a different
1174 link-layer encapsulation type, it'd be O(N^2) to read the file, but
1175 there are probably going to be a small number of encapsulation types
1177 cf_add_encapsulation_type(cf, phdr->pkt_encap);
1179 /* The frame number of this packet is one more than the count of
1180 frames in the file so far. */
1181 framenum = cf->count + 1;
1183 frame_data_init(&fdlocal, framenum, phdr, offset, cf->cum_bytes);
1187 epan_dissect_t rf_edt;
1189 epan_dissect_init(&rf_edt, cf->epan, TRUE, FALSE);
1190 epan_dissect_prime_dfilter(&rf_edt, cf->rfcode);
1191 epan_dissect_run(&rf_edt, cf->cd_t, phdr, frame_tvbuff_new(&fdlocal, buf), &fdlocal, NULL);
1192 passed = dfilter_apply_edt(cf->rfcode, &rf_edt);
1193 epan_dissect_cleanup(&rf_edt);
1197 /* This does a shallow copy of fdlocal, which is good enough. */
1198 fdata = frame_data_sequence_add(cf->frames, &fdlocal);
1201 if (phdr->opt_comment != NULL)
1202 cf->packet_comment_count++;
1203 cf->f_datalen = offset + fdlocal.cap_len;
1205 if (!cf->redissecting) {
1206 row = add_packet_to_packet_list(fdata, cf, edt, dfcode,
1207 cinfo, phdr, buf, TRUE);
1215 typedef struct _callback_data_t {
1217 gint64 progbar_nextstep;
1218 gint64 progbar_quantum;
1219 GTimeVal start_time;
1226 merge_callback(merge_event event, int num _U_,
1227 const merge_in_file_t in_files[], const guint in_file_count,
1231 callback_data_t *cb_data = (callback_data_t*) data;
1233 g_assert(cb_data != NULL);
1237 case MERGE_EVENT_INPUT_FILES_OPENED:
1241 case MERGE_EVENT_FRAME_TYPE_SELECTED:
1245 case MERGE_EVENT_READY_TO_MERGE:
1246 /* Get the sum of the sizes of all the files. */
1247 for (i = 0; i < in_file_count; i++)
1248 cb_data->f_len += in_files[i].size;
1250 /* When we reach the value that triggers a progress bar update,
1251 bump that value by this amount. */
1252 cb_data->progbar_quantum = cb_data->f_len / N_PROGBAR_UPDATES;
1254 g_get_current_time(&cb_data->start_time);
1257 case MERGE_EVENT_PACKET_WAS_READ:
1259 gint64 data_offset = 0;
1261 /* Get the sum of the data offsets in all of the files. */
1263 for (i = 0; i < in_file_count; i++)
1264 data_offset += in_files[i].data_offset;
1266 /* Create the progress bar if necessary.
1267 We check on every iteration of the loop, so that it takes no
1268 longer than the standard time to create it (otherwise, for a
1269 large file, we might take considerably longer than that standard
1270 time in order to get to the next progress bar step). */
1271 if (cb_data->progbar == NULL) {
1272 cb_data->progbar = delayed_create_progress_dlg(NULL, "Merging", "files",
1273 FALSE, &cb_data->stop_flag, &cb_data->start_time, 0.0f);
1276 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1277 when we update it, we have to run the GTK+ main loop to get it
1278 to repaint what's pending, and doing so may involve an "ioctl()"
1279 to see if there's any pending input from an X server, and doing
1280 that for every packet can be costly, especially on a big file. */
1281 if (data_offset >= cb_data->progbar_nextstep) {
1283 gint64 file_pos = 0;
1284 /* Get the sum of the seek positions in all of the files. */
1285 for (i = 0; i < in_file_count; i++)
1286 file_pos += wtap_read_so_far(in_files[i].wth);
1288 progbar_val = (gfloat) file_pos / (gfloat) cb_data->f_len;
1289 if (progbar_val > 1.0f) {
1290 /* Some file probably grew while we were reading it.
1291 That "shouldn't happen", so we'll just clip the progress
1296 if (cb_data->progbar != NULL) {
1297 gchar status_str[100];
1298 g_snprintf(status_str, sizeof(status_str),
1299 "%" G_GINT64_MODIFIER "dKB of %" G_GINT64_MODIFIER "dKB",
1300 file_pos / 1024, cb_data->f_len / 1024);
1301 update_progress_dlg(cb_data->progbar, progbar_val, status_str);
1303 cb_data->progbar_nextstep += cb_data->progbar_quantum;
1308 case MERGE_EVENT_DONE:
1309 /* We're done merging the files; destroy the progress bar if it was created. */
1310 if (cb_data->progbar != NULL)
1311 destroy_progress_dlg(cb_data->progbar);
1315 return cb_data->stop_flag;
1321 cf_merge_files(char **out_filenamep, int in_file_count,
1322 char *const *in_filenames, int file_type, gboolean do_append)
1328 gchar *err_info = NULL;
1330 merge_result status;
1331 merge_progress_callback_t cb;
1334 if (*out_filenamep != NULL) {
1335 out_filename = *out_filenamep;
1336 out_fd = ws_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1340 out_fd = create_tempfile(&tmpname, "wireshark");
1343 out_filename = g_strdup(tmpname);
1344 *out_filenamep = out_filename;
1347 cf_open_failure_alert_box(out_filename, err, NULL, TRUE, file_type);
1351 /* prepare our callback routine */
1352 cb.callback_func = merge_callback;
1353 cb.data = g_malloc0(sizeof(callback_data_t));
1355 /* merge the files */
1356 status = merge_files(out_fd, out_filename, file_type,
1357 (const char *const *) in_filenames, in_file_count,
1358 do_append, IDB_MERGE_MODE_ALL_SAME, 0 /* snaplen */,
1359 "Wireshark", &cb, &err, &err_info, &err_fileno);
1367 case MERGE_USER_ABORTED:
1368 /* this isn't really an error, though we will return CF_ERROR later */
1371 case MERGE_ERR_CANT_OPEN_INFILE:
1372 cf_open_failure_alert_box(in_filenames[err_fileno], err, err_info,
1377 case MERGE_ERR_CANT_OPEN_OUTFILE:
1378 cf_open_failure_alert_box(out_filename, err, err_info, TRUE,
1383 case MERGE_ERR_CANT_READ_INFILE: /* fall through */
1384 case MERGE_ERR_BAD_PHDR_INTERFACE_ID:
1385 case MERGE_ERR_CANT_WRITE_OUTFILE:
1386 case MERGE_ERR_CANT_CLOSE_OUTFILE:
1388 simple_error_message_box("%s", err_info ? err_info : "unknown error");
1393 /* for general case, no need to close out_fd: file handle associated to this file
1394 descriptor was already closed by the call to wtap_dump_close() in merge_files() */
1396 if (status != MERGE_OK) {
1397 /* Callers aren't expected to treat an error or an explicit abort
1398 differently - we put up error dialogs ourselves, so they don't
1406 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1408 const char *filter_new = dftext ? dftext : "";
1409 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1412 GTimeVal start_time;
1414 /* if new filter equals old one, do nothing unless told to do so */
1415 if (!force && strcmp(filter_new, filter_old) == 0) {
1421 if (dftext == NULL) {
1422 /* The new filter is an empty filter (i.e., display all packets).
1423 * so leave dfcode==NULL
1427 * We have a filter; make a copy of it (as we'll be saving it),
1428 * and try to compile it.
1430 dftext = g_strdup(dftext);
1431 if (!dfilter_compile(dftext, &dfcode, &err_msg)) {
1432 /* The attempt failed; report an error. */
1433 simple_message_box(ESD_TYPE_ERROR, NULL,
1434 "See the help for a description of the display filter syntax.",
1435 "\"%s\" isn't a valid display filter: %s",
1443 if (dfcode == NULL) {
1444 /* Yes - free the filter text, and set it to null. */
1450 /* We have a valid filter. Replace the current filter. */
1451 g_free(cf->dfilter);
1452 cf->dfilter = dftext;
1453 g_get_current_time(&start_time);
1456 /* Now rescan the packet list, applying the new filter, but not
1457 throwing away information constructed on a previous pass. */
1458 if (cf->state != FILE_CLOSED) {
1459 if (dftext == NULL) {
1460 rescan_packets(cf, "Resetting", "Filter", FALSE);
1462 rescan_packets(cf, "Filtering", dftext, FALSE);
1466 /* Cleanup and release all dfilter resources */
1467 dfilter_free(dfcode);
1473 cf_reftime_packets(capture_file *cf)
1475 ref_time_packets(cf);
1479 cf_redissect_packets(capture_file *cf)
1481 if (cf->state != FILE_CLOSED) {
1482 rescan_packets(cf, "Reprocessing", "all packets", TRUE);
1487 cf_read_record_r(capture_file *cf, const frame_data *fdata,
1488 struct wtap_pkthdr *phdr, Buffer *buf)
1492 gchar *display_basename;
1494 #ifdef WANT_PACKET_EDITOR
1495 /* if fdata->file_off == -1 it means packet was edited, and we must find data inside edited_frames tree */
1496 if (G_UNLIKELY(fdata->file_off == -1)) {
1497 const modified_frame_data *frame = (const modified_frame_data *) g_tree_lookup(cf->edited_frames, GINT_TO_POINTER(fdata->num));
1500 simple_error_message_box("fdata->file_off == -1, but can't find modified frame.");
1504 *phdr = frame->phdr;
1505 ws_buffer_assure_space(buf, frame->phdr.caplen);
1506 memcpy(ws_buffer_start_ptr(buf), frame->pd, frame->phdr.caplen);
1511 if (!wtap_seek_read(cf->wth, fdata->file_off, phdr, buf, &err, &err_info)) {
1512 display_basename = g_filename_display_basename(cf->filename);
1515 case WTAP_ERR_BAD_FILE:
1516 simple_error_message_box("An error occurred while reading from the file \"%s\": %s.\n(%s)",
1517 display_basename, wtap_strerror(err),
1518 err_info != NULL ? err_info : "no information supplied");
1523 simple_error_message_box(
1524 "An error occurred while reading from the file \"%s\": %s.",
1525 display_basename, wtap_strerror(err));
1528 g_free(display_basename);
1535 cf_read_record(capture_file *cf, frame_data *fdata)
1537 return cf_read_record_r(cf, fdata, &cf->phdr, &cf->buf);
1540 /* Rescan the list of packets, reconstructing the CList.
1542 "action" describes why we're doing this; it's used in the progress
1545 "action_item" describes what we're doing; it's used in the progress
1548 "redissect" is TRUE if we need to make the dissectors reconstruct
1549 any state information they have (because a preference that affects
1550 some dissector has changed, meaning some dissector might construct
1551 its state differently from the way it was constructed the last time). */
1553 rescan_packets(capture_file *cf, const char *action, const char *action_item, gboolean redissect)
1555 /* Rescan packets new packet list */
1558 progdlg_t *progbar = NULL;
1560 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1561 int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num;
1562 gboolean selected_frame_seen;
1564 GTimeVal start_time;
1565 gchar status_str[100];
1566 int progbar_nextstep;
1567 int progbar_quantum;
1571 gboolean create_proto_tree;
1573 gboolean add_to_packet_list = FALSE;
1575 guint32 frames_count;
1577 /* Compile the current display filter.
1578 * We assume this will not fail since cf->dfilter is only set in
1579 * cf_filter IFF the filter was valid.
1581 compiled = dfilter_compile(cf->dfilter, &dfcode, NULL);
1582 g_assert(!cf->dfilter || (compiled && dfcode));
1584 /* Get the union of the flags for all tap listeners. */
1585 tap_flags = union_of_tap_listener_flags();
1586 cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
1588 (dfcode != NULL || have_filtering_tap_listeners() || (tap_flags & TL_REQUIRES_PROTO_TREE));
1590 reset_tap_listeners();
1591 /* Which frame, if any, is the currently selected frame?
1592 XXX - should the selected frame or the focus frame be the "current"
1593 frame, that frame being the one from which "Find Frame" searches
1595 selected_frame = cf->current_frame;
1597 /* Mark frame num as not found */
1598 selected_frame_num = -1;
1600 /* Freeze the packet list while we redo it, so we don't get any
1601 screen updates while it happens. */
1602 packet_list_freeze();
1605 /* We need to re-initialize all the state information that protocols
1606 keep, because some preference that controls a dissector has changed,
1607 which might cause the state information to be constructed differently
1608 by that dissector. */
1610 /* We might receive new packets while redissecting, and we don't
1611 want to dissect those before their time. */
1612 cf->redissecting = TRUE;
1614 /* 'reset' dissection session */
1615 epan_free(cf->epan);
1616 if (cf->edt && cf->edt->pi.fd) {
1617 /* All pointers in "per frame proto data" for the currently selected
1618 packet are allocated in wmem_file_scope() and deallocated in epan_free().
1619 Free them here to avoid unintended usage in packet_list_clear(). */
1620 frame_data_destroy(cf->edt->pi.fd);
1622 cf->epan = ws_epan_new(cf);
1623 cf->cinfo.epan = cf->epan;
1625 /* We need to redissect the packets so we have to discard our old
1626 * packet list store. */
1627 packet_list_clear();
1628 add_to_packet_list = TRUE;
1631 /* We don't yet know which will be the first and last frames displayed. */
1632 cf->first_displayed = 0;
1633 cf->last_displayed = 0;
1635 /* We currently don't display any packets */
1636 cf->displayed_count = 0;
1638 /* Iterate through the list of frames. Call a routine for each frame
1639 to check whether it should be displayed and, if so, add it to
1640 the display list. */
1642 cf->prev_dis = NULL;
1643 cf->prev_cap = NULL;
1646 cf_callback_invoke(cf_cb_file_rescan_started, cf);
1648 /* Update the progress bar when it gets to this value. */
1649 progbar_nextstep = 0;
1650 /* When we reach the value that triggers a progress bar update,
1651 bump that value by this amount. */
1652 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1653 /* Count of packets at which we've looked. */
1655 /* Progress so far. */
1658 cf->stop_flag = FALSE;
1659 g_get_current_time(&start_time);
1661 /* no previous row yet */
1662 prev_frame_num = -1;
1665 preceding_frame_num = -1;
1666 preceding_frame = NULL;
1667 following_frame_num = -1;
1668 following_frame = NULL;
1670 selected_frame_seen = FALSE;
1672 frames_count = cf->count;
1674 epan_dissect_init(&edt, cf->epan, create_proto_tree, FALSE);
1676 for (framenum = 1; framenum <= frames_count; framenum++) {
1677 fdata = frame_data_sequence_find(cf->frames, framenum);
1679 /* Create the progress bar if necessary.
1680 We check on every iteration of the loop, so that it takes no
1681 longer than the standard time to create it (otherwise, for a
1682 large file, we might take considerably longer than that standard
1683 time in order to get to the next progress bar step). */
1684 if (progbar == NULL)
1685 progbar = delayed_create_progress_dlg(cf->window, action, action_item, TRUE,
1690 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1691 when we update it, we have to run the GTK+ main loop to get it
1692 to repaint what's pending, and doing so may involve an "ioctl()"
1693 to see if there's any pending input from an X server, and doing
1694 that for every packet can be costly, especially on a big file. */
1695 if (count >= progbar_nextstep) {
1696 /* let's not divide by zero. I should never be started
1697 * with count == 0, so let's assert that
1699 g_assert(cf->count > 0);
1700 progbar_val = (gfloat) count / frames_count;
1702 if (progbar != NULL) {
1703 g_snprintf(status_str, sizeof(status_str),
1704 "%4u of %u frames", count, frames_count);
1705 update_progress_dlg(progbar, progbar_val, status_str);
1708 progbar_nextstep += progbar_quantum;
1711 if (cf->stop_flag) {
1712 /* Well, the user decided to abort the filtering. Just stop.
1714 XXX - go back to the previous filter? Users probably just
1715 want not to wait for a filtering operation to finish;
1716 unless we cancel by having no filter, reverting to the
1717 previous filter will probably be even more expensive than
1718 continuing the filtering, as it involves going back to the
1719 beginning and filtering, and even with no filter we currently
1720 have to re-generate the entire clist, which is also expensive.
1722 I'm not sure what Network Monitor does, but it doesn't appear
1723 to give you an unfiltered display if you cancel. */
1730 /* Since all state for the frame was destroyed, mark the frame
1731 * as not visited, free the GSList referring to the state
1732 * data (the per-frame data itself was freed by
1733 * "init_dissection()"), and null out the GSList pointer. */
1734 frame_data_reset(fdata);
1735 frames_count = cf->count;
1738 /* Frame dependencies from the previous dissection/filtering are no longer valid. */
1739 fdata->flags.dependent_of_displayed = 0;
1741 if (!cf_read_record(cf, fdata))
1742 break; /* error reading the frame */
1744 /* If the previous frame is displayed, and we haven't yet seen the
1745 selected frame, remember that frame - it's the closest one we've
1746 yet seen before the selected frame. */
1747 if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) {
1748 preceding_frame_num = prev_frame_num;
1749 preceding_frame = prev_frame;
1752 add_packet_to_packet_list(fdata, cf, &edt, dfcode,
1754 ws_buffer_start_ptr(&cf->buf),
1755 add_to_packet_list);
1757 /* If this frame is displayed, and this is the first frame we've
1758 seen displayed after the selected frame, remember this frame -
1759 it's the closest one we've yet seen at or after the selected
1761 if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) {
1762 following_frame_num = fdata->num;
1763 following_frame = fdata;
1765 if (fdata == selected_frame) {
1766 selected_frame_seen = TRUE;
1767 if (fdata->flags.passed_dfilter)
1768 selected_frame_num = fdata->num;
1771 /* Remember this frame - it'll be the previous frame
1772 on the next pass through the loop. */
1773 prev_frame_num = fdata->num;
1777 epan_dissect_cleanup(&edt);
1779 /* We are done redissecting the packet list. */
1780 cf->redissecting = FALSE;
1783 frames_count = cf->count;
1784 /* Clear out what remains of the visited flags and per-frame data
1787 XXX - that may cause various forms of bogosity when dissecting
1788 these frames, as they won't have been seen by this sequential
1789 pass, but the only alternative I see is to keep scanning them
1790 even though the user requested that the scan stop, and that
1791 would leave the user stuck with an Wireshark grinding on
1792 until it finishes. Should we just stick them with that? */
1793 for (; framenum <= frames_count; framenum++) {
1794 fdata = frame_data_sequence_find(cf->frames, framenum);
1795 frame_data_reset(fdata);
1799 /* We're done filtering the packets; destroy the progress bar if it
1801 if (progbar != NULL)
1802 destroy_progress_dlg(progbar);
1804 /* Unfreeze the packet list. */
1805 if (!add_to_packet_list)
1806 packet_list_recreate_visible_rows();
1808 /* Compute the time it took to filter the file */
1809 compute_elapsed(cf, &start_time);
1813 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
1815 if (selected_frame_num == -1) {
1816 /* The selected frame didn't pass the filter. */
1817 if (selected_frame == NULL) {
1818 /* That's because there *was* no selected frame. Make the first
1819 displayed frame the current frame. */
1820 selected_frame_num = 0;
1822 /* Find the nearest displayed frame to the selected frame (whether
1823 it's before or after that frame) and make that the current frame.
1824 If the next and previous displayed frames are equidistant from the
1825 selected frame, choose the next one. */
1826 g_assert(following_frame == NULL ||
1827 following_frame->num >= selected_frame->num);
1828 g_assert(preceding_frame == NULL ||
1829 preceding_frame->num <= selected_frame->num);
1830 if (following_frame == NULL) {
1831 /* No frame after the selected frame passed the filter, so we
1832 have to select the last displayed frame before the selected
1834 selected_frame_num = preceding_frame_num;
1835 selected_frame = preceding_frame;
1836 } else if (preceding_frame == NULL) {
1837 /* No frame before the selected frame passed the filter, so we
1838 have to select the first displayed frame after the selected
1840 selected_frame_num = following_frame_num;
1841 selected_frame = following_frame;
1843 /* Frames before and after the selected frame passed the filter, so
1844 we'll select the previous frame */
1845 selected_frame_num = preceding_frame_num;
1846 selected_frame = preceding_frame;
1851 if (selected_frame_num == -1) {
1852 /* There are no frames displayed at all. */
1853 cf_unselect_packet(cf);
1855 /* Either the frame that was selected passed the filter, or we've
1856 found the nearest displayed frame to that frame. Select it, make
1857 it the focus row, and make it visible. */
1858 /* Set to invalid to force update of packet list and packet details */
1859 cf->current_row = -1;
1860 if (selected_frame_num == 0) {
1861 packet_list_select_first_row();
1863 if (!packet_list_select_row_from_data(selected_frame)) {
1864 /* We didn't find a row corresponding to this frame.
1865 This means that the frame isn't being displayed currently,
1866 so we can't select it. */
1867 simple_message_box(ESD_TYPE_INFO, NULL,
1868 "The capture file is probably not fully dissected.",
1869 "End of capture exceeded.");
1874 /* Cleanup and release all dfilter resources */
1875 dfilter_free(dfcode);
1880 * Scan trough all frame data and recalculate the ref time
1881 * without rereading the file.
1882 * XXX - do we need a progres bar or is this fast enough?
1885 ref_time_packets(capture_file *cf)
1892 cf->prev_dis = NULL;
1895 for (framenum = 1; framenum <= cf->count; framenum++) {
1896 fdata = frame_data_sequence_find(cf->frames, framenum);
1898 /* just add some value here until we know if it is being displayed or not */
1899 fdata->cum_bytes = cf->cum_bytes + fdata->pkt_len;
1905 /* If we don't have the time stamp of the first packet in the
1906 capture, it's because this is the first packet. Save the time
1907 stamp of this packet as the time stamp of the first packet. */
1908 if (cf->ref == NULL)
1910 /* if this frames is marked as a reference time frame, reset
1911 firstsec and firstusec to this frame */
1912 if (fdata->flags.ref_time)
1915 /* If we don't have the time stamp of the previous displayed packet,
1916 it's because this is the first displayed packet. Save the time
1917 stamp of this packet as the time stamp of the previous displayed
1919 if (cf->prev_dis == NULL) {
1920 cf->prev_dis = fdata;
1923 /* Get the time elapsed between the first packet and this packet. */
1924 fdata->frame_ref_num = (fdata != cf->ref) ? cf->ref->num : 0;
1925 nstime_delta(&rel_ts, &fdata->abs_ts, &cf->ref->abs_ts);
1927 /* If it's greater than the current elapsed time, set the elapsed time
1928 to it (we check for "greater than" so as not to be confused by
1929 time moving backwards). */
1930 if ((gint32)cf->elapsed_time.secs < rel_ts.secs
1931 || ((gint32)cf->elapsed_time.secs == rel_ts.secs && (gint32)cf->elapsed_time.nsecs < rel_ts.nsecs)) {
1932 cf->elapsed_time = rel_ts;
1935 /* If this frame is displayed, get the time elapsed between the
1936 previous displayed packet and this packet. */
1937 if ( fdata->flags.passed_dfilter ) {
1938 fdata->prev_dis_num = cf->prev_dis->num;
1939 cf->prev_dis = fdata;
1945 if ( (fdata->flags.passed_dfilter) || (fdata->flags.ref_time) ) {
1946 /* This frame either passed the display filter list or is marked as
1947 a time reference frame. All time reference frames are displayed
1948 even if they don't pass the display filter */
1949 if (fdata->flags.ref_time) {
1950 /* if this was a TIME REF frame we should reset the cum_bytes field */
1951 cf->cum_bytes = fdata->pkt_len;
1952 fdata->cum_bytes = cf->cum_bytes;
1954 /* increase cum_bytes with this packets length */
1955 cf->cum_bytes += fdata->pkt_len;
1968 process_specified_records(capture_file *cf, packet_range_t *range,
1969 const char *string1, const char *string2, gboolean terminate_is_stop,
1970 gboolean (*callback)(capture_file *, frame_data *,
1971 struct wtap_pkthdr *, const guint8 *, void *),
1972 void *callback_args)
1977 psp_return_t ret = PSP_FINISHED;
1979 progdlg_t *progbar = NULL;
1982 GTimeVal progbar_start_time;
1983 gchar progbar_status_str[100];
1984 int progbar_nextstep;
1985 int progbar_quantum;
1986 range_process_e process_this;
1987 struct wtap_pkthdr phdr;
1989 wtap_phdr_init(&phdr);
1990 ws_buffer_init(&buf, 1500);
1992 /* Update the progress bar when it gets to this value. */
1993 progbar_nextstep = 0;
1994 /* When we reach the value that triggers a progress bar update,
1995 bump that value by this amount. */
1996 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1997 /* Count of packets at which we've looked. */
1999 /* Progress so far. */
2002 cf->stop_flag = FALSE;
2003 g_get_current_time(&progbar_start_time);
2006 packet_range_process_init(range);
2008 /* Iterate through all the packets, printing the packets that
2009 were selected by the current display filter. */
2010 for (framenum = 1; framenum <= cf->count; framenum++) {
2011 fdata = frame_data_sequence_find(cf->frames, framenum);
2013 /* Create the progress bar if necessary.
2014 We check on every iteration of the loop, so that it takes no
2015 longer than the standard time to create it (otherwise, for a
2016 large file, we might take considerably longer than that standard
2017 time in order to get to the next progress bar step). */
2018 if (progbar == NULL)
2019 progbar = delayed_create_progress_dlg(cf->window, string1, string2,
2022 &progbar_start_time,
2025 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2026 when we update it, we have to run the GTK+ main loop to get it
2027 to repaint what's pending, and doing so may involve an "ioctl()"
2028 to see if there's any pending input from an X server, and doing
2029 that for every packet can be costly, especially on a big file. */
2030 if (progbar_count >= progbar_nextstep) {
2031 /* let's not divide by zero. I should never be started
2032 * with count == 0, so let's assert that
2034 g_assert(cf->count > 0);
2035 progbar_val = (gfloat) progbar_count / cf->count;
2037 if (progbar != NULL) {
2038 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
2039 "%4u of %u packets", progbar_count, cf->count);
2040 update_progress_dlg(progbar, progbar_val, progbar_status_str);
2043 progbar_nextstep += progbar_quantum;
2046 if (cf->stop_flag) {
2047 /* Well, the user decided to abort the operation. Just stop,
2048 and arrange to return PSP_STOPPED to our caller, so they know
2049 it was stopped explicitly. */
2056 if (range != NULL) {
2057 /* do we have to process this packet? */
2058 process_this = packet_range_process_packet(range, fdata);
2059 if (process_this == range_process_next) {
2060 /* this packet uninteresting, continue with next one */
2062 } else if (process_this == range_processing_finished) {
2063 /* all interesting packets processed, stop the loop */
2068 /* Get the packet */
2069 if (!cf_read_record_r(cf, fdata, &phdr, &buf)) {
2070 /* Attempt to get the packet failed. */
2074 /* Process the packet */
2075 if (!callback(cf, fdata, &phdr, ws_buffer_start_ptr(&buf), callback_args)) {
2076 /* Callback failed. We assume it reported the error appropriately. */
2082 /* We're done printing the packets; destroy the progress bar if
2084 if (progbar != NULL)
2085 destroy_progress_dlg(progbar);
2087 wtap_phdr_cleanup(&phdr);
2088 ws_buffer_free(&buf);
2096 } retap_callback_args_t;
2099 retap_packet(capture_file *cf, frame_data *fdata,
2100 struct wtap_pkthdr *phdr, const guint8 *pd,
2103 retap_callback_args_t *args = (retap_callback_args_t *)argsp;
2105 epan_dissect_run_with_taps(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, args->cinfo);
2106 epan_dissect_reset(&args->edt);
2112 cf_retap_packets(capture_file *cf)
2114 packet_range_t range;
2115 retap_callback_args_t callback_args;
2116 gboolean construct_protocol_tree;
2117 gboolean filtering_tap_listeners;
2121 /* Presumably the user closed the capture file. */
2123 return CF_READ_ABORTED;
2126 cf_callback_invoke(cf_cb_file_retap_started, cf);
2128 /* Do we have any tap listeners with filters? */
2129 filtering_tap_listeners = have_filtering_tap_listeners();
2131 tap_flags = union_of_tap_listener_flags();
2133 /* If any tap listeners have filters, or require the protocol tree,
2134 construct the protocol tree. */
2135 construct_protocol_tree = filtering_tap_listeners ||
2136 (tap_flags & TL_REQUIRES_PROTO_TREE);
2138 /* If any tap listeners require the columns, construct them. */
2139 callback_args.cinfo = (tap_flags & TL_REQUIRES_COLUMNS) ? &cf->cinfo : NULL;
2141 /* Reset the tap listeners. */
2142 reset_tap_listeners();
2144 epan_dissect_init(&callback_args.edt, cf->epan, construct_protocol_tree, FALSE);
2146 /* Iterate through the list of packets, dissecting all packets and
2147 re-running the taps. */
2148 packet_range_init(&range, cf);
2149 packet_range_process_init(&range);
2151 ret = process_specified_records(cf, &range, "Recalculating statistics on",
2152 "all packets", TRUE, retap_packet,
2155 epan_dissect_cleanup(&callback_args.edt);
2157 cf_callback_invoke(cf_cb_file_retap_finished, cf);
2161 /* Completed successfully. */
2165 /* Well, the user decided to abort the refiltering.
2166 Return CF_READ_ABORTED so our caller knows they did that. */
2167 return CF_READ_ABORTED;
2170 /* Error while retapping. */
2171 return CF_READ_ERROR;
2174 g_assert_not_reached();
2179 print_args_t *print_args;
2180 gboolean print_header_line;
2181 char *header_line_buf;
2182 int header_line_buf_len;
2183 gboolean print_formfeed;
2184 gboolean print_separator;
2188 int num_visible_cols;
2191 } print_callback_args_t;
2194 print_packet(capture_file *cf, frame_data *fdata,
2195 struct wtap_pkthdr *phdr, const guint8 *pd,
2198 print_callback_args_t *args = (print_callback_args_t *)argsp;
2204 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
2205 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
2206 col_item_t* col_item;
2208 /* Fill in the column information if we're printing the summary
2210 if (args->print_args->print_summary) {
2211 col_custom_prime_edt(&args->edt, &cf->cinfo);
2212 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2213 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2215 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2217 if (args->print_formfeed) {
2218 if (!new_page(args->print_args->stream))
2221 if (args->print_separator) {
2222 if (!print_line(args->print_args->stream, 0, ""))
2228 * We generate bookmarks, if the output format supports them.
2229 * The name is "__frameN__".
2231 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
2233 if (args->print_args->print_summary) {
2234 if (!args->print_args->print_col_headings)
2235 args->print_header_line = FALSE;
2236 if (args->print_header_line) {
2237 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
2239 args->print_header_line = FALSE; /* we might not need to print any more */
2241 cp = &args->line_buf[0];
2243 for (i = 0; i < args->num_visible_cols; i++) {
2244 col_item = &cf->cinfo.columns[args->visible_cols[i]];
2245 /* Find the length of the string for this column. */
2246 column_len = (int) strlen(col_item->col_data);
2247 if (args->col_widths[i] > column_len)
2248 column_len = args->col_widths[i];
2250 /* Make sure there's room in the line buffer for the column; if not,
2251 double its length. */
2252 line_len += column_len + 1; /* "+1" for space */
2253 if (line_len > args->line_buf_len) {
2254 cp_off = (int) (cp - args->line_buf);
2255 args->line_buf_len = 2 * line_len;
2256 args->line_buf = (char *)g_realloc(args->line_buf, args->line_buf_len + 1);
2257 cp = args->line_buf + cp_off;
2260 /* Right-justify the packet number column. */
2261 if (col_item->col_fmt == COL_NUMBER)
2262 g_snprintf(cp, column_len+1, "%*s", args->col_widths[i], col_item->col_data);
2264 g_snprintf(cp, column_len+1, "%-*s", args->col_widths[i], col_item->col_data);
2266 if (i != args->num_visible_cols - 1)
2272 * Generate a bookmark, using the summary line as the title.
2274 if (!print_bookmark(args->print_args->stream, bookmark_name,
2278 if (!print_line(args->print_args->stream, 0, args->line_buf))
2282 * Generate a bookmark, using "Frame N" as the title, as we're not
2283 * printing the summary line.
2285 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
2286 if (!print_bookmark(args->print_args->stream, bookmark_name,
2289 } /* if (print_summary) */
2291 if (args->print_args->print_dissections != print_dissections_none) {
2292 if (args->print_args->print_summary) {
2293 /* Separate the summary line from the tree with a blank line. */
2294 if (!print_line(args->print_args->stream, 0, ""))
2298 /* Print the information in that tree. */
2299 if (!proto_tree_print(args->print_args, &args->edt, NULL, args->print_args->stream))
2302 /* Print a blank line if we print anything after this (aka more than one packet). */
2303 args->print_separator = TRUE;
2305 /* Print a header line if we print any more packet summaries */
2306 if (args->print_args->print_col_headings)
2307 args->print_header_line = TRUE;
2310 if (args->print_args->print_hex) {
2311 if (args->print_args->print_summary || (args->print_args->print_dissections != print_dissections_none)) {
2312 if (!print_line(args->print_args->stream, 0, ""))
2315 /* Print the full packet data as hex. */
2316 if (!print_hex_data(args->print_args->stream, &args->edt))
2319 /* Print a blank line if we print anything after this (aka more than one packet). */
2320 args->print_separator = TRUE;
2322 /* Print a header line if we print any more packet summaries */
2323 if (args->print_args->print_col_headings)
2324 args->print_header_line = TRUE;
2325 } /* if (args->print_args->print_dissections != print_dissections_none) */
2327 epan_dissect_reset(&args->edt);
2329 /* do we want to have a formfeed between each packet from now on? */
2330 if (args->print_args->print_formfeed) {
2331 args->print_formfeed = TRUE;
2337 epan_dissect_reset(&args->edt);
2342 cf_print_packets(capture_file *cf, print_args_t *print_args)
2344 print_callback_args_t callback_args;
2347 int i, cp_off, column_len, line_len;
2348 int num_visible_col = 0, last_visible_col = 0, visible_col_count;
2352 gboolean proto_tree_needed;
2354 callback_args.print_args = print_args;
2355 callback_args.print_header_line = print_args->print_col_headings;
2356 callback_args.header_line_buf = NULL;
2357 callback_args.header_line_buf_len = 256;
2358 callback_args.print_formfeed = FALSE;
2359 callback_args.print_separator = FALSE;
2360 callback_args.line_buf = NULL;
2361 callback_args.line_buf_len = 256;
2362 callback_args.col_widths = NULL;
2363 callback_args.num_visible_cols = 0;
2364 callback_args.visible_cols = NULL;
2366 if (!print_preamble(print_args->stream, cf->filename, get_ws_vcs_version_info())) {
2367 destroy_print_stream(print_args->stream);
2368 return CF_PRINT_WRITE_ERROR;
2371 if (print_args->print_summary) {
2372 /* We're printing packet summaries. Allocate the header line buffer
2373 and get the column widths. */
2374 callback_args.header_line_buf = (char *)g_malloc(callback_args.header_line_buf_len + 1);
2376 /* Find the number of visible columns and the last visible column */
2377 for (i = 0; i < prefs.num_cols; i++) {
2379 clp = g_list_nth(prefs.col_list, i);
2380 if (clp == NULL) /* Sanity check, Invalid column requested */
2383 cfmt = (fmt_data *) clp->data;
2384 if (cfmt->visible) {
2386 last_visible_col = i;
2390 /* Find the widths for each of the columns - maximum of the
2391 width of the title and the width of the data - and construct
2392 a buffer with a line containing the column titles. */
2393 callback_args.num_visible_cols = num_visible_col;
2394 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2395 callback_args.visible_cols = (gint *) g_malloc(sizeof(gint) * num_visible_col);
2396 cp = &callback_args.header_line_buf[0];
2398 visible_col_count = 0;
2399 for (i = 0; i < cf->cinfo.num_cols; i++) {
2401 clp = g_list_nth(prefs.col_list, i);
2402 if (clp == NULL) /* Sanity check, Invalid column requested */
2405 cfmt = (fmt_data *) clp->data;
2406 if (cfmt->visible == FALSE)
2409 /* Save the order of visible columns */
2410 callback_args.visible_cols[visible_col_count] = i;
2412 /* Don't pad the last column. */
2413 if (i == last_visible_col)
2414 callback_args.col_widths[visible_col_count] = 0;
2416 callback_args.col_widths[visible_col_count] = (gint) strlen(cf->cinfo.columns[i].col_title);
2417 data_width = get_column_char_width(get_column_format(i));
2418 if (data_width > callback_args.col_widths[visible_col_count])
2419 callback_args.col_widths[visible_col_count] = data_width;
2422 /* Find the length of the string for this column. */
2423 column_len = (int) strlen(cf->cinfo.columns[i].col_title);
2424 if (callback_args.col_widths[i] > column_len)
2425 column_len = callback_args.col_widths[visible_col_count];
2427 /* Make sure there's room in the line buffer for the column; if not,
2428 double its length. */
2429 line_len += column_len + 1; /* "+1" for space */
2430 if (line_len > callback_args.header_line_buf_len) {
2431 cp_off = (int) (cp - callback_args.header_line_buf);
2432 callback_args.header_line_buf_len = 2 * line_len;
2433 callback_args.header_line_buf = (char *)g_realloc(callback_args.header_line_buf,
2434 callback_args.header_line_buf_len + 1);
2435 cp = callback_args.header_line_buf + cp_off;
2438 /* Right-justify the packet number column. */
2439 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2440 g_snprintf(cp, column_len+1, "%*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2442 g_snprintf(cp, column_len+1, "%-*s", callback_args.col_widths[visible_col_count], cf->cinfo.columns[i].col_title);
2444 if (i != cf->cinfo.num_cols - 1)
2447 visible_col_count++;
2451 /* Now start out the main line buffer with the same length as the
2452 header line buffer. */
2453 callback_args.line_buf_len = callback_args.header_line_buf_len;
2454 callback_args.line_buf = (char *)g_malloc(callback_args.line_buf_len + 1);
2455 } /* if (print_summary) */
2457 /* Create the protocol tree, and make it visible, if we're printing
2458 the dissection or the hex data.
2459 XXX - do we need it if we're just printing the hex data? */
2461 callback_args.print_args->print_dissections != print_dissections_none ||
2462 callback_args.print_args->print_hex ||
2463 have_custom_cols(&cf->cinfo);
2464 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2466 /* Iterate through the list of packets, printing the packets we were
2468 ret = process_specified_records(cf, &print_args->range, "Printing",
2469 "selected packets", TRUE, print_packet,
2471 epan_dissect_cleanup(&callback_args.edt);
2472 g_free(callback_args.header_line_buf);
2473 g_free(callback_args.line_buf);
2474 g_free(callback_args.col_widths);
2475 g_free(callback_args.visible_cols);
2480 /* Completed successfully. */
2484 /* Well, the user decided to abort the printing.
2486 XXX - note that what got generated before they did that
2487 will get printed if we're piping to a print program; we'd
2488 have to write to a file and then hand that to the print
2489 program to make it actually not print anything. */
2493 /* Error while printing.
2495 XXX - note that what got generated before they did that
2496 will get printed if we're piping to a print program; we'd
2497 have to write to a file and then hand that to the print
2498 program to make it actually not print anything. */
2499 destroy_print_stream(print_args->stream);
2500 return CF_PRINT_WRITE_ERROR;
2503 if (!print_finale(print_args->stream)) {
2504 destroy_print_stream(print_args->stream);
2505 return CF_PRINT_WRITE_ERROR;
2508 if (!destroy_print_stream(print_args->stream))
2509 return CF_PRINT_WRITE_ERROR;
2517 } write_packet_callback_args_t;
2520 write_pdml_packet(capture_file *cf, frame_data *fdata,
2521 struct wtap_pkthdr *phdr, const guint8 *pd,
2524 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2526 /* Create the protocol tree, but don't fill in the column information. */
2527 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2529 /* Write out the information in that tree. */
2530 write_pdml_proto_tree(&args->edt, args->fh);
2532 epan_dissect_reset(&args->edt);
2534 return !ferror(args->fh);
2538 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2540 write_packet_callback_args_t callback_args;
2544 fh = ws_fopen(print_args->file, "w");
2546 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2548 write_pdml_preamble(fh, cf->filename);
2551 return CF_PRINT_WRITE_ERROR;
2554 callback_args.fh = fh;
2555 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2557 /* Iterate through the list of packets, printing the packets we were
2559 ret = process_specified_records(cf, &print_args->range, "Writing PDML",
2560 "selected packets", TRUE,
2561 write_pdml_packet, &callback_args);
2563 epan_dissect_cleanup(&callback_args.edt);
2568 /* Completed successfully. */
2572 /* Well, the user decided to abort the printing. */
2576 /* Error while printing. */
2578 return CF_PRINT_WRITE_ERROR;
2581 write_pdml_finale(fh);
2584 return CF_PRINT_WRITE_ERROR;
2587 /* XXX - check for an error */
2594 write_psml_packet(capture_file *cf, frame_data *fdata,
2595 struct wtap_pkthdr *phdr, const guint8 *pd,
2598 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2600 /* Fill in the column information */
2601 col_custom_prime_edt(&args->edt, &cf->cinfo);
2602 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2603 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2605 /* Write out the column information. */
2606 write_psml_columns(&args->edt, args->fh);
2608 epan_dissect_reset(&args->edt);
2610 return !ferror(args->fh);
2614 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2616 write_packet_callback_args_t callback_args;
2620 gboolean proto_tree_needed;
2622 fh = ws_fopen(print_args->file, "w");
2624 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2626 write_psml_preamble(&cf->cinfo, fh);
2629 return CF_PRINT_WRITE_ERROR;
2632 callback_args.fh = fh;
2634 /* Fill in the column information, only create the protocol tree
2635 if having custom columns. */
2636 proto_tree_needed = have_custom_cols(&cf->cinfo);
2637 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2639 /* Iterate through the list of packets, printing the packets we were
2641 ret = process_specified_records(cf, &print_args->range, "Writing PSML",
2642 "selected packets", TRUE,
2643 write_psml_packet, &callback_args);
2645 epan_dissect_cleanup(&callback_args.edt);
2650 /* Completed successfully. */
2654 /* Well, the user decided to abort the printing. */
2658 /* Error while printing. */
2660 return CF_PRINT_WRITE_ERROR;
2663 write_psml_finale(fh);
2666 return CF_PRINT_WRITE_ERROR;
2669 /* XXX - check for an error */
2676 write_csv_packet(capture_file *cf, frame_data *fdata,
2677 struct wtap_pkthdr *phdr, const guint8 *pd,
2680 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2682 /* Fill in the column information */
2683 col_custom_prime_edt(&args->edt, &cf->cinfo);
2684 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, &cf->cinfo);
2685 epan_dissect_fill_in_columns(&args->edt, FALSE, TRUE);
2687 /* Write out the column information. */
2688 write_csv_columns(&args->edt, args->fh);
2690 epan_dissect_reset(&args->edt);
2692 return !ferror(args->fh);
2696 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2698 write_packet_callback_args_t callback_args;
2699 gboolean proto_tree_needed;
2703 fh = ws_fopen(print_args->file, "w");
2705 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2707 write_csv_column_titles(&cf->cinfo, fh);
2710 return CF_PRINT_WRITE_ERROR;
2713 callback_args.fh = fh;
2715 /* only create the protocol tree if having custom columns. */
2716 proto_tree_needed = have_custom_cols(&cf->cinfo);
2717 epan_dissect_init(&callback_args.edt, cf->epan, proto_tree_needed, proto_tree_needed);
2719 /* Iterate through the list of packets, printing the packets we were
2721 ret = process_specified_records(cf, &print_args->range, "Writing CSV",
2722 "selected packets", TRUE,
2723 write_csv_packet, &callback_args);
2725 epan_dissect_cleanup(&callback_args.edt);
2730 /* Completed successfully. */
2734 /* Well, the user decided to abort the printing. */
2738 /* Error while printing. */
2740 return CF_PRINT_WRITE_ERROR;
2743 /* XXX - check for an error */
2750 carrays_write_packet(capture_file *cf, frame_data *fdata,
2751 struct wtap_pkthdr *phdr,
2752 const guint8 *pd, void *argsp)
2754 write_packet_callback_args_t *args = (write_packet_callback_args_t *)argsp;
2756 epan_dissect_run(&args->edt, cf->cd_t, phdr, frame_tvbuff_new(fdata, pd), fdata, NULL);
2757 write_carrays_hex_data(fdata->num, args->fh, &args->edt);
2758 epan_dissect_reset(&args->edt);
2760 return !ferror(args->fh);
2764 cf_write_carrays_packets(capture_file *cf, print_args_t *print_args)
2766 write_packet_callback_args_t callback_args;
2770 fh = ws_fopen(print_args->file, "w");
2773 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2777 return CF_PRINT_WRITE_ERROR;
2780 callback_args.fh = fh;
2781 epan_dissect_init(&callback_args.edt, cf->epan, TRUE, TRUE);
2783 /* Iterate through the list of packets, printing the packets we were
2785 ret = process_specified_records(cf, &print_args->range,
2787 "selected packets", TRUE,
2788 carrays_write_packet, &callback_args);
2790 epan_dissect_cleanup(&callback_args.edt);
2794 /* Completed successfully. */
2797 /* Well, the user decided to abort the printing. */
2800 /* Error while printing. */
2802 return CF_PRINT_WRITE_ERROR;
2810 cf_find_packet_protocol_tree(capture_file *cf, const char *string,
2811 search_direction dir)
2815 mdata.string = string;
2816 mdata.string_len = strlen(string);
2817 return find_packet(cf, match_protocol_tree, &mdata, dir);
2821 cf_find_string_protocol_tree(capture_file *cf, proto_tree *tree, match_data *mdata)
2823 mdata->frame_matched = FALSE;
2824 mdata->string = convert_string_case(cf->sfilter, cf->case_type);
2825 mdata->string_len = strlen(mdata->string);
2827 /* Iterate through all the nodes looking for matching text */
2828 proto_tree_children_foreach(tree, match_subtree_text, mdata);
2829 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2833 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2835 match_data *mdata = (match_data *)criterion;
2838 /* Load the frame's data. */
2839 if (!cf_read_record(cf, fdata)) {
2840 /* Attempt to get the packet failed. */
2844 /* Construct the protocol tree, including the displayed text */
2845 epan_dissect_init(&edt, cf->epan, TRUE, TRUE);
2846 /* We don't need the column information */
2847 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
2849 /* Iterate through all the nodes, seeing if they have text that matches. */
2851 mdata->frame_matched = FALSE;
2852 proto_tree_children_foreach(edt.tree, match_subtree_text, mdata);
2853 epan_dissect_cleanup(&edt);
2854 return mdata->frame_matched ? MR_MATCHED : MR_NOTMATCHED;
2858 match_subtree_text(proto_node *node, gpointer data)
2860 match_data *mdata = (match_data *) data;
2861 const gchar *string = mdata->string;
2862 size_t string_len = mdata->string_len;
2863 capture_file *cf = mdata->cf;
2864 field_info *fi = PNODE_FINFO(node);
2865 gchar label_str[ITEM_LABEL_LENGTH];
2872 /* dissection with an invisible proto tree? */
2875 if (mdata->frame_matched) {
2876 /* We already had a match; don't bother doing any more work. */
2880 /* Don't match invisible entries. */
2881 if (PROTO_ITEM_IS_HIDDEN(node))
2884 /* was a free format label produced? */
2886 label_ptr = fi->rep->representation;
2888 /* no, make a generic label */
2889 label_ptr = label_str;
2890 proto_item_fill_label(fi, label_str);
2893 /* Does that label match? */
2894 label_len = strlen(label_ptr);
2895 for (i = 0; i < label_len; i++) {
2896 c_char = label_ptr[i];
2898 c_char = g_ascii_toupper(c_char);
2899 if (c_char == string[c_match]) {
2901 if (c_match == string_len) {
2902 /* No need to look further; we have a match */
2903 mdata->frame_matched = TRUE;
2911 /* Recurse into the subtree, if it exists */
2912 if (node->first_child != NULL)
2913 proto_tree_children_foreach(node, match_subtree_text, mdata);
2917 cf_find_packet_summary_line(capture_file *cf, const char *string,
2918 search_direction dir)
2922 mdata.string = string;
2923 mdata.string_len = strlen(string);
2924 return find_packet(cf, match_summary_line, &mdata, dir);
2928 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2930 match_data *mdata = (match_data *)criterion;
2931 const gchar *string = mdata->string;
2932 size_t string_len = mdata->string_len;
2934 const char *info_column;
2935 size_t info_column_len;
2936 match_result result = MR_NOTMATCHED;
2942 /* Load the frame's data. */
2943 if (!cf_read_record(cf, fdata)) {
2944 /* Attempt to get the packet failed. */
2948 /* Don't bother constructing the protocol tree */
2949 epan_dissect_init(&edt, cf->epan, FALSE, FALSE);
2950 /* Get the column information */
2951 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata,
2954 /* Find the Info column */
2955 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2956 if (cf->cinfo.columns[colx].fmt_matx[COL_INFO]) {
2957 /* Found it. See if we match. */
2958 info_column = edt.pi.cinfo->columns[colx].col_data;
2959 info_column_len = strlen(info_column);
2960 for (i = 0; i < info_column_len; i++) {
2961 c_char = info_column[i];
2963 c_char = g_ascii_toupper(c_char);
2964 if (c_char == string[c_match]) {
2966 if (c_match == string_len) {
2967 result = MR_MATCHED;
2976 epan_dissect_cleanup(&edt);
2983 } cbs_t; /* "Counted byte string" */
2987 * The current match_* routines only support ASCII case insensitivity and don't
2988 * convert UTF-8 inputs to UTF-16 for matching.
2990 * We could modify them to use the GLib Unicode routines or the International
2991 * Components for Unicode library but it's not apparent that we could do so
2992 * without consuming a lot more CPU and memory or that searching would be
2993 * significantly better.
2997 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size,
2998 search_direction dir)
3003 info.data_len = string_size;
3005 /* String or hex search? */
3007 /* String search - what type of string? */
3008 switch (cf->scs_type) {
3010 case SCS_NARROW_AND_WIDE:
3011 return find_packet(cf, match_narrow_and_wide, &info, dir);
3014 return find_packet(cf, match_narrow, &info, dir);
3017 return find_packet(cf, match_wide, &info, dir);
3020 g_assert_not_reached();
3024 return find_packet(cf, match_binary, &info, dir);
3028 match_narrow_and_wide(capture_file *cf, frame_data *fdata, void *criterion)
3030 cbs_t *info = (cbs_t *)criterion;
3031 const guint8 *ascii_text = info->data;
3032 size_t textlen = info->data_len;
3033 match_result result;
3040 /* Load the frame's data. */
3041 if (!cf_read_record(cf, fdata)) {
3042 /* Attempt to get the packet failed. */
3046 result = MR_NOTMATCHED;
3047 buf_len = fdata->cap_len;
3048 pd = ws_buffer_start_ptr(&cf->buf);
3050 while (i < buf_len) {
3053 c_char = g_ascii_toupper(c_char);
3054 if (c_char != '\0') {
3055 if (c_char == ascii_text[c_match]) {
3057 if (c_match == textlen) {
3058 result = MR_MATCHED;
3059 cf->search_pos = i; /* Save the position of the last character
3060 for highlighting the field. */
3065 g_assert(i>=c_match);
3066 i -= (guint32)c_match;
3076 match_narrow(capture_file *cf, frame_data *fdata, void *criterion)
3079 cbs_t *info = (cbs_t *)criterion;
3080 const guint8 *ascii_text = info->data;
3081 size_t textlen = info->data_len;
3082 match_result result;
3088 /* Load the frame's data. */
3089 if (!cf_read_record(cf, fdata)) {
3090 /* Attempt to get the packet failed. */
3094 result = MR_NOTMATCHED;
3095 buf_len = fdata->cap_len;
3096 pd = ws_buffer_start_ptr(&cf->buf);
3098 while (i < buf_len) {
3101 c_char = g_ascii_toupper(c_char);
3102 if (c_char == ascii_text[c_match]) {
3104 if (c_match == textlen) {
3105 result = MR_MATCHED;
3106 cf->search_pos = i; /* Save the position of the last character
3107 for highlighting the field. */
3112 g_assert(i>=c_match);
3113 i -= (guint32)c_match;
3123 match_wide(capture_file *cf, frame_data *fdata, void *criterion)
3125 cbs_t *info = (cbs_t *)criterion;
3126 const guint8 *ascii_text = info->data;
3127 size_t textlen = info->data_len;
3128 match_result result;
3135 /* Load the frame's data. */
3136 if (!cf_read_record(cf, fdata)) {
3137 /* Attempt to get the packet failed. */
3141 result = MR_NOTMATCHED;
3142 buf_len = fdata->cap_len;
3143 pd = ws_buffer_start_ptr(&cf->buf);
3145 while (i < buf_len) {
3148 c_char = g_ascii_toupper(c_char);
3149 if (c_char == ascii_text[c_match]) {
3151 if (c_match == textlen) {
3152 result = MR_MATCHED;
3153 cf->search_pos = i; /* Save the position of the last character
3154 for highlighting the field. */
3160 g_assert(i>=(c_match*2));
3161 i -= (guint32)c_match*2;
3170 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
3172 cbs_t *info = (cbs_t *)criterion;
3173 const guint8 *binary_data = info->data;
3174 size_t datalen = info->data_len;
3175 match_result result;
3181 /* Load the frame's data. */
3182 if (!cf_read_record(cf, fdata)) {
3183 /* Attempt to get the packet failed. */
3187 result = MR_NOTMATCHED;
3188 buf_len = fdata->cap_len;
3189 pd = ws_buffer_start_ptr(&cf->buf);
3191 while (i < buf_len) {
3192 if (pd[i] == binary_data[c_match]) {
3194 if (c_match == datalen) {
3195 result = MR_MATCHED;
3196 cf->search_pos = i; /* Save the position of the last character
3197 for highlighting the field. */
3202 g_assert(i>=c_match);
3203 i -= (guint32)c_match;
3212 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode,
3213 search_direction dir)
3215 return find_packet(cf, match_dfilter, sfcode, dir);
3219 cf_find_packet_dfilter_string(capture_file *cf, const char *filter,
3220 search_direction dir)
3225 if (!dfilter_compile(filter, &sfcode, NULL)) {
3227 * XXX - this shouldn't happen, as the filter string is machine
3232 if (sfcode == NULL) {
3234 * XXX - this shouldn't happen, as the filter string is machine
3239 result = find_packet(cf, match_dfilter, sfcode, dir);
3240 dfilter_free(sfcode);
3245 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
3247 dfilter_t *sfcode = (dfilter_t *)criterion;
3249 match_result result;
3251 /* Load the frame's data. */
3252 if (!cf_read_record(cf, fdata)) {
3253 /* Attempt to get the packet failed. */
3257 epan_dissect_init(&edt, cf->epan, TRUE, FALSE);
3258 epan_dissect_prime_dfilter(&edt, sfcode);
3259 epan_dissect_run(&edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(fdata, &cf->buf), fdata, NULL);
3260 result = dfilter_apply_edt(sfcode, &edt) ? MR_MATCHED : MR_NOTMATCHED;
3261 epan_dissect_cleanup(&edt);
3266 cf_find_packet_marked(capture_file *cf, search_direction dir)
3268 return find_packet(cf, match_marked, NULL, dir);
3272 match_marked(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3274 return fdata->flags.marked ? MR_MATCHED : MR_NOTMATCHED;
3278 cf_find_packet_time_reference(capture_file *cf, search_direction dir)
3280 return find_packet(cf, match_time_reference, NULL, dir);
3284 match_time_reference(capture_file *cf _U_, frame_data *fdata, void *criterion _U_)
3286 return fdata->flags.ref_time ? MR_MATCHED : MR_NOTMATCHED;
3290 find_packet(capture_file *cf,
3291 match_result (*match_function)(capture_file *, frame_data *, void *),
3292 void *criterion, search_direction dir)
3294 frame_data *start_fd;
3297 frame_data *new_fd = NULL;
3298 progdlg_t *progbar = NULL;
3302 GTimeVal start_time;
3303 gchar status_str[100];
3304 int progbar_nextstep;
3305 int progbar_quantum;
3307 match_result result;
3309 start_fd = cf->current_frame;
3310 if (start_fd != NULL) {
3311 /* Iterate through the list of packets, starting at the packet we've
3312 picked, calling a routine to run the filter on the packet, see if
3313 it matches, and stop if so. */
3315 framenum = start_fd->num;
3317 /* Update the progress bar when it gets to this value. */
3318 progbar_nextstep = 0;
3319 /* When we reach the value that triggers a progress bar update,
3320 bump that value by this amount. */
3321 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
3322 /* Progress so far. */
3325 cf->stop_flag = FALSE;
3326 g_get_current_time(&start_time);
3328 title = cf->sfilter?cf->sfilter:"";
3330 /* Create the progress bar if necessary.
3331 We check on every iteration of the loop, so that it takes no
3332 longer than the standard time to create it (otherwise, for a
3333 large file, we might take considerably longer than that standard
3334 time in order to get to the next progress bar step). */
3335 if (progbar == NULL)
3336 progbar = delayed_create_progress_dlg(cf->window, "Searching", title,
3337 FALSE, &cf->stop_flag, &start_time, progbar_val);
3339 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
3340 when we update it, we have to run the GTK+ main loop to get it
3341 to repaint what's pending, and doing so may involve an "ioctl()"
3342 to see if there's any pending input from an X server, and doing
3343 that for every packet can be costly, especially on a big file. */
3344 if (count >= progbar_nextstep) {
3345 /* let's not divide by zero. I should never be started
3346 * with count == 0, so let's assert that
3348 g_assert(cf->count > 0);
3350 progbar_val = (gfloat) count / cf->count;
3352 if (progbar != NULL) {
3353 g_snprintf(status_str, sizeof(status_str),
3354 "%4u of %u packets", count, cf->count);
3355 update_progress_dlg(progbar, progbar_val, status_str);
3358 progbar_nextstep += progbar_quantum;
3361 if (cf->stop_flag) {
3362 /* Well, the user decided to abort the search. Go back to the
3363 frame where we started. */
3368 /* Go past the current frame. */
3369 if (dir == SD_BACKWARD) {
3370 /* Go on to the previous frame. */
3371 if (framenum == 1) {
3373 * XXX - other apps have a bit more of a detailed message
3374 * for this, and instead of offering "OK" and "Cancel",
3375 * they offer things such as "Continue" and "Cancel";
3376 * we need an API for popping up alert boxes with
3377 * {Verb} and "Cancel".
3380 if (prefs.gui_find_wrap)
3382 statusbar_push_temporary_msg("Search reached the beginning. Continuing at end.");
3383 framenum = cf->count; /* wrap around */
3387 statusbar_push_temporary_msg("Search reached the beginning.");
3388 framenum = start_fd->num; /* stay on previous packet */
3393 /* Go on to the next frame. */
3394 if (framenum == cf->count) {
3395 if (prefs.gui_find_wrap)
3397 statusbar_push_temporary_msg("Search reached the end. Continuing at beginning.");
3398 framenum = 1; /* wrap around */
3402 statusbar_push_temporary_msg("Search reached the end.");
3403 framenum = start_fd->num; /* stay on previous packet */
3408 fdata = frame_data_sequence_find(cf->frames, framenum);
3412 /* Is this packet in the display? */
3413 if (fdata->flags.passed_dfilter) {
3414 /* Yes. Does it match the search criterion? */
3415 result = (*match_function)(cf, fdata, criterion);
3416 if (result == MR_ERROR) {
3417 /* Error; our caller has reported the error. Go back to the frame
3418 where we started. */
3421 } else if (result == MR_MATCHED) {
3422 /* Yes. Go to the new frame. */
3428 if (fdata == start_fd) {
3429 /* We're back to the frame we were on originally, and that frame
3430 doesn't match the search filter. The search failed. */
3435 /* We're done scanning the packets; destroy the progress bar if it
3437 if (progbar != NULL)
3438 destroy_progress_dlg(progbar);
3441 if (new_fd != NULL) {
3442 /* Find and select */
3443 cf->search_in_progress = TRUE;
3444 found = packet_list_select_row_from_data(new_fd);
3445 cf->search_in_progress = FALSE;
3446 cf->search_pos = 0; /* Reset the position */
3448 /* We didn't find a row corresponding to this frame.
3449 This means that the frame isn't being displayed currently,
3450 so we can't select it. */
3451 simple_message_box(ESD_TYPE_INFO, NULL,
3452 "The capture file is probably not fully dissected.",
3453 "End of capture exceeded.");
3456 return TRUE; /* success */
3458 return FALSE; /* failure */
3462 cf_goto_frame(capture_file *cf, guint fnumber)
3467 /* we don't have a loaded capture file - fix for bug 11810*/
3468 statusbar_push_temporary_msg("There is no file loaded");
3469 return FALSE; /* we failed to go to that packet */
3472 fdata = frame_data_sequence_find(cf->frames, fnumber);
3474 if (fdata == NULL) {
3475 /* we didn't find a packet with that packet number */
3476 statusbar_push_temporary_msg("There is no packet number %u.", fnumber);
3477 return FALSE; /* we failed to go to that packet */
3479 if (!fdata->flags.passed_dfilter) {
3480 /* that packet currently isn't displayed */
3481 /* XXX - add it to the set of displayed packets? */
3482 statusbar_push_temporary_msg("Packet number %u isn't displayed.", fnumber);
3483 return FALSE; /* we failed to go to that packet */
3486 if (!packet_list_select_row_from_data(fdata)) {
3487 /* We didn't find a row corresponding to this frame.
3488 This means that the frame isn't being displayed currently,
3489 so we can't select it. */
3490 simple_message_box(ESD_TYPE_INFO, NULL,
3491 "The capture file is probably not fully dissected.",
3492 "End of capture exceeded.");
3495 return TRUE; /* we got to that packet */
3499 cf_goto_top_frame(void)
3501 /* Find and select */
3502 packet_list_select_first_row();
3503 return TRUE; /* we got to that packet */
3507 cf_goto_bottom_frame(void)
3509 /* Find and select */
3510 packet_list_select_last_row();
3511 return TRUE; /* we got to that packet */
3515 * Go to frame specified by currently selected protocol tree item.
3518 cf_goto_framenum(capture_file *cf)
3520 header_field_info *hfinfo;
3523 if (cf->finfo_selected) {
3524 hfinfo = cf->finfo_selected->hfinfo;
3526 if (hfinfo->type == FT_FRAMENUM) {
3527 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3529 return cf_goto_frame(cf, framenum);
3536 /* Select the packet on a given row. */
3538 cf_select_packet(capture_file *cf, int row)
3540 epan_dissect_t *old_edt;
3543 /* Get the frame data struct pointer for this frame */
3544 fdata = packet_list_get_row_data(row);
3546 if (fdata == NULL) {
3547 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3548 the first entry is added to it by "real_insert_row()", that row
3549 is selected (see "real_insert_row()", in "ui/gtk/gtkclist.c", in both
3550 our version and the vanilla GTK+ version).
3552 This means that a "select-row" signal is emitted; this causes
3553 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3556 "cf_select_packet()" fetches, above, the data associated with the
3557 row that was selected; however, as "gtk_clist_append()", which
3558 called "real_insert_row()", hasn't yet returned, we haven't yet
3559 associated any data with that row, so we get back a null pointer.
3561 We can't assume that there's only one frame in the frame list,
3562 either, as we may be filtering the display.
3564 We therefore assume that, if "row" is 0, i.e. the first row
3565 is being selected, and "cf->first_displayed" equals
3566 "cf->last_displayed", i.e. there's only one frame being
3567 displayed, that frame is the frame we want.
3569 This means we have to set "cf->first_displayed" and
3570 "cf->last_displayed" before adding the row to the
3571 GtkCList; see the comment in "add_packet_to_packet_list()". */
3573 if (row == 0 && cf->first_displayed == cf->last_displayed)
3574 fdata = frame_data_sequence_find(cf->frames, cf->first_displayed);
3577 /* If fdata _still_ isn't set simply give up. */
3578 if (fdata == NULL) {
3582 /* Get the data in that frame. */
3583 if (!cf_read_record (cf, fdata)) {
3587 /* Record that this frame is the current frame. */
3588 cf->current_frame = fdata;
3589 cf->current_row = row;
3592 /* Create the logical protocol tree. */
3593 /* We don't need the columns here. */
3594 cf->edt = epan_dissect_new(cf->epan, TRUE, TRUE);
3596 tap_build_interesting(cf->edt);
3597 epan_dissect_run(cf->edt, cf->cd_t, &cf->phdr, frame_tvbuff_new_buffer(cf->current_frame, &cf->buf),
3598 cf->current_frame, NULL);
3600 dfilter_macro_build_ftv_cache(cf->edt->tree);
3602 cf_callback_invoke(cf_cb_packet_selected, cf);
3604 if (old_edt != NULL)
3605 epan_dissect_free(old_edt);
3609 /* Unselect the selected packet, if any. */
3611 cf_unselect_packet(capture_file *cf)
3613 epan_dissect_t *old_edt = cf->edt;
3617 /* No packet is selected. */
3618 cf->current_frame = NULL;
3619 cf->current_row = 0;
3621 cf_callback_invoke(cf_cb_packet_unselected, cf);
3623 /* No protocol tree means no selected field. */
3624 cf_unselect_field(cf);
3626 /* Destroy the epan_dissect_t for the unselected packet. */
3627 if (old_edt != NULL)
3628 epan_dissect_free(old_edt);
3631 /* Unset the selected protocol tree field, if any. */
3633 cf_unselect_field(capture_file *cf)
3635 cf->finfo_selected = NULL;
3637 cf_callback_invoke(cf_cb_field_unselected, cf);
3641 * Mark a particular frame.
3644 cf_mark_frame(capture_file *cf, frame_data *frame)
3646 if (! frame->flags.marked) {
3647 frame->flags.marked = TRUE;
3648 if (cf->count > cf->marked_count)
3654 * Unmark a particular frame.
3657 cf_unmark_frame(capture_file *cf, frame_data *frame)
3659 if (frame->flags.marked) {
3660 frame->flags.marked = FALSE;
3661 if (cf->marked_count > 0)
3667 * Ignore a particular frame.
3670 cf_ignore_frame(capture_file *cf, frame_data *frame)
3672 if (! frame->flags.ignored) {
3673 frame->flags.ignored = TRUE;
3674 if (cf->count > cf->ignored_count)
3675 cf->ignored_count++;
3680 * Un-ignore a particular frame.
3683 cf_unignore_frame(capture_file *cf, frame_data *frame)
3685 if (frame->flags.ignored) {
3686 frame->flags.ignored = FALSE;
3687 if (cf->ignored_count > 0)
3688 cf->ignored_count--;
3693 * Read the comment in SHB block
3697 cf_read_shb_comment(capture_file *cf)
3699 /* Get info from SHB */
3700 return wtap_file_get_shb_comment(cf->wth);
3704 cf_update_capture_comment(capture_file *cf, gchar *comment)
3706 const gchar *shb_comment;
3708 /* Get info from SHB */
3709 shb_comment = wtap_file_get_shb_comment(cf->wth);
3711 /* See if the comment has changed or not */
3713 if (strcmp(shb_comment, comment) == 0) {
3719 /* The comment has changed, let's update it */
3720 wtap_write_shb_comment(cf->wth, comment);
3721 /* Mark the file as having unsaved changes */
3722 cf->unsaved_changes = TRUE;
3726 cf_get_user_packet_comment(capture_file *cf, const frame_data *fd)
3728 if (cf->frames_user_comments)
3729 return (const char *)g_tree_lookup(cf->frames_user_comments, fd);
3736 cf_get_comment(capture_file *cf, const frame_data *fd)
3740 /* fetch user comment */
3741 if (fd->flags.has_user_comment)
3742 return g_strdup(cf_get_user_packet_comment(cf, fd));
3744 /* fetch phdr comment */
3745 if (fd->flags.has_phdr_comment) {
3746 struct wtap_pkthdr phdr; /* Packet header */
3747 Buffer buf; /* Packet data */
3749 wtap_phdr_init(&phdr);
3750 ws_buffer_init(&buf, 1500);
3752 if (!cf_read_record_r(cf, fd, &phdr, &buf))
3753 { /* XXX, what we can do here? */ }
3755 comment = phdr.opt_comment;
3756 wtap_phdr_cleanup(&phdr);
3757 ws_buffer_free(&buf);
3764 frame_cmp(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3766 const frame_data *fdata1 = (const frame_data *) a;
3767 const frame_data *fdata2 = (const frame_data *) b;
3769 return (fdata1->num < fdata2->num) ? -1 :
3770 (fdata1->num > fdata2->num) ? 1 :
3775 cf_set_user_packet_comment(capture_file *cf, frame_data *fd, const gchar *new_comment)
3777 char *pkt_comment = cf_get_comment(cf, fd);
3779 /* Check if the comment has changed */
3780 if (!g_strcmp0(pkt_comment, new_comment)) {
3781 g_free(pkt_comment);
3784 g_free(pkt_comment);
3787 cf->packet_comment_count--;
3790 cf->packet_comment_count++;
3792 fd->flags.has_user_comment = TRUE;
3794 if (!cf->frames_user_comments)
3795 cf->frames_user_comments = g_tree_new_full(frame_cmp, NULL, NULL, g_free);
3797 /* insert new packet comment */
3798 g_tree_replace(cf->frames_user_comments, fd, g_strdup(new_comment));
3800 expert_update_comment_count(cf->packet_comment_count);
3802 /* OK, we have unsaved changes. */
3803 cf->unsaved_changes = TRUE;
3808 * What types of comments does this capture file have?
3811 cf_comment_types(capture_file *cf)
3813 guint32 comment_types = 0;
3815 if (cf_read_shb_comment(cf) != NULL)
3816 comment_types |= WTAP_COMMENT_PER_SECTION;
3817 if (cf->packet_comment_count != 0)
3818 comment_types |= WTAP_COMMENT_PER_PACKET;
3819 return comment_types;
3822 #ifdef WANT_PACKET_EDITOR
3824 g_direct_compare_func(gconstpointer a, gconstpointer b, gpointer user_data _U_)
3835 modified_frame_data_free(gpointer data)
3837 modified_frame_data *mfd = (modified_frame_data *)data;
3844 * Give a frame new, edited data.
3847 cf_set_frame_edited(capture_file *cf, frame_data *fd,
3848 struct wtap_pkthdr *phdr, guint8 *pd)
3850 modified_frame_data *mfd = (modified_frame_data *)g_malloc(sizeof(modified_frame_data));
3855 if (cf->edited_frames == NULL)
3856 cf->edited_frames = g_tree_new_full(g_direct_compare_func, NULL, NULL,
3857 modified_frame_data_free);
3858 g_tree_insert(cf->edited_frames, GINT_TO_POINTER(fd->num), mfd);
3861 /* Mark the file as having unsaved changes */
3862 cf->unsaved_changes = TRUE;
3870 } save_callback_args_t;
3873 * Save a capture to a file, in a particular format, saving either
3874 * all packets, all currently-displayed packets, or all marked packets.
3876 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3877 * up a message box for the failure.
3880 save_record(capture_file *cf, frame_data *fdata,
3881 struct wtap_pkthdr *phdr, const guint8 *pd,
3884 save_callback_args_t *args = (save_callback_args_t *)argsp;
3885 struct wtap_pkthdr hdr;
3888 gchar *display_basename;
3889 const char *pkt_comment;
3891 if (fdata->flags.has_user_comment)
3892 pkt_comment = cf_get_user_packet_comment(cf, fdata);
3894 pkt_comment = phdr->opt_comment;
3896 /* init the wtap header for saving */
3897 /* TODO: reuse phdr */
3898 /* XXX - these are the only flags that correspond to data that we have
3899 in the frame_data structure and that matter on a per-packet basis.
3901 For WTAP_HAS_CAP_LEN, either the file format has separate "captured"
3902 and "on the wire" lengths, or it doesn't.
3904 For WTAP_HAS_DROP_COUNT, Wiretap doesn't actually supply the value
3907 For WTAP_HAS_PACK_FLAGS, we currently don't save the FCS length
3908 from the packet flags. */
3909 hdr.rec_type = phdr->rec_type;
3910 hdr.presence_flags = 0;
3911 if (fdata->flags.has_ts)
3912 hdr.presence_flags |= WTAP_HAS_TS;
3913 if (phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
3914 hdr.presence_flags |= WTAP_HAS_INTERFACE_ID;
3915 if (phdr->presence_flags & WTAP_HAS_PACK_FLAGS)
3916 hdr.presence_flags |= WTAP_HAS_PACK_FLAGS;
3917 hdr.ts.secs = fdata->abs_ts.secs;
3918 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3919 hdr.caplen = phdr->caplen;
3920 hdr.len = phdr->len;
3921 hdr.pkt_encap = fdata->lnk_t;
3923 hdr.interface_id = phdr->interface_id; /* identifier of the interface. */
3925 hdr.pack_flags = phdr->pack_flags;
3926 hdr.opt_comment = g_strdup(pkt_comment);
3929 hdr.pseudo_header = phdr->pseudo_header;
3932 hdr.pack_flags = /* XXX - 0 for now (any value for "we don't have it"?) */
3934 /* and save the packet */
3935 if (!wtap_dump(args->pdh, &hdr, pd, &err, &err_info)) {
3937 /* Wiretap error. */
3940 case WTAP_ERR_UNWRITABLE_ENCAP:
3942 * This is a problem with the particular frame we're writing and
3943 * the file type and subtype we're writing; note that, and report
3944 * the frame number and file type/subtype.
3946 simple_error_message_box(
3947 "Frame %u has a network type that can't be saved in a \"%s\" file.",
3948 fdata->num, wtap_file_type_subtype_string(args->file_type));
3951 case WTAP_ERR_PACKET_TOO_LARGE:
3953 * This is a problem with the particular frame we're writing and
3954 * the file type and subtype we're writing; note that, and report
3955 * the frame number and file type/subtype.
3957 simple_error_message_box(
3958 "Frame %u is larger than Wireshark supports in a \"%s\" file.",
3959 fdata->num, wtap_file_type_subtype_string(args->file_type));
3962 case WTAP_ERR_UNWRITABLE_REC_TYPE:
3964 * This is a problem with the particular record we're writing and
3965 * the file type and subtype we're writing; note that, and report
3966 * the record number and file type/subtype.
3968 simple_error_message_box(
3969 "Record %u has a record type that can't be saved in a \"%s\" file.",
3970 fdata->num, wtap_file_type_subtype_string(args->file_type));
3973 case WTAP_ERR_UNWRITABLE_REC_DATA:
3975 * This is a problem with the particular frame we're writing and
3976 * the file type and subtype we're writing; note that, and report
3977 * the frame number and file type/subtype.
3979 simple_error_message_box(
3980 "Record %u has data that can't be saved in a \"%s\" file.\n(%s)",
3981 fdata->num, wtap_file_type_subtype_string(args->file_type),
3982 err_info != NULL ? err_info : "no information supplied");
3987 display_basename = g_filename_display_basename(args->fname);
3988 simple_error_message_box(
3989 "An error occurred while writing to the file \"%s\": %s.",
3990 display_basename, wtap_strerror(err));
3991 g_free(display_basename);
3996 write_failure_alert_box(args->fname, err);
4001 g_free(hdr.opt_comment);
4006 * Can this capture file be written out in any format using Wiretap
4007 * rather than by copying the raw data?
4010 cf_can_write_with_wiretap(capture_file *cf)
4012 /* We don't care whether we support the comments in this file or not;
4013 if we can't, we'll offer the user the option of discarding the
4015 return wtap_dump_can_write(cf->linktypes, 0);
4019 * Should we let the user do a save?
4023 * the file has unsaved changes, and we can save it in some
4024 * format through Wiretap
4028 * the file is a temporary file and has no unsaved changes (so
4029 * that "saving" it just means copying it).
4031 * XXX - we shouldn't allow files to be edited if they can't be saved,
4032 * so cf->unsaved_changes should be true only if the file can be saved.
4034 * We don't care whether we support the comments in this file or not;
4035 * if we can't, we'll offer the user the option of discarding the
4039 cf_can_save(capture_file *cf)
4041 if (cf->unsaved_changes && wtap_dump_can_write(cf->linktypes, 0)) {
4042 /* Saved changes, and we can write it out with Wiretap. */
4046 if (cf->is_tempfile && !cf->unsaved_changes) {
4048 * Temporary file with no unsaved changes, so we can just do a
4054 /* Nothing to save. */
4059 * Should we let the user do a "save as"?
4063 * we can save it in some format through Wiretap
4067 * the file is a temporary file and has no unsaved changes (so
4068 * that "saving" it just means copying it).
4070 * XXX - we shouldn't allow files to be edited if they can't be saved,
4071 * so cf->unsaved_changes should be true only if the file can be saved.
4073 * We don't care whether we support the comments in this file or not;
4074 * if we can't, we'll offer the user the option of discarding the
4078 cf_can_save_as(capture_file *cf)
4080 if (wtap_dump_can_write(cf->linktypes, 0)) {
4081 /* We can write it out with Wiretap. */
4085 if (cf->is_tempfile && !cf->unsaved_changes) {
4087 * Temporary file with no unsaved changes, so we can just do a
4093 /* Nothing to save. */
4098 * Does this file have unsaved data?
4101 cf_has_unsaved_data(capture_file *cf)
4104 * If this is a temporary file, or a file with unsaved changes, it
4107 return (cf->is_tempfile && cf->count>0) || cf->unsaved_changes;
4111 * Quick scan to find packet offsets.
4113 static cf_read_status_t
4114 rescan_file(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
4116 const struct wtap_pkthdr *phdr;
4120 progdlg_t *progbar = NULL;
4123 GTimeVal start_time;
4124 gchar status_str[100];
4125 gint64 progbar_nextstep;
4126 gint64 progbar_quantum;
4131 /* Close the old handle. */
4132 wtap_close(cf->wth);
4134 /* Open the new file. */
4135 /* XXX: this will go through all open_routines for a matching one. But right
4136 now rescan_file() is only used when a file is being saved to a different
4137 format than the original, and the user is not given a choice of which
4138 reader to use (only which format to save it in), so doing this makes
4140 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, err, &err_info, TRUE);
4141 if (cf->wth == NULL) {
4142 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
4143 return CF_READ_ERROR;
4146 /* We're scanning a file whose contents should be the same as what
4147 we had before, so we don't discard dissection state etc.. */
4150 /* Set the file name because we need it to set the follow stream filter.
4151 XXX - is that still true? We need it for other reasons, though,
4153 cf->filename = g_strdup(fname);
4155 /* Indicate whether it's a permanent or temporary file. */
4156 cf->is_tempfile = is_tempfile;
4158 /* No user changes yet. */
4159 cf->unsaved_changes = FALSE;
4161 cf->cd_t = wtap_file_type_subtype(cf->wth);
4162 cf->linktypes = g_array_sized_new(FALSE, FALSE, (guint) sizeof(int), 1);
4164 cf->snap = wtap_snapshot_length(cf->wth);
4165 if (cf->snap == 0) {
4166 /* Snapshot length not known. */
4167 cf->has_snap = FALSE;
4168 cf->snap = WTAP_MAX_PACKET_SIZE;
4170 cf->has_snap = TRUE;
4172 name_ptr = g_filename_display_basename(cf->filename);
4174 cf_callback_invoke(cf_cb_file_rescan_started, cf);
4176 /* Record whether the file is compressed.
4177 XXX - do we know this at open time? */
4178 cf->iscompressed = wtap_iscompressed(cf->wth);
4180 /* Find the size of the file. */
4181 size = wtap_file_size(cf->wth, NULL);
4183 /* Update the progress bar when it gets to this value. */
4184 progbar_nextstep = 0;
4185 /* When we reach the value that triggers a progress bar update,
4186 bump that value by this amount. */
4188 progbar_quantum = size/N_PROGBAR_UPDATES;
4189 if (progbar_quantum < MIN_QUANTUM)
4190 progbar_quantum = MIN_QUANTUM;
4192 progbar_quantum = 0;
4194 cf->stop_flag = FALSE;
4195 g_get_current_time(&start_time);
4198 phdr = wtap_phdr(cf->wth);
4199 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
4201 fdata = frame_data_sequence_find(cf->frames, framenum);
4202 fdata->file_off = data_offset;
4205 cf->f_datalen = wtap_read_so_far(cf->wth);
4207 /* Create the progress bar if necessary.
4208 * Check whether it should be created or not every MIN_NUMBER_OF_PACKET
4210 if ((progbar == NULL) && !(count % MIN_NUMBER_OF_PACKET)) {
4211 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4212 progbar = delayed_create_progress_dlg(cf->window, "Rescanning", name_ptr,
4213 TRUE, &cf->stop_flag, &start_time, progbar_val);
4216 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
4217 when we update it, we have to run the GTK+ main loop to get it
4218 to repaint what's pending, and doing so may involve an "ioctl()"
4219 to see if there's any pending input from an X server, and doing
4220 that for every packet can be costly, especially on a big file. */
4221 if (cf->f_datalen >= progbar_nextstep) {
4222 if (progbar != NULL) {
4223 progbar_val = calc_progbar_val(cf, size, cf->f_datalen, status_str, sizeof(status_str));
4224 /* update the packet bar content on the first run or frequently on very large files */
4225 update_progress_dlg(progbar, progbar_val, status_str);
4226 packets_bar_update();
4228 progbar_nextstep += progbar_quantum;
4232 if (cf->stop_flag) {
4233 /* Well, the user decided to abort the rescan. Sadly, as this
4234 isn't a reread, recovering is difficult, so we'll just
4235 close the current capture. */
4239 /* Add this packet's link-layer encapsulation type to cf->linktypes, if
4240 it's not already there.
4241 XXX - yes, this is O(N), so if every packet had a different
4242 link-layer encapsulation type, it'd be O(N^2) to read the file, but
4243 there are probably going to be a small number of encapsulation types
4245 cf_add_encapsulation_type(cf, phdr->pkt_encap);
4248 /* Free the display name */
4251 /* We're done reading the file; destroy the progress bar if it was created. */
4252 if (progbar != NULL)
4253 destroy_progress_dlg(progbar);
4255 /* We're done reading sequentially through the file. */
4256 cf->state = FILE_READ_DONE;
4258 /* Close the sequential I/O side, to free up memory it requires. */
4259 wtap_sequential_close(cf->wth);
4261 /* compute the time it took to load the file */
4262 compute_elapsed(cf, &start_time);
4264 /* Set the file encapsulation type now; we don't know what it is until
4265 we've looked at all the packets, as we don't know until then whether
4266 there's more than one type (and thus whether it's
4267 WTAP_ENCAP_PER_PACKET). */
4268 cf->lnk_t = wtap_file_encap(cf->wth);
4270 cf_callback_invoke(cf_cb_file_rescan_finished, cf);
4272 if (cf->stop_flag) {
4273 /* Our caller will give up at this point. */
4274 return CF_READ_ABORTED;
4278 /* Put up a message box noting that the read failed somewhere along
4279 the line. Don't throw out the stuff we managed to read, though,
4283 case WTAP_ERR_UNSUPPORTED:
4284 simple_error_message_box(
4285 "The capture file contains record data that Wireshark doesn't support.\n(%s)",
4286 err_info != NULL ? err_info : "no information supplied");
4290 case WTAP_ERR_SHORT_READ:
4291 simple_error_message_box(
4292 "The capture file appears to have been cut short"
4293 " in the middle of a packet.");
4296 case WTAP_ERR_BAD_FILE:
4297 simple_error_message_box(
4298 "The capture file appears to be damaged or corrupt.\n(%s)",
4299 err_info != NULL ? err_info : "no information supplied");
4303 case WTAP_ERR_DECOMPRESS:
4304 simple_error_message_box(
4305 "The compressed capture file appears to be damaged or corrupt.\n"
4307 err_info != NULL ? err_info : "no information supplied");
4312 simple_error_message_box(
4313 "An error occurred while reading the"
4314 " capture file: %s.", wtap_strerror(*err));
4317 return CF_READ_ERROR;
4323 cf_save_records(capture_file *cf, const char *fname, guint save_format,
4324 gboolean compressed, gboolean discard_comments,
4325 gboolean dont_reopen)
4328 gchar *fname_new = NULL;
4331 addrinfo_lists_t *addr_lists;
4335 gchar *display_basename;
4342 save_callback_args_t callback_args;
4344 cf_callback_invoke(cf_cb_file_save_started, (gpointer)fname);
4346 addr_lists = get_addrinfo_list();
4348 if (save_format == cf->cd_t && compressed == cf->iscompressed
4349 && !discard_comments && !cf->unsaved_changes
4350 && !(addr_lists && wtap_dump_has_name_resolution(save_format))) {
4351 /* We're saving in the format it's already in, and we're
4352 not discarding comments, and there are no changes we have
4353 in memory that aren't saved to the file, and we have no name
4354 resolution blocks to write, so we can just move or copy the raw data. */
4356 if (cf->is_tempfile) {
4357 /* The file being saved is a temporary file from a live
4358 capture, so it doesn't need to stay around under that name;
4359 first, try renaming the capture buffer file to the new name.
4360 This acts as a "safe save", in that, if the file already
4361 exists, the existing file will be removed only if the rename
4364 Sadly, on Windows, as we have the current capture file
4365 open, even MoveFileEx() with MOVEFILE_REPLACE_EXISTING
4366 (to cause the rename to remove an existing target), as
4367 done by ws_stdio_rename() (ws_rename() is #defined to
4368 be ws_stdio_rename() on Windows) will fail.
4370 According to the MSDN documentation for CreateFile(), if,
4371 when we open a capture file, we were to directly do a CreateFile(),
4372 opening with FILE_SHARE_DELETE|FILE_SHARE_READ, and then
4373 convert it to a file descriptor with _open_osfhandle(),
4374 that would allow the file to be renamed out from under us.
4376 However, that doesn't work in practice. Perhaps the problem
4377 is that the process doing the rename is the process that
4378 has the file open. */
4380 if (ws_rename(cf->filename, fname) == 0) {
4381 /* That succeeded - there's no need to copy the source file. */
4382 how_to_save = SAVE_WITH_MOVE;
4384 if (errno == EXDEV) {
4385 /* They're on different file systems, so we have to copy the
4387 how_to_save = SAVE_WITH_COPY;
4389 /* The rename failed, but not because they're on different
4390 file systems - put up an error message. (Or should we
4391 just punt and try to copy? The only reason why I'd
4392 expect the rename to fail and the copy to succeed would
4393 be if we didn't have permission to remove the file from
4394 the temporary directory, and that might be fixable - but
4395 is it worth requiring the user to go off and fix it?) */
4396 cf_rename_failure_alert_box(fname, errno);
4401 how_to_save = SAVE_WITH_COPY;
4404 /* It's a permanent file, so we should copy it, and not remove the
4406 how_to_save = SAVE_WITH_COPY;
4409 if (how_to_save == SAVE_WITH_COPY) {
4410 /* Copy the file, if we haven't moved it. If we're overwriting
4411 an existing file, we do it with a "safe save", by writing
4412 to a new file and, if the write succeeds, renaming the
4413 new file on top of the old file. */
4414 if (file_exists(fname)) {
4415 fname_new = g_strdup_printf("%s~", fname);
4416 if (!copy_file_binary_mode(cf->filename, fname_new))
4419 if (!copy_file_binary_mode(cf->filename, fname))
4424 /* Either we're saving in a different format or we're saving changes,
4425 such as added, modified, or removed comments, that haven't yet
4426 been written to the underlying file; we can't do that by copying
4427 or moving the capture file, we have to do it by writing the packets
4430 wtapng_section_t *shb_hdr = NULL;
4431 wtapng_iface_descriptions_t *idb_inf = NULL;
4432 wtapng_name_res_t *nrb_hdr = NULL;
4435 /* XXX: what free's this shb_hdr? */
4436 shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
4437 idb_inf = wtap_file_get_idb_info(cf->wth);
4438 nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
4440 /* Determine what file encapsulation type we should use. */
4441 encap = wtap_dump_file_encap_type(cf->linktypes);
4443 if (file_exists(fname)) {
4444 /* We're overwriting an existing file; write out to a new file,
4445 and, if that succeeds, rename the new file on top of the
4446 old file. That makes this a "safe save", so that we don't
4447 lose the old file if we have a problem writing out the new
4448 file. (If the existing file is the current capture file,
4449 we *HAVE* to do that, otherwise we're overwriting the file
4450 from which we're reading the packets that we're writing!) */
4451 fname_new = g_strdup_printf("%s~", fname);
4452 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4453 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4455 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4456 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4462 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4466 /* Add address resolution */
4467 wtap_dump_set_addrinfo_list(pdh, addr_lists);
4469 /* Iterate through the list of packets, processing all the packets. */
4470 callback_args.pdh = pdh;
4471 callback_args.fname = fname;
4472 callback_args.file_type = save_format;
4473 switch (process_specified_records(cf, NULL, "Saving", "packets",
4474 TRUE, save_record, &callback_args)) {
4477 /* Completed successfully. */
4481 /* The user decided to abort the saving.
4482 If we're writing to a temporary file, remove it.
4483 XXX - should we do so even if we're not writing to a
4485 wtap_dump_close(pdh, &err);
4486 if (fname_new != NULL)
4487 ws_unlink(fname_new);
4488 cf_callback_invoke(cf_cb_file_save_stopped, NULL);
4489 return CF_WRITE_ABORTED;
4492 /* Error while saving.
4493 If we're writing to a temporary file, remove it. */
4494 if (fname_new != NULL)
4495 ws_unlink(fname_new);
4496 wtap_dump_close(pdh, &err);
4500 if (!wtap_dump_close(pdh, &err)) {
4501 cf_close_failure_alert_box(fname, err);
4505 how_to_save = SAVE_WITH_WTAP;
4508 if (fname_new != NULL) {
4509 /* We wrote out to fname_new, and should rename it on top of
4510 fname. fname_new is now closed, so that should be possible even
4511 on Windows. However, on Windows, we first need to close whatever
4512 file descriptors we have open for fname. */
4514 wtap_fdclose(cf->wth);
4516 /* Now do the rename. */
4517 if (ws_rename(fname_new, fname) == -1) {
4518 /* Well, the rename failed. */
4519 cf_rename_failure_alert_box(fname, errno);
4521 /* Attempt to reopen the random file descriptor using the
4522 current file's filename. (At this point, the sequential
4523 file descriptor is closed.) */
4524 if (!wtap_fdreopen(cf->wth, cf->filename, &err)) {
4525 /* Oh, well, we're screwed. */
4526 display_basename = g_filename_display_basename(cf->filename);
4527 simple_error_message_box(
4528 file_open_error_message(err, FALSE), display_basename);
4529 g_free(display_basename);
4536 cf_callback_invoke(cf_cb_file_save_finished, NULL);
4537 cf->unsaved_changes = FALSE;
4540 switch (how_to_save) {
4542 case SAVE_WITH_MOVE:
4543 /* We just moved the file, so the wtap structure refers to the
4544 new file, and all the information other than the filename
4545 and the "is temporary" status applies to the new file; just
4547 g_free(cf->filename);
4548 cf->filename = g_strdup(fname);
4549 cf->is_tempfile = FALSE;
4550 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4553 case SAVE_WITH_COPY:
4554 /* We just copied the file, s all the information other than
4555 the wtap structure, the filename, and the "is temporary"
4556 status applies to the new file; just update that. */
4557 wtap_close(cf->wth);
4558 /* Although we're just "copying" and then opening the copy, it will
4559 try all open_routine readers to open the copy, so we need to
4560 reset the cfile's open_type. */
4561 cf->open_type = WTAP_TYPE_AUTO;
4562 cf->wth = wtap_open_offline(fname, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
4563 if (cf->wth == NULL) {
4564 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
4567 g_free(cf->filename);
4568 cf->filename = g_strdup(fname);
4569 cf->is_tempfile = FALSE;
4571 cf_callback_invoke(cf_cb_file_fast_save_finished, cf);
4574 case SAVE_WITH_WTAP:
4575 /* Open and read the file we saved to.
4577 XXX - this is somewhat of a waste; we already have the
4578 packets, all this gets us is updated file type information
4579 (which we could just stuff into "cf"), and having the new
4580 file be the one we have opened and from which we're reading
4581 the data, and it means we have to spend time opening and
4582 reading the file, which could be a significant amount of
4583 time if the file is large.
4585 If the capture-file-writing code were to return the
4586 seek offset of each packet it writes, we could save that
4587 in the frame_data structure for the frame, and just open
4588 the file without reading it again...
4590 ...as long as, for gzipped files, the process of writing
4591 out the file *also* generates the information needed to
4592 support fast random access to the compressed file. */
4593 /* rescan_file will cause us to try all open_routines, so
4594 reset cfile's open_type */
4595 cf->open_type = WTAP_TYPE_AUTO;
4596 if (rescan_file(cf, fname, FALSE, &err) != CF_READ_OK) {
4597 /* The rescan failed; just close the file. Either
4598 a dialog was popped up for the failure, so the
4599 user knows what happened, or they stopped the
4600 rescan, in which case they know what happened. */
4606 /* If we were told to discard the comments, do so. */
4607 if (discard_comments) {
4608 /* Remove SHB comment, if any. */
4609 wtap_write_shb_comment(cf->wth, NULL);
4611 /* remove all user comments */
4612 for (framenum = 1; framenum <= cf->count; framenum++) {
4613 fdata = frame_data_sequence_find(cf->frames, framenum);
4615 fdata->flags.has_phdr_comment = FALSE;
4616 fdata->flags.has_user_comment = FALSE;
4619 if (cf->frames_user_comments) {
4620 g_tree_destroy(cf->frames_user_comments);
4621 cf->frames_user_comments = NULL;
4624 cf->packet_comment_count = 0;
4630 if (fname_new != NULL) {
4631 /* We were trying to write to a temporary file; get rid of it if it
4632 exists. (We don't care whether this fails, as, if it fails,
4633 there's not much we can do about it. I guess if it failed for
4634 a reason other than "it doesn't exist", we could report an
4635 error, so the user knows there's a junk file that they might
4636 want to clean up.) */
4637 ws_unlink(fname_new);
4640 cf_callback_invoke(cf_cb_file_save_failed, NULL);
4641 return CF_WRITE_ERROR;
4645 cf_export_specified_packets(capture_file *cf, const char *fname,
4646 packet_range_t *range, guint save_format,
4647 gboolean compressed)
4649 gchar *fname_new = NULL;
4652 save_callback_args_t callback_args;
4653 wtapng_section_t *shb_hdr = NULL;
4654 wtapng_iface_descriptions_t *idb_inf = NULL;
4655 wtapng_name_res_t *nrb_hdr = NULL;
4658 cf_callback_invoke(cf_cb_file_export_specified_packets_started, (gpointer)fname);
4660 packet_range_process_init(range);
4662 /* We're writing out specified packets from the specified capture
4663 file to another file. Even if all captured packets are to be
4664 written, don't special-case the operation - read each packet
4665 and then write it out if it's one of the specified ones. */
4667 /* XXX: what free's this shb_hdr? */
4668 shb_hdr = wtap_file_get_shb_for_new_file(cf->wth);
4669 idb_inf = wtap_file_get_idb_info(cf->wth);
4670 nrb_hdr = wtap_file_get_nrb_for_new_file(cf->wth);
4672 /* Determine what file encapsulation type we should use. */
4673 encap = wtap_dump_file_encap_type(cf->linktypes);
4675 if (file_exists(fname)) {
4676 /* We're overwriting an existing file; write out to a new file,
4677 and, if that succeeds, rename the new file on top of the
4678 old file. That makes this a "safe save", so that we don't
4679 lose the old file if we have a problem writing out the new
4680 file. (If the existing file is the current capture file,
4681 we *HAVE* to do that, otherwise we're overwriting the file
4682 from which we're reading the packets that we're writing!) */
4683 fname_new = g_strdup_printf("%s~", fname);
4684 pdh = wtap_dump_open_ng(fname_new, save_format, encap, cf->snap,
4685 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4687 pdh = wtap_dump_open_ng(fname, save_format, encap, cf->snap,
4688 compressed, shb_hdr, idb_inf, nrb_hdr, &err);
4694 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
4698 /* Add address resolution */
4699 wtap_dump_set_addrinfo_list(pdh, get_addrinfo_list());
4701 /* Iterate through the list of packets, processing the packets we were
4704 XXX - we've already called "packet_range_process_init(range)", but
4705 "process_specified_records()" will do it again. Fortunately,
4706 that's harmless in this case, as we haven't done anything to
4707 "range" since we initialized it. */
4708 callback_args.pdh = pdh;
4709 callback_args.fname = fname;
4710 callback_args.file_type = save_format;
4711 switch (process_specified_records(cf, range, "Writing", "specified records",
4712 TRUE, save_record, &callback_args)) {
4715 /* Completed successfully. */
4719 /* The user decided to abort the saving.
4720 If we're writing to a temporary file, remove it.
4721 XXX - should we do so even if we're not writing to a
4723 wtap_dump_close(pdh, &err);
4724 if (fname_new != NULL)
4725 ws_unlink(fname_new);
4726 cf_callback_invoke(cf_cb_file_export_specified_packets_stopped, NULL);
4727 return CF_WRITE_ABORTED;
4731 /* Error while saving.
4732 If we're writing to a temporary file, remove it. */
4733 if (fname_new != NULL)
4734 ws_unlink(fname_new);
4735 wtap_dump_close(pdh, &err);
4739 if (!wtap_dump_close(pdh, &err)) {
4740 cf_close_failure_alert_box(fname, err);
4744 if (fname_new != NULL) {
4745 /* We wrote out to fname_new, and should rename it on top of
4746 fname; fname is now closed, so that should be possible even
4747 on Windows. Do the rename. */
4748 if (ws_rename(fname_new, fname) == -1) {
4749 /* Well, the rename failed. */
4750 cf_rename_failure_alert_box(fname, errno);
4755 cf_callback_invoke(cf_cb_file_export_specified_packets_finished, NULL);
4759 if (fname_new != NULL) {
4760 /* We were trying to write to a temporary file; get rid of it if it
4761 exists. (We don't care whether this fails, as, if it fails,
4762 there's not much we can do about it. I guess if it failed for
4763 a reason other than "it doesn't exist", we could report an
4764 error, so the user knows there's a junk file that they might
4765 want to clean up.) */
4766 ws_unlink(fname_new);
4769 cf_callback_invoke(cf_cb_file_export_specified_packets_failed, NULL);
4770 return CF_WRITE_ERROR;
4774 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
4775 gboolean for_writing, int file_type)
4777 gchar *display_basename;
4780 /* Wiretap error. */
4781 display_basename = g_filename_display_basename(filename);
4784 case WTAP_ERR_NOT_REGULAR_FILE:
4785 simple_error_message_box(
4786 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
4790 case WTAP_ERR_RANDOM_OPEN_PIPE:
4791 /* Seen only when opening a capture file for reading. */
4792 simple_error_message_box(
4793 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.\n"
4794 "To capture from a pipe or FIFO use wireshark -i -",
4798 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
4799 /* Seen only when opening a capture file for reading. */
4800 simple_error_message_box(
4801 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
4805 case WTAP_ERR_UNSUPPORTED:
4806 /* Seen only when opening a capture file for reading. */
4807 simple_error_message_box(
4808 "The file \"%s\" contains record data that Wireshark doesn't support.\n"
4811 err_info != NULL ? err_info : "no information supplied");
4815 case WTAP_ERR_CANT_WRITE_TO_PIPE:
4816 /* Seen only when opening a capture file for writing. */
4817 simple_error_message_box(
4818 "The file \"%s\" is a pipe, and %s capture files can't be "
4819 "written to a pipe.",
4820 display_basename, wtap_file_type_subtype_string(file_type));
4823 case WTAP_ERR_UNWRITABLE_FILE_TYPE:
4824 /* Seen only when opening a capture file for writing. */
4825 simple_error_message_box(
4826 "Wireshark doesn't support writing capture files in that format.");
4829 case WTAP_ERR_UNWRITABLE_ENCAP:
4830 /* Seen only when opening a capture file for writing. */
4831 simple_error_message_box("Wireshark can't save this capture in that format.");
4834 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
4836 simple_error_message_box(
4837 "Wireshark can't save this capture in that format.");
4839 simple_error_message_box(
4840 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
4845 case WTAP_ERR_BAD_FILE:
4846 /* Seen only when opening a capture file for reading. */
4847 simple_error_message_box(
4848 "The file \"%s\" appears to be damaged or corrupt.\n"
4851 err_info != NULL ? err_info : "no information supplied");
4855 case WTAP_ERR_CANT_OPEN:
4857 simple_error_message_box(
4858 "The file \"%s\" could not be created for some unknown reason.",
4861 simple_error_message_box(
4862 "The file \"%s\" could not be opened for some unknown reason.",
4867 case WTAP_ERR_SHORT_READ:
4868 simple_error_message_box(
4869 "The file \"%s\" appears to have been cut short"
4870 " in the middle of a packet or other data.",
4874 case WTAP_ERR_SHORT_WRITE:
4875 simple_error_message_box(
4876 "A full header couldn't be written to the file \"%s\".",
4880 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
4881 simple_error_message_box(
4882 "This file type cannot be written as a compressed file.");
4885 case WTAP_ERR_DECOMPRESS:
4886 simple_error_message_box(
4887 "The compressed file \"%s\" appears to be damaged or corrupt.\n"
4888 "(%s)", display_basename,
4889 err_info != NULL ? err_info : "no information supplied");
4894 simple_error_message_box(
4895 "The file \"%s\" could not be %s: %s.",
4897 for_writing ? "created" : "opened",
4898 wtap_strerror(err));
4901 g_free(display_basename);
4904 open_failure_alert_box(filename, err, for_writing);
4909 * XXX - whether we mention the source pathname, the target pathname,
4910 * or both depends on the error and on what we find if we look for
4911 * one or both of them.
4914 cf_rename_failure_alert_box(const char *filename, int err)
4916 gchar *display_basename;
4918 display_basename = g_filename_display_basename(filename);
4922 /* XXX - should check whether the source exists and, if not,
4923 report it as the problem and, if so, report the destination
4925 simple_error_message_box("The path to the file \"%s\" doesn't exist.",
4930 /* XXX - if we're doing a rename after a safe save, we should
4931 probably say something else. */
4932 simple_error_message_box("You don't have permission to move the capture file to \"%s\".",
4937 /* XXX - this should probably mention both the source and destination
4939 simple_error_message_box("The file \"%s\" could not be moved: %s.",
4940 display_basename, wtap_strerror(err));
4943 g_free(display_basename);
4946 /* Check for write errors - if the file is being written to an NFS server,
4947 a write error may not show up until the file is closed, as NFS clients
4948 might not send writes to the server until the "write()" call finishes,
4949 so that the write may fail on the server but the "write()" may succeed. */
4951 cf_close_failure_alert_box(const char *filename, int err)
4953 gchar *display_basename;
4956 /* Wiretap error. */
4957 display_basename = g_filename_display_basename(filename);
4960 case WTAP_ERR_CANT_CLOSE:
4961 simple_error_message_box(
4962 "The file \"%s\" couldn't be closed for some unknown reason.",
4966 case WTAP_ERR_SHORT_WRITE:
4967 simple_error_message_box(
4968 "Not all the packets could be written to the file \"%s\".",
4973 simple_error_message_box(
4974 "An error occurred while closing the file \"%s\": %s.",
4975 display_basename, wtap_strerror(err));
4978 g_free(display_basename);
4981 We assume that a close error from the OS is really a write error. */
4982 write_failure_alert_box(filename, err);
4986 /* Reload the current capture file. */
4988 cf_reload(capture_file *cf) {
4990 gboolean is_tempfile;
4993 /* If the file could be opened, "cf_open()" calls "cf_close()"
4994 to get rid of state for the old capture file before filling in state
4995 for the new capture file. "cf_close()" will remove the file if
4996 it's a temporary file; we don't want that to happen (for one thing,
4997 it'd prevent subsequent reopens from working). Remember whether it's
4998 a temporary file, mark it as not being a temporary file, and then
4999 reopen it as the type of file it was.
5001 Also, "cf_close()" will free "cf->filename", so we must make
5002 a copy of it first. */
5003 filename = g_strdup(cf->filename);
5004 is_tempfile = cf->is_tempfile;
5005 cf->is_tempfile = FALSE;
5006 if (cf_open(cf, filename, cf->open_type, is_tempfile, &err) == CF_OK) {
5007 switch (cf_read(cf, TRUE)) {
5011 /* Just because we got an error, that doesn't mean we were unable
5012 to read any of the file; we handle what we could get from the
5016 case CF_READ_ABORTED:
5017 /* The user bailed out of re-reading the capture file; the
5018 capture file has been closed - just free the capture file name
5019 string and return (without changing the last containing
5025 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
5026 Instead, the file was left open, so we should restore "cf->is_tempfile"
5029 XXX - change the menu? Presumably "cf_open()" will do that;
5030 make sure it does! */
5031 cf->is_tempfile = is_tempfile;
5033 /* "cf_open()" made a copy of the file name we handed it, so
5034 we should free up our copy. */
5044 * indent-tabs-mode: nil
5047 * ex: set shiftwidth=2 tabstop=8 expandtab:
5048 * :indentSize=2:tabSize=8:noTabs=true: