6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #ifdef NEED_STRERROR_H
50 #include <epan/epan.h>
51 #include <epan/filesystem.h>
54 #include "color_filters.h"
55 #include <epan/column.h>
56 #include <epan/packet.h>
57 #include "packet-range.h"
63 #include "alert_box.h"
64 #include "simple_dialog.h"
65 #include "progress_dlg.h"
67 #include <epan/prefs.h>
68 #include <epan/dfilter/dfilter.h>
69 #include <epan/conversation.h>
70 #include <epan/epan_dissect.h>
72 #include "stat_menu.h"
73 #include "tap_dfilter_dlg.h"
74 #include <epan/dissectors/packet-data.h>
75 #include <epan/dissectors/packet-ber.h>
76 #include <epan/timestamp.h>
77 #include "file_util.h"
82 gboolean auto_scroll_live;
85 static nstime_t first_ts;
86 static nstime_t prev_ts;
87 static guint32 cum_bytes = 0;
89 static void cf_reset_state(capture_file *cf);
91 static int read_packet(capture_file *cf, dfilter_t *dfcode, gint64 offset);
93 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
94 gboolean refilter, gboolean redissect);
96 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
98 static void match_subtree_text(proto_node *node, gpointer data);
99 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
101 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
103 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
105 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
107 static gboolean match_binary(capture_file *cf, frame_data *fdata,
109 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
111 static gboolean find_packet(capture_file *cf,
112 gboolean (*match_function)(capture_file *, frame_data *, void *),
115 static void cf_open_failure_alert_box(const char *filename, int err,
116 gchar *err_info, gboolean for_writing,
118 static const char *file_rename_error_message(int err);
119 static void cf_write_failure_alert_box(const char *filename, int err);
120 static void cf_close_failure_alert_box(const char *filename, int err);
121 static gboolean copy_binary_file(const char *from_filename, const char *to_filename);
123 /* Update the progress bar this many times when reading a file. */
124 #define N_PROGBAR_UPDATES 100
126 /* Number of "frame_data" structures per memory chunk.
127 XXX - is this the right number? */
128 #define FRAME_DATA_CHUNK_SIZE 1024
131 /* one callback for now, we could have a list later */
132 static cf_callback_t cf_cb = NULL;
133 static gpointer cf_cb_user_data = NULL;
136 cf_callback_invoke(int event, gpointer data)
138 g_assert(cf_cb != NULL);
139 cf_cb(event, data, cf_cb_user_data);
144 cf_callback_add(cf_callback_t func, gpointer user_data)
146 /* More than one callback listener is currently not implemented,
147 but should be easy to do. */
148 g_assert(cf_cb == NULL);
150 cf_cb_user_data = user_data;
154 cf_callback_remove(cf_callback_t func _U_)
156 g_assert(cf_cb != NULL);
158 cf_cb_user_data = NULL;
162 cf_timestamp_auto_precision(capture_file *cf)
164 int prec = timestamp_get_precision();
167 /* don't try to get the file's precision if none is opened */
168 if(cf->state == FILE_CLOSED) {
172 /* if we are in auto mode, set precision of current file */
173 if(prec == TS_PREC_AUTO ||
174 prec == TS_PREC_AUTO_SEC ||
175 prec == TS_PREC_AUTO_DSEC ||
176 prec == TS_PREC_AUTO_CSEC ||
177 prec == TS_PREC_AUTO_MSEC ||
178 prec == TS_PREC_AUTO_USEC ||
179 prec == TS_PREC_AUTO_NSEC)
181 switch(wtap_file_tsprecision(cf->wth)) {
182 case(WTAP_FILE_TSPREC_SEC):
183 timestamp_set_precision(TS_PREC_AUTO_SEC);
185 case(WTAP_FILE_TSPREC_DSEC):
186 timestamp_set_precision(TS_PREC_AUTO_DSEC);
188 case(WTAP_FILE_TSPREC_CSEC):
189 timestamp_set_precision(TS_PREC_AUTO_CSEC);
191 case(WTAP_FILE_TSPREC_MSEC):
192 timestamp_set_precision(TS_PREC_AUTO_MSEC);
194 case(WTAP_FILE_TSPREC_USEC):
195 timestamp_set_precision(TS_PREC_AUTO_USEC);
197 case(WTAP_FILE_TSPREC_NSEC):
198 timestamp_set_precision(TS_PREC_AUTO_NSEC);
201 g_assert_not_reached();
208 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
213 wth = wtap_open_offline(fname, err, &err_info, TRUE);
217 /* The open succeeded. Close whatever capture file we had open,
218 and fill in the information for this file. */
221 /* Initialize all data structures used for dissection. */
224 /* We're about to start reading the file. */
225 cf->state = FILE_READ_IN_PROGRESS;
230 /* Set the file name because we need it to set the follow stream filter.
231 XXX - is that still true? We need it for other reasons, though,
233 cf->filename = g_strdup(fname);
235 /* Indicate whether it's a permanent or temporary file. */
236 cf->is_tempfile = is_tempfile;
238 /* If it's a temporary capture buffer file, mark it as not saved. */
239 cf->user_saved = !is_tempfile;
241 cf->cd_t = wtap_file_type(cf->wth);
243 cf->displayed_count = 0;
244 cf->marked_count = 0;
245 cf->drops_known = FALSE;
247 cf->snap = wtap_snapshot_length(cf->wth);
249 /* Snapshot length not known. */
250 cf->has_snap = FALSE;
251 cf->snap = WTAP_MAX_PACKET_SIZE;
254 nstime_set_zero(&cf->elapsed_time);
255 nstime_set_zero(&first_ts);
256 nstime_set_zero(&prev_ts);
258 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
260 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
262 g_assert(cf->plist_chunk);
264 /* change the time formats now, as we might have a new precision */
265 cf_change_time_formats(cf);
267 fileset_file_opened(fname);
269 if(cf->cd_t == WTAP_FILE_BER) {
270 /* tell the BER dissector the file name */
271 ber_set_filename(cf->filename);
277 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
283 * Reset the state for the currently closed file, but don't do the
284 * UI callbacks; this is for use in "cf_open()", where we don't
285 * want the UI to go from "file open" to "file closed" back to
286 * "file open", we want it to go from "old file open" to "new file
287 * open and being read".
290 cf_reset_state(capture_file *cf)
292 /* Die if we're in the middle of reading a file. */
293 g_assert(cf->state != FILE_READ_IN_PROGRESS);
299 /* We have no file open... */
300 if (cf->filename != NULL) {
301 /* If it's a temporary file, remove it. */
303 eth_unlink(cf->filename);
304 g_free(cf->filename);
307 /* ...which means we have nothing to save. */
308 cf->user_saved = FALSE;
310 if (cf->plist_chunk != NULL) {
311 g_mem_chunk_destroy(cf->plist_chunk);
312 cf->plist_chunk = NULL;
314 if (cf->rfcode != NULL) {
315 dfilter_free(cf->rfcode);
319 cf->plist_end = NULL;
320 cf_unselect_packet(cf); /* nothing to select */
321 cf->first_displayed = NULL;
322 cf->last_displayed = NULL;
324 /* No frame selected, no field in that frame selected. */
325 cf->current_frame = NULL;
326 cf->finfo_selected = NULL;
328 /* Clear the packet list. */
329 packet_list_freeze();
335 nstime_set_zero(&cf->elapsed_time);
337 reset_tap_listeners();
339 /* We have no file open. */
340 cf->state = FILE_CLOSED;
342 fileset_file_closed();
345 /* Reset everything to a pristine state */
347 cf_close(capture_file *cf)
349 /* do GUI things even if file is already closed,
350 * e.g. to cleanup things if a capture couldn't be started */
351 cf_callback_invoke(cf_cb_file_closing, cf);
353 /* close things, if not already closed before */
354 if(cf->state != FILE_CLOSED) {
356 color_filters_cleanup();
360 cleanup_dissection();
363 cf_callback_invoke(cf_cb_file_closed, cf);
367 cf_read(capture_file *cf)
371 const gchar *name_ptr;
373 char errmsg_errno[1024+1];
374 gchar err_str[2048+1];
376 progdlg_t *progbar = NULL;
378 gint64 size, file_pos;
381 gchar status_str[100];
382 gint64 progbar_nextstep;
383 gint64 progbar_quantum;
386 /* Compile the current display filter.
387 * We assume this will not fail since cf->dfilter is only set in
388 * cf_filter IFF the filter was valid.
392 dfilter_compile(cf->dfilter, &dfcode);
397 reset_tap_listeners();
398 tap_dfilter_dlg_update();
400 cf_callback_invoke(cf_cb_file_read_start, cf);
402 name_ptr = get_basename(cf->filename);
404 /* Find the size of the file. */
405 size = wtap_file_size(cf->wth, NULL);
407 /* Update the progress bar when it gets to this value. */
408 progbar_nextstep = 0;
409 /* When we reach the value that triggers a progress bar update,
410 bump that value by this amount. */
412 progbar_quantum = size/N_PROGBAR_UPDATES;
415 /* Progress so far. */
418 packet_list_freeze();
421 g_get_current_time(&start_time);
423 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
425 /* Create the progress bar if necessary.
426 We check on every iteration of the loop, so that it takes no
427 longer than the standard time to create it (otherwise, for a
428 large file, we might take considerably longer than that standard
429 time in order to get to the next progress bar step). */
430 if (progbar == NULL) {
431 progbar = delayed_create_progress_dlg("Loading", name_ptr,
432 TRUE, &stop_flag, &start_time, progbar_val);
435 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
436 when we update it, we have to run the GTK+ main loop to get it
437 to repaint what's pending, and doing so may involve an "ioctl()"
438 to see if there's any pending input from an X server, and doing
439 that for every packet can be costly, especially on a big file. */
440 if (data_offset >= progbar_nextstep) {
441 file_pos = wtap_read_so_far(cf->wth, NULL);
442 progbar_val = (gfloat) file_pos / (gfloat) size;
443 if (progbar_val > 1.0) {
444 /* The file probably grew while we were reading it.
445 Update file size, and try again. */
446 size = wtap_file_size(cf->wth, NULL);
448 progbar_val = (gfloat) file_pos / (gfloat) size;
449 /* If it's still > 1, either "wtap_file_size()" failed (in which
450 case there's not much we can do about it), or the file
451 *shrank* (in which case there's not much we can do about
452 it); just clip the progress value at 1.0. */
453 if (progbar_val > 1.0)
456 if (progbar != NULL) {
457 /* update the packet lists content */
459 if (auto_scroll_live && cf->plist_end != NULL)
460 packet_list_moveto_end();
461 packet_list_freeze();
463 g_snprintf(status_str, sizeof(status_str),
464 "%" PRId64 "KB of %" PRId64 "KB",
465 file_pos / 1024, size / 1024);
466 update_progress_dlg(progbar, progbar_val, status_str);
468 progbar_nextstep += progbar_quantum;
473 /* Well, the user decided to abort the read. He/She will be warned and
474 it might be enough for him/her to work with the already loaded
476 This is especially true for very large capture files, where you don't
477 want to wait loading the whole file (which may last minutes or even
478 hours even on fast machines) just to see that it was the wrong file. */
481 read_packet(cf, dfcode, data_offset);
484 /* Cleanup and release all dfilter resources */
486 dfilter_free(dfcode);
489 /* We're done reading the file; destroy the progress bar if it was created. */
491 destroy_progress_dlg(progbar);
493 /* We're done reading sequentially through the file. */
494 cf->state = FILE_READ_DONE;
496 /* Close the sequential I/O side, to free up memory it requires. */
497 wtap_sequential_close(cf->wth);
499 /* Allow the protocol dissectors to free up memory that they
500 * don't need after the sequential run-through of the packets. */
501 postseq_cleanup_all_protocols();
503 /* Set the file encapsulation type now; we don't know what it is until
504 we've looked at all the packets, as we don't know until then whether
505 there's more than one type (and thus whether it's
506 WTAP_ENCAP_PER_PACKET). */
507 cf->lnk_t = wtap_file_encap(cf->wth);
509 cf->current_frame = cf->first_displayed;
512 cf_callback_invoke(cf_cb_file_read_finished, cf);
514 /* If we have any displayed packets to select, select the first of those
515 packets by making the first row the selected row. */
516 if (cf->first_displayed != NULL)
517 packet_list_select_row(0);
520 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
521 "%sFile loading was cancelled!%s\n"
523 "The remaining packets in the file were discarded.\n"
525 "As a lot of packets from the original file will be missing,\n"
526 "remember to be careful when saving the current content to a file.\n",
527 simple_dialog_primary_start(), simple_dialog_primary_end());
528 return CF_READ_ERROR;
532 /* Put up a message box noting that the read failed somewhere along
533 the line. Don't throw out the stuff we managed to read, though,
537 case WTAP_ERR_UNSUPPORTED_ENCAP:
538 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
539 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
542 errmsg = errmsg_errno;
545 case WTAP_ERR_CANT_READ:
546 errmsg = "An attempt to read from the capture file failed for"
547 " some unknown reason.";
550 case WTAP_ERR_SHORT_READ:
551 errmsg = "The capture file appears to have been cut short"
552 " in the middle of a packet.";
555 case WTAP_ERR_BAD_RECORD:
556 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
557 "The capture file appears to be damaged or corrupt.\n(%s)",
560 errmsg = errmsg_errno;
564 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
565 "An error occurred while reading the"
566 " capture file: %s.", wtap_strerror(err));
567 errmsg = errmsg_errno;
570 g_snprintf(err_str, sizeof err_str, errmsg);
571 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
572 return CF_READ_ERROR;
579 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
581 cf_status_t cf_status;
583 cf_status = cf_open(cf, fname, is_tempfile, err);
588 cf_continue_tail(capture_file *cf, int to_read, int *err)
590 gint64 data_offset = 0;
592 int newly_displayed_packets = 0;
595 /* Compile the current display filter.
596 * We assume this will not fail since cf->dfilter is only set in
597 * cf_filter IFF the filter was valid.
601 dfilter_compile(cf->dfilter, &dfcode);
606 packet_list_freeze();
608 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
610 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
611 if (cf->state == FILE_READ_ABORTED) {
612 /* Well, the user decided to exit Wireshark. Break out of the
613 loop, and let the code below (which is called even if there
614 aren't any packets left to read) exit. */
617 if (read_packet(cf, dfcode, data_offset) != -1) {
618 newly_displayed_packets++;
623 /* Cleanup and release all dfilter resources */
625 dfilter_free(dfcode);
628 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
629 cf->count, cf->state, *err);*/
631 /* XXX - this causes "flickering" of the list */
634 /* moving to the end of the packet list - if the user requested so and
635 we have some new packets.
636 this doesn't seem to work well with a frozen GTK_Clist, so do this after
637 packet_list_thaw() is done, see bugzilla 1188 */
638 /* XXX - this cheats and looks inside the packet list to find the final
640 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
641 packet_list_moveto_end();
643 if (cf->state == FILE_READ_ABORTED) {
644 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
645 so that our caller can kill off the capture child process;
646 this will cause an EOF on the pipe from the child, so
647 "cf_finish_tail()" will be called, and it will clean up
649 return CF_READ_ABORTED;
650 } else if (*err != 0) {
651 /* We got an error reading the capture file.
652 XXX - pop up a dialog box instead? */
653 g_warning("Error \"%s\" while reading: \"%s\"\n",
654 wtap_strerror(*err), cf->filename);
656 return CF_READ_ERROR;
662 cf_finish_tail(capture_file *cf, int *err)
668 /* Compile the current display filter.
669 * We assume this will not fail since cf->dfilter is only set in
670 * cf_filter IFF the filter was valid.
674 dfilter_compile(cf->dfilter, &dfcode);
677 if(cf->wth == NULL) {
679 return CF_READ_ERROR;
682 packet_list_freeze();
684 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
685 if (cf->state == FILE_READ_ABORTED) {
686 /* Well, the user decided to abort the read. Break out of the
687 loop, and let the code below (which is called even if there
688 aren't any packets left to read) exit. */
691 read_packet(cf, dfcode, data_offset);
694 /* Cleanup and release all dfilter resources */
696 dfilter_free(dfcode);
701 if (cf->state == FILE_READ_ABORTED) {
702 /* Well, the user decided to abort the read. We're only called
703 when the child capture process closes the pipe to us (meaning
704 it's probably exited), so we can just close the capture
705 file; we return CF_READ_ABORTED so our caller can do whatever
706 is appropriate when that happens. */
708 return CF_READ_ABORTED;
711 if (auto_scroll_live && cf->plist_end != NULL)
712 /* XXX - this cheats and looks inside the packet list to find the final
714 packet_list_moveto_end();
716 /* We're done reading sequentially through the file. */
717 cf->state = FILE_READ_DONE;
719 /* We're done reading sequentially through the file; close the
720 sequential I/O side, to free up memory it requires. */
721 wtap_sequential_close(cf->wth);
723 /* Allow the protocol dissectors to free up memory that they
724 * don't need after the sequential run-through of the packets. */
725 postseq_cleanup_all_protocols();
727 /* Set the file encapsulation type now; we don't know what it is until
728 we've looked at all the packets, as we don't know until then whether
729 there's more than one type (and thus whether it's
730 WTAP_ENCAP_PER_PACKET). */
731 cf->lnk_t = wtap_file_encap(cf->wth);
734 /* We got an error reading the capture file.
735 XXX - pop up a dialog box? */
736 return CF_READ_ERROR;
741 #endif /* HAVE_LIBPCAP */
744 cf_get_display_name(capture_file *cf)
746 const gchar *displayname;
748 /* Return a name to use in displays */
749 if (!cf->is_tempfile) {
750 /* Get the last component of the file name, and use that. */
752 displayname = get_basename(cf->filename);
754 displayname="(No file)";
757 /* The file we read is a temporary file from a live capture;
758 we don't mention its name. */
759 displayname = "(Untitled)";
764 /* XXX - use a macro instead? */
766 cf_get_packet_count(capture_file *cf)
771 /* XXX - use a macro instead? */
773 cf_set_packet_count(capture_file *cf, int packet_count)
775 cf->count = packet_count;
778 /* XXX - use a macro instead? */
780 cf_is_tempfile(capture_file *cf)
782 return cf->is_tempfile;
785 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
787 cf->is_tempfile = is_tempfile;
791 /* XXX - use a macro instead? */
792 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
794 cf->drops_known = drops_known;
797 /* XXX - use a macro instead? */
798 void cf_set_drops(capture_file *cf, guint32 drops)
803 /* XXX - use a macro instead? */
804 gboolean cf_get_drops_known(capture_file *cf)
806 return cf->drops_known;
809 /* XXX - use a macro instead? */
810 guint32 cf_get_drops(capture_file *cf)
815 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
821 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
823 union wtap_pseudo_header *pseudo_header, const guchar *buf,
827 gboolean create_proto_tree = FALSE;
830 /* just add some value here until we know if it is being displayed or not */
831 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
833 /* If we don't have the time stamp of the first packet in the
834 capture, it's because this is the first packet. Save the time
835 stamp of this packet as the time stamp of the first packet. */
836 if (nstime_is_zero(&first_ts)) {
837 first_ts = fdata->abs_ts;
839 /* if this frames is marked as a reference time frame, reset
840 firstsec and firstusec to this frame */
841 if(fdata->flags.ref_time){
842 first_ts = fdata->abs_ts;
845 /* If we don't have the time stamp of the previous displayed packet,
846 it's because this is the first displayed packet. Save the time
847 stamp of this packet as the time stamp of the previous displayed
849 if (nstime_is_zero(&prev_ts)) {
850 prev_ts = fdata->abs_ts;
853 /* Get the time elapsed between the first packet and this packet. */
854 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
856 /* If it's greater than the current elapsed time, set the elapsed time
857 to it (we check for "greater than" so as not to be confused by
858 time moving backwards). */
859 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
860 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
861 cf->elapsed_time = fdata->rel_ts;
864 /* Get the time elapsed between the previous displayed packet and
866 nstime_delta(&fdata->del_ts, &fdata->abs_ts, &prev_ts);
870 we have a display filter and are re-applying it;
872 we have a list of color filters;
874 we have tap listeners;
876 allocate a protocol tree root node, so that we'll construct
877 a protocol tree against which a filter expression can be
879 if ((dfcode != NULL && refilter) || color_filters_used()
880 || num_tap_filters != 0)
881 create_proto_tree = TRUE;
883 /* Dissect the frame. */
884 edt = epan_dissect_new(create_proto_tree, FALSE);
886 if (dfcode != NULL && refilter) {
887 epan_dissect_prime_dfilter(edt, dfcode);
889 /* prepare color filters */
890 if (color_filters_used()) {
891 color_filters_prime_edt(edt);
894 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
895 tap_push_tapped_queue(edt);
897 /* If we have a display filter, apply it if we're refiltering, otherwise
898 leave the "passed_dfilter" flag alone.
900 If we don't have a display filter, set "passed_dfilter" to 1. */
901 if (dfcode != NULL) {
903 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
906 fdata->flags.passed_dfilter = 1;
908 if( (fdata->flags.passed_dfilter)
909 || (edt->pi.fd->flags.ref_time) ){
910 /* This frame either passed the display filter list or is marked as
911 a time reference frame. All time reference frames are displayed
912 even if they dont pass the display filter */
913 /* if this was a TIME REF frame we should reset the cul bytes field */
914 if(edt->pi.fd->flags.ref_time){
915 cum_bytes = fdata->pkt_len;
916 fdata->cum_bytes = cum_bytes;
919 /* increase cum_bytes with this packets length */
920 cum_bytes += fdata->pkt_len;
922 epan_dissect_fill_in_columns(edt);
924 /* If we haven't yet seen the first frame, this is it.
926 XXX - we must do this before we add the row to the display,
927 as, if the display's GtkCList's selection mode is
928 GTK_SELECTION_BROWSE, when the first entry is added to it,
929 "cf_select_packet()" will be called, and it will fetch the row
930 data for the 0th row, and will get a null pointer rather than
931 "fdata", as "gtk_clist_append()" won't yet have returned and
932 thus "gtk_clist_set_row_data()" won't yet have been called.
934 We thus need to leave behind bread crumbs so that
935 "cf_select_packet()" can find this frame. See the comment
936 in "cf_select_packet()". */
937 if (cf->first_displayed == NULL)
938 cf->first_displayed = fdata;
940 /* This is the last frame we've seen so far. */
941 cf->last_displayed = fdata;
943 row = packet_list_append(cf->cinfo.col_data, fdata);
945 /* colorize packet: if packet is marked, use preferences,
946 otherwise try to apply color filters */
947 if (fdata->flags.marked) {
948 fdata->color_filter = NULL;
949 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
951 fdata->color_filter = color_filters_colorize_packet(row, edt);
954 /* Set the time of the previous displayed frame to the time of this
956 prev_ts = fdata->abs_ts;
958 cf->displayed_count++;
960 /* This frame didn't pass the display filter, so it's not being added
961 to the clist, and thus has no row. */
964 epan_dissect_free(edt);
968 /* read in a new packet */
969 /* returns the row of the new packet in the packet list or -1 if not displayed */
971 read_packet(capture_file *cf, dfilter_t *dfcode, gint64 offset)
973 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
974 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
975 const guchar *buf = wtap_buf_ptr(cf->wth);
978 frame_data *plist_end;
982 /* Allocate the next list entry, and add it to the list. */
983 fdata = g_mem_chunk_alloc(cf->plist_chunk);
989 fdata->pkt_len = phdr->len;
990 fdata->cap_len = phdr->caplen;
991 fdata->file_off = offset;
992 fdata->lnk_t = phdr->pkt_encap;
993 fdata->flags.encoding = CHAR_ASCII;
994 fdata->flags.visited = 0;
995 fdata->flags.marked = 0;
996 fdata->flags.ref_time = 0;
997 fdata->color_filter = NULL;
999 fdata->abs_ts = *((nstime_t *) &phdr->ts);
1003 edt = epan_dissect_new(TRUE, FALSE);
1004 epan_dissect_prime_dfilter(edt, cf->rfcode);
1005 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
1006 passed = dfilter_apply_edt(cf->rfcode, edt);
1007 epan_dissect_free(edt);
1010 plist_end = cf->plist_end;
1011 fdata->prev = plist_end;
1012 if (plist_end != NULL)
1013 plist_end->next = fdata;
1016 cf->plist_end = fdata;
1019 cf->f_datalen = offset + phdr->caplen;
1020 fdata->num = cf->count;
1021 row = add_packet_to_packet_list(fdata, cf, dfcode, pseudo_header, buf, TRUE);
1023 /* XXX - if we didn't have read filters, or if we could avoid
1024 allocating the "frame_data" structure until we knew whether
1025 the frame passed the read filter, we could use a G_ALLOC_ONLY
1028 ...but, at least in one test I did, where I just made the chunk
1029 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1030 seem to save a noticeable amount of time or space. */
1031 g_mem_chunk_free(cf->plist_chunk, fdata);
1038 cf_merge_files(char **out_filenamep, int in_file_count,
1039 char *const *in_filenames, int file_type, gboolean do_append)
1041 merge_in_file_t *in_files;
1044 char tmpname[128+1];
1047 int open_err, read_err, write_err, close_err;
1051 char errmsg_errno[1024+1];
1052 gchar err_str[2048+1];
1054 gboolean got_read_error = FALSE, got_write_error = FALSE;
1056 progdlg_t *progbar = NULL;
1058 gint64 f_len, file_pos;
1060 GTimeVal start_time;
1061 gchar status_str[100];
1062 gint64 progbar_nextstep;
1063 gint64 progbar_quantum;
1065 /* open the input files */
1066 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1067 &open_err, &err_info, &err_fileno)) {
1069 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1074 if (*out_filenamep != NULL) {
1075 out_filename = *out_filenamep;
1076 out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1080 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
1083 out_filename = g_strdup(tmpname);
1084 *out_filenamep = out_filename;
1088 merge_close_in_files(in_file_count, in_files);
1090 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1094 pdh = wtap_dump_fdopen(out_fd, file_type,
1095 merge_select_frame_type(in_file_count, in_files),
1096 merge_max_snapshot_length(in_file_count, in_files),
1097 FALSE /* compressed */, &open_err);
1100 merge_close_in_files(in_file_count, in_files);
1102 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1107 /* Get the sum of the sizes of all the files. */
1109 for (i = 0; i < in_file_count; i++)
1110 f_len += in_files[i].size;
1112 /* Update the progress bar when it gets to this value. */
1113 progbar_nextstep = 0;
1114 /* When we reach the value that triggers a progress bar update,
1115 bump that value by this amount. */
1116 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1117 /* Progress so far. */
1121 g_get_current_time(&start_time);
1123 /* do the merge (or append) */
1126 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1129 wth = merge_read_packet(in_file_count, in_files, &read_err,
1133 got_read_error = TRUE;
1137 /* Get the sum of the data offsets in all of the files. */
1139 for (i = 0; i < in_file_count; i++)
1140 data_offset += in_files[i].data_offset;
1142 /* Create the progress bar if necessary.
1143 We check on every iteration of the loop, so that it takes no
1144 longer than the standard time to create it (otherwise, for a
1145 large file, we might take considerably longer than that standard
1146 time in order to get to the next progress bar step). */
1147 if (progbar == NULL) {
1148 progbar = delayed_create_progress_dlg("Merging", "files",
1149 FALSE, &stop_flag, &start_time, progbar_val);
1152 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1153 when we update it, we have to run the GTK+ main loop to get it
1154 to repaint what's pending, and doing so may involve an "ioctl()"
1155 to see if there's any pending input from an X server, and doing
1156 that for every packet can be costly, especially on a big file. */
1157 if (data_offset >= progbar_nextstep) {
1158 /* Get the sum of the seek positions in all of the files. */
1160 for (i = 0; i < in_file_count; i++)
1161 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1162 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1163 if (progbar_val > 1.0) {
1164 /* Some file probably grew while we were reading it.
1165 That "shouldn't happen", so we'll just clip the progress
1169 if (progbar != NULL) {
1170 g_snprintf(status_str, sizeof(status_str),
1171 "%" PRId64 "KB of %" PRId64 "KB",
1172 file_pos / 1024, f_len / 1024);
1173 update_progress_dlg(progbar, progbar_val, status_str);
1175 progbar_nextstep += progbar_quantum;
1179 /* Well, the user decided to abort the merge. */
1183 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1184 wtap_buf_ptr(wth), &write_err)) {
1185 got_write_error = TRUE;
1190 /* We're done merging the files; destroy the progress bar if it was created. */
1191 if (progbar != NULL)
1192 destroy_progress_dlg(progbar);
1194 merge_close_in_files(in_file_count, in_files);
1195 if (!got_read_error && !got_write_error) {
1196 if (!wtap_dump_close(pdh, &write_err))
1197 got_write_error = TRUE;
1199 wtap_dump_close(pdh, &close_err);
1201 if (got_read_error) {
1203 * Find the file on which we got the error, and report the error.
1205 for (i = 0; i < in_file_count; i++) {
1206 if (in_files[i].state == GOT_ERROR) {
1207 /* Put up a message box noting that a read failed somewhere along
1211 case WTAP_ERR_UNSUPPORTED_ENCAP:
1212 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1213 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1216 errmsg = errmsg_errno;
1219 case WTAP_ERR_CANT_READ:
1220 errmsg = "An attempt to read from the capture file %s failed for"
1221 " some unknown reason.";
1224 case WTAP_ERR_SHORT_READ:
1225 errmsg = "The capture file %s appears to have been cut short"
1226 " in the middle of a packet.";
1229 case WTAP_ERR_BAD_RECORD:
1230 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1231 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1234 errmsg = errmsg_errno;
1238 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1239 "An error occurred while reading the"
1240 " capture file %%s: %s.", wtap_strerror(read_err));
1241 errmsg = errmsg_errno;
1244 g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
1245 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
1250 if (got_write_error) {
1251 /* Put up an alert box for the write error. */
1252 cf_write_failure_alert_box(out_filename, write_err);
1255 if (got_read_error || got_write_error || stop_flag) {
1256 /* Callers aren't expected to treat an error or an explicit abort
1257 differently - we put up error dialogs ourselves, so they don't
1265 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1267 const char *filter_new = dftext ? dftext : "";
1268 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1271 /* if new filter equals old one, do nothing unless told to do so */
1272 if (!force && strcmp(filter_new, filter_old) == 0) {
1278 if (dftext == NULL) {
1279 /* The new filter is an empty filter (i.e., display all packets).
1280 * so leave dfcode==NULL
1284 * We have a filter; make a copy of it (as we'll be saving it),
1285 * and try to compile it.
1287 dftext = g_strdup(dftext);
1288 if (!dfilter_compile(dftext, &dfcode)) {
1289 /* The attempt failed; report an error. */
1290 gchar *safe_dftext = simple_dialog_format_message(dftext);
1291 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1293 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1296 "The following display filter isn't a valid display filter:\n%s\n"
1297 "See the help for a description of the display filter syntax.",
1298 simple_dialog_primary_start(), safe_dfilter_error_msg,
1299 simple_dialog_primary_end(), safe_dftext);
1300 g_free(safe_dfilter_error_msg);
1301 g_free(safe_dftext);
1307 if (dfcode == NULL) {
1308 /* Yes - free the filter text, and set it to null. */
1314 /* We have a valid filter. Replace the current filter. */
1315 if (cf->dfilter != NULL)
1316 g_free(cf->dfilter);
1317 cf->dfilter = dftext;
1319 /* Now rescan the packet list, applying the new filter, but not
1320 throwing away information constructed on a previous pass. */
1321 if (dftext == NULL) {
1322 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1324 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1327 /* Cleanup and release all dfilter resources */
1328 if (dfcode != NULL){
1329 dfilter_free(dfcode);
1335 cf_colorize_packets(capture_file *cf)
1337 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1341 cf_reftime_packets(capture_file *cf)
1343 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1347 cf_redissect_packets(capture_file *cf)
1349 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1352 /* Rescan the list of packets, reconstructing the CList.
1354 "action" describes why we're doing this; it's used in the progress
1357 "action_item" describes what we're doing; it's used in the progress
1360 "refilter" is TRUE if we need to re-evaluate the filter expression.
1362 "redissect" is TRUE if we need to make the dissectors reconstruct
1363 any state information they have (because a preference that affects
1364 some dissector has changed, meaning some dissector might construct
1365 its state differently from the way it was constructed the last time). */
1367 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1368 gboolean refilter, gboolean redissect)
1371 progdlg_t *progbar = NULL;
1376 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1377 int selected_row, prev_row, preceding_row, following_row;
1378 gboolean selected_frame_seen;
1381 GTimeVal start_time;
1382 gchar status_str[100];
1383 int progbar_nextstep;
1384 int progbar_quantum;
1387 /* Compile the current display filter.
1388 * We assume this will not fail since cf->dfilter is only set in
1389 * cf_filter IFF the filter was valid.
1393 dfilter_compile(cf->dfilter, &dfcode);
1397 reset_tap_listeners();
1398 /* Which frame, if any, is the currently selected frame?
1399 XXX - should the selected frame or the focus frame be the "current"
1400 frame, that frame being the one from which "Find Frame" searches
1402 selected_frame = cf->current_frame;
1404 /* We don't yet know what row that frame will be on, if any, after we
1405 rebuild the clist, however. */
1409 /* We need to re-initialize all the state information that protocols
1410 keep, because some preference that controls a dissector has changed,
1411 which might cause the state information to be constructed differently
1412 by that dissector. */
1414 /* Initialize all data structures used for dissection. */
1418 /* Freeze the packet list while we redo it, so we don't get any
1419 screen updates while it happens. */
1420 packet_list_freeze();
1423 packet_list_clear();
1425 /* We don't yet know which will be the first and last frames displayed. */
1426 cf->first_displayed = NULL;
1427 cf->last_displayed = NULL;
1429 /* We currently don't display any packets */
1430 cf->displayed_count = 0;
1432 /* Iterate through the list of frames. Call a routine for each frame
1433 to check whether it should be displayed and, if so, add it to
1434 the display list. */
1435 nstime_set_zero(&first_ts);
1436 nstime_set_zero(&prev_ts);
1438 /* Update the progress bar when it gets to this value. */
1439 progbar_nextstep = 0;
1440 /* When we reach the value that triggers a progress bar update,
1441 bump that value by this amount. */
1442 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1443 /* Count of packets at which we've looked. */
1445 /* Progress so far. */
1449 g_get_current_time(&start_time);
1451 row = -1; /* no previous row yet */
1456 preceding_frame = NULL;
1458 following_frame = NULL;
1460 selected_frame_seen = FALSE;
1462 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1463 /* Create the progress bar if necessary.
1464 We check on every iteration of the loop, so that it takes no
1465 longer than the standard time to create it (otherwise, for a
1466 large file, we might take considerably longer than that standard
1467 time in order to get to the next progress bar step). */
1468 if (progbar == NULL)
1469 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1470 &stop_flag, &start_time,
1473 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1474 when we update it, we have to run the GTK+ main loop to get it
1475 to repaint what's pending, and doing so may involve an "ioctl()"
1476 to see if there's any pending input from an X server, and doing
1477 that for every packet can be costly, especially on a big file. */
1478 if (count >= progbar_nextstep) {
1479 /* let's not divide by zero. I should never be started
1480 * with count == 0, so let's assert that
1482 g_assert(cf->count > 0);
1483 progbar_val = (gfloat) count / cf->count;
1485 if (progbar != NULL) {
1486 g_snprintf(status_str, sizeof(status_str),
1487 "%4u of %u frames", count, cf->count);
1488 update_progress_dlg(progbar, progbar_val, status_str);
1491 progbar_nextstep += progbar_quantum;
1495 /* Well, the user decided to abort the filtering. Just stop.
1497 XXX - go back to the previous filter? Users probably just
1498 want not to wait for a filtering operation to finish;
1499 unless we cancel by having no filter, reverting to the
1500 previous filter will probably be even more expensive than
1501 continuing the filtering, as it involves going back to the
1502 beginning and filtering, and even with no filter we currently
1503 have to re-generate the entire clist, which is also expensive.
1505 I'm not sure what Network Monitor does, but it doesn't appear
1506 to give you an unfiltered display if you cancel. */
1513 /* Since all state for the frame was destroyed, mark the frame
1514 * as not visited, free the GSList referring to the state
1515 * data (the per-frame data itself was freed by
1516 * "init_dissection()"), and null out the GSList pointer. */
1517 fdata->flags.visited = 0;
1519 g_slist_free(fdata->pfd);
1524 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1525 cf->pd, fdata->cap_len, &err, &err_info)) {
1526 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1527 cf_read_error_message(err, err_info), cf->filename);
1531 /* If the previous frame is displayed, and we haven't yet seen the
1532 selected frame, remember that frame - it's the closest one we've
1533 yet seen before the selected frame. */
1534 if (prev_row != -1 && !selected_frame_seen) {
1535 preceding_row = prev_row;
1536 preceding_frame = prev_frame;
1538 row = add_packet_to_packet_list(fdata, cf, dfcode, &cf->pseudo_header, cf->pd,
1541 /* If this frame is displayed, and this is the first frame we've
1542 seen displayed after the selected frame, remember this frame -
1543 it's the closest one we've yet seen at or after the selected
1545 if (row != -1 && selected_frame_seen && following_row == -1) {
1546 following_row = row;
1547 following_frame = fdata;
1549 if (fdata == selected_frame) {
1551 selected_frame_seen = TRUE;
1554 /* Remember this row/frame - it'll be the previous row/frame
1555 on the next pass through the loop. */
1560 /* Re-sort the list using the previously selected order */
1561 packet_list_set_sort_column();
1564 /* Clear out what remains of the visited flags and per-frame data
1567 XXX - that may cause various forms of bogosity when dissecting
1568 these frames, as they won't have been seen by this sequential
1569 pass, but the only alternative I see is to keep scanning them
1570 even though the user requested that the scan stop, and that
1571 would leave the user stuck with an Wireshark grinding on
1572 until it finishes. Should we just stick them with that? */
1573 for (; fdata != NULL; fdata = fdata->next) {
1574 fdata->flags.visited = 0;
1576 g_slist_free(fdata->pfd);
1582 /* We're done filtering the packets; destroy the progress bar if it
1584 if (progbar != NULL)
1585 destroy_progress_dlg(progbar);
1587 /* Unfreeze the packet list. */
1590 if (selected_row == -1) {
1591 /* The selected frame didn't pass the filter. */
1592 if (selected_frame == NULL) {
1593 /* That's because there *was* no selected frame. Make the first
1594 displayed frame the current frame. */
1597 /* Find the nearest displayed frame to the selected frame (whether
1598 it's before or after that frame) and make that the current frame.
1599 If the next and previous displayed frames are equidistant from the
1600 selected frame, choose the next one. */
1601 g_assert(following_frame == NULL ||
1602 following_frame->num >= selected_frame->num);
1603 g_assert(preceding_frame == NULL ||
1604 preceding_frame->num <= selected_frame->num);
1605 if (following_frame == NULL) {
1606 /* No frame after the selected frame passed the filter, so we
1607 have to select the last displayed frame before the selected
1609 selected_row = preceding_row;
1610 } else if (preceding_frame == NULL) {
1611 /* No frame before the selected frame passed the filter, so we
1612 have to select the first displayed frame after the selected
1614 selected_row = following_row;
1616 /* Frames before and after the selected frame passed the filter, so
1617 we'll select the previous frame */
1618 selected_row = preceding_row;
1623 if (selected_row == -1) {
1624 /* There are no frames displayed at all. */
1625 cf_unselect_packet(cf);
1627 /* Either the frame that was selected passed the filter, or we've
1628 found the nearest displayed frame to that frame. Select it, make
1629 it the focus row, and make it visible. */
1630 packet_list_set_selected_row(selected_row);
1633 /* Cleanup and release all dfilter resources */
1634 if (dfcode != NULL){
1635 dfilter_free(dfcode);
1646 process_specified_packets(capture_file *cf, packet_range_t *range,
1647 const char *string1, const char *string2, gboolean terminate_is_stop,
1648 gboolean (*callback)(capture_file *, frame_data *,
1649 union wtap_pseudo_header *, const guint8 *, void *),
1650 void *callback_args)
1655 union wtap_pseudo_header pseudo_header;
1656 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1657 psp_return_t ret = PSP_FINISHED;
1659 progdlg_t *progbar = NULL;
1662 gboolean progbar_stop_flag;
1663 GTimeVal progbar_start_time;
1664 gchar progbar_status_str[100];
1665 int progbar_nextstep;
1666 int progbar_quantum;
1667 range_process_e process_this;
1669 /* Update the progress bar when it gets to this value. */
1670 progbar_nextstep = 0;
1671 /* When we reach the value that triggers a progress bar update,
1672 bump that value by this amount. */
1673 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1674 /* Count of packets at which we've looked. */
1676 /* Progress so far. */
1679 progbar_stop_flag = FALSE;
1680 g_get_current_time(&progbar_start_time);
1682 packet_range_process_init(range);
1684 /* Iterate through the list of packets, printing the packets that
1685 were selected by the current display filter. */
1686 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1687 /* Create the progress bar if necessary.
1688 We check on every iteration of the loop, so that it takes no
1689 longer than the standard time to create it (otherwise, for a
1690 large file, we might take considerably longer than that standard
1691 time in order to get to the next progress bar step). */
1692 if (progbar == NULL)
1693 progbar = delayed_create_progress_dlg(string1, string2,
1696 &progbar_start_time,
1699 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1700 when we update it, we have to run the GTK+ main loop to get it
1701 to repaint what's pending, and doing so may involve an "ioctl()"
1702 to see if there's any pending input from an X server, and doing
1703 that for every packet can be costly, especially on a big file. */
1704 if (progbar_count >= progbar_nextstep) {
1705 /* let's not divide by zero. I should never be started
1706 * with count == 0, so let's assert that
1708 g_assert(cf->count > 0);
1709 progbar_val = (gfloat) progbar_count / cf->count;
1711 if (progbar != NULL) {
1712 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1713 "%4u of %u packets", progbar_count, cf->count);
1714 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1717 progbar_nextstep += progbar_quantum;
1720 if (progbar_stop_flag) {
1721 /* Well, the user decided to abort the operation. Just stop,
1722 and arrange to return PSP_STOPPED to our caller, so they know
1723 it was stopped explicitly. */
1730 /* do we have to process this packet? */
1731 process_this = packet_range_process_packet(range, fdata);
1732 if (process_this == range_process_next) {
1733 /* this packet uninteresting, continue with next one */
1735 } else if (process_this == range_processing_finished) {
1736 /* all interesting packets processed, stop the loop */
1740 /* Get the packet */
1741 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1742 pd, fdata->cap_len, &err, &err_info)) {
1743 /* Attempt to get the packet failed. */
1744 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1745 cf_read_error_message(err, err_info), cf->filename);
1749 /* Process the packet */
1750 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1751 /* Callback failed. We assume it reported the error appropriately. */
1757 /* We're done printing the packets; destroy the progress bar if
1759 if (progbar != NULL)
1760 destroy_progress_dlg(progbar);
1766 retap_packet(capture_file *cf _U_, frame_data *fdata,
1767 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1770 column_info *cinfo = argsp;
1771 epan_dissect_t *edt;
1773 /* If we have tap listeners, allocate a protocol tree root node, so that
1774 we'll construct a protocol tree against which a filter expression can
1776 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1777 tap_queue_init(edt);
1778 epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
1779 tap_push_tapped_queue(edt);
1780 epan_dissect_free(edt);
1786 cf_retap_packets(capture_file *cf, gboolean do_columns)
1788 packet_range_t range;
1790 /* Reset the tap listeners. */
1791 reset_tap_listeners();
1793 /* Iterate through the list of packets, dissecting all packets and
1794 re-running the taps. */
1795 packet_range_init(&range);
1796 packet_range_process_init(&range);
1797 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1798 "all packets", TRUE, retap_packet,
1799 do_columns ? &cf->cinfo : NULL)) {
1801 /* Completed successfully. */
1805 /* Well, the user decided to abort the refiltering.
1806 Return CF_READ_ABORTED so our caller knows they did that. */
1807 return CF_READ_ABORTED;
1810 /* Error while retapping. */
1811 return CF_READ_ERROR;
1814 g_assert_not_reached();
1819 print_args_t *print_args;
1820 gboolean print_header_line;
1821 char *header_line_buf;
1822 int header_line_buf_len;
1823 gboolean print_formfeed;
1824 gboolean print_separator;
1828 } print_callback_args_t;
1831 print_packet(capture_file *cf, frame_data *fdata,
1832 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1835 print_callback_args_t *args = argsp;
1836 epan_dissect_t *edt;
1842 gboolean proto_tree_needed;
1843 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1844 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1846 /* Create the protocol tree, and make it visible, if we're printing
1847 the dissection or the hex data.
1848 XXX - do we need it if we're just printing the hex data? */
1850 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1851 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1853 /* Fill in the column information if we're printing the summary
1855 if (args->print_args->print_summary) {
1856 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1857 epan_dissect_fill_in_columns(edt);
1859 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1861 if (args->print_formfeed) {
1862 if (!new_page(args->print_args->stream))
1865 if (args->print_separator) {
1866 if (!print_line(args->print_args->stream, 0, ""))
1872 * We generate bookmarks, if the output format supports them.
1873 * The name is "__frameN__".
1875 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1877 if (args->print_args->print_summary) {
1878 if (args->print_header_line) {
1879 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1881 args->print_header_line = FALSE; /* we might not need to print any more */
1883 cp = &args->line_buf[0];
1885 for (i = 0; i < cf->cinfo.num_cols; i++) {
1886 /* Find the length of the string for this column. */
1887 column_len = strlen(cf->cinfo.col_data[i]);
1888 if (args->col_widths[i] > column_len)
1889 column_len = args->col_widths[i];
1891 /* Make sure there's room in the line buffer for the column; if not,
1892 double its length. */
1893 line_len += column_len + 1; /* "+1" for space */
1894 if (line_len > args->line_buf_len) {
1895 cp_off = cp - args->line_buf;
1896 args->line_buf_len = 2 * line_len;
1897 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1898 cp = args->line_buf + cp_off;
1901 /* Right-justify the packet number column. */
1902 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1903 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1905 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1907 if (i != cf->cinfo.num_cols - 1)
1913 * Generate a bookmark, using the summary line as the title.
1915 if (!print_bookmark(args->print_args->stream, bookmark_name,
1919 if (!print_line(args->print_args->stream, 0, args->line_buf))
1923 * Generate a bookmark, using "Frame N" as the title, as we're not
1924 * printing the summary line.
1926 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1927 if (!print_bookmark(args->print_args->stream, bookmark_name,
1930 } /* if (print_summary) */
1932 if (args->print_args->print_dissections != print_dissections_none) {
1933 if (args->print_args->print_summary) {
1934 /* Separate the summary line from the tree with a blank line. */
1935 if (!print_line(args->print_args->stream, 0, ""))
1939 /* Print the information in that tree. */
1940 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1943 /* Print a blank line if we print anything after this (aka more than one packet). */
1944 args->print_separator = TRUE;
1946 /* Print a header line if we print any more packet summaries */
1947 args->print_header_line = TRUE;
1950 if (args->print_args->print_hex) {
1951 /* Print the full packet data as hex. */
1952 if (!print_hex_data(args->print_args->stream, edt))
1955 /* Print a blank line if we print anything after this (aka more than one packet). */
1956 args->print_separator = TRUE;
1958 /* Print a header line if we print any more packet summaries */
1959 args->print_header_line = TRUE;
1960 } /* if (args->print_args->print_dissections != print_dissections_none) */
1962 epan_dissect_free(edt);
1964 /* do we want to have a formfeed between each packet from now on? */
1965 if(args->print_args->print_formfeed) {
1966 args->print_formfeed = TRUE;
1972 epan_dissect_free(edt);
1977 cf_print_packets(capture_file *cf, print_args_t *print_args)
1980 print_callback_args_t callback_args;
1988 callback_args.print_args = print_args;
1989 callback_args.print_header_line = TRUE;
1990 callback_args.header_line_buf = NULL;
1991 callback_args.header_line_buf_len = 256;
1992 callback_args.print_formfeed = FALSE;
1993 callback_args.print_separator = FALSE;
1994 callback_args.line_buf = NULL;
1995 callback_args.line_buf_len = 256;
1996 callback_args.col_widths = NULL;
1998 if (!print_preamble(print_args->stream, cf->filename)) {
1999 destroy_print_stream(print_args->stream);
2000 return CF_PRINT_WRITE_ERROR;
2003 if (print_args->print_summary) {
2004 /* We're printing packet summaries. Allocate the header line buffer
2005 and get the column widths. */
2006 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2008 /* Find the widths for each of the columns - maximum of the
2009 width of the title and the width of the data - and construct
2010 a buffer with a line containing the column titles. */
2011 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2012 cp = &callback_args.header_line_buf[0];
2014 for (i = 0; i < cf->cinfo.num_cols; i++) {
2015 /* Don't pad the last column. */
2016 if (i == cf->cinfo.num_cols - 1)
2017 callback_args.col_widths[i] = 0;
2019 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
2020 data_width = get_column_char_width(get_column_format(i));
2021 if (data_width > callback_args.col_widths[i])
2022 callback_args.col_widths[i] = data_width;
2025 /* Find the length of the string for this column. */
2026 column_len = strlen(cf->cinfo.col_title[i]);
2027 if (callback_args.col_widths[i] > column_len)
2028 column_len = callback_args.col_widths[i];
2030 /* Make sure there's room in the line buffer for the column; if not,
2031 double its length. */
2032 line_len += column_len + 1; /* "+1" for space */
2033 if (line_len > callback_args.header_line_buf_len) {
2034 cp_off = cp - callback_args.header_line_buf;
2035 callback_args.header_line_buf_len = 2 * line_len;
2036 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2037 callback_args.header_line_buf_len + 1);
2038 cp = callback_args.header_line_buf + cp_off;
2041 /* Right-justify the packet number column. */
2042 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2043 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2045 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2047 if (i != cf->cinfo.num_cols - 1)
2052 /* Now start out the main line buffer with the same length as the
2053 header line buffer. */
2054 callback_args.line_buf_len = callback_args.header_line_buf_len;
2055 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2056 } /* if (print_summary) */
2058 /* Iterate through the list of packets, printing the packets we were
2060 ret = process_specified_packets(cf, &print_args->range, "Printing",
2061 "selected packets", TRUE, print_packet,
2064 if (callback_args.header_line_buf != NULL)
2065 g_free(callback_args.header_line_buf);
2066 if (callback_args.line_buf != NULL)
2067 g_free(callback_args.line_buf);
2068 if (callback_args.col_widths != NULL)
2069 g_free(callback_args.col_widths);
2074 /* Completed successfully. */
2078 /* Well, the user decided to abort the printing.
2080 XXX - note that what got generated before they did that
2081 will get printed if we're piping to a print program; we'd
2082 have to write to a file and then hand that to the print
2083 program to make it actually not print anything. */
2087 /* Error while printing.
2089 XXX - note that what got generated before they did that
2090 will get printed if we're piping to a print program; we'd
2091 have to write to a file and then hand that to the print
2092 program to make it actually not print anything. */
2093 destroy_print_stream(print_args->stream);
2094 return CF_PRINT_WRITE_ERROR;
2097 if (!print_finale(print_args->stream)) {
2098 destroy_print_stream(print_args->stream);
2099 return CF_PRINT_WRITE_ERROR;
2102 if (!destroy_print_stream(print_args->stream))
2103 return CF_PRINT_WRITE_ERROR;
2109 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2110 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2114 epan_dissect_t *edt;
2116 /* Create the protocol tree, but don't fill in the column information. */
2117 edt = epan_dissect_new(TRUE, TRUE);
2118 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2120 /* Write out the information in that tree. */
2121 proto_tree_write_pdml(edt, fh);
2123 epan_dissect_free(edt);
2129 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2134 fh = eth_fopen(print_args->file, "w");
2136 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2138 write_pdml_preamble(fh);
2141 return CF_PRINT_WRITE_ERROR;
2144 /* Iterate through the list of packets, printing the packets we were
2146 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2147 "selected packets", TRUE,
2148 write_pdml_packet, fh);
2153 /* Completed successfully. */
2157 /* Well, the user decided to abort the printing. */
2161 /* Error while printing. */
2163 return CF_PRINT_WRITE_ERROR;
2166 write_pdml_finale(fh);
2169 return CF_PRINT_WRITE_ERROR;
2172 /* XXX - check for an error */
2179 write_psml_packet(capture_file *cf, frame_data *fdata,
2180 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2184 epan_dissect_t *edt;
2186 /* Fill in the column information, but don't create the protocol tree. */
2187 edt = epan_dissect_new(FALSE, FALSE);
2188 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2189 epan_dissect_fill_in_columns(edt);
2191 /* Write out the information in that tree. */
2192 proto_tree_write_psml(edt, fh);
2194 epan_dissect_free(edt);
2200 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2205 fh = eth_fopen(print_args->file, "w");
2207 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2209 write_psml_preamble(fh);
2212 return CF_PRINT_WRITE_ERROR;
2215 /* Iterate through the list of packets, printing the packets we were
2217 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2218 "selected packets", TRUE,
2219 write_psml_packet, fh);
2224 /* Completed successfully. */
2228 /* Well, the user decided to abort the printing. */
2232 /* Error while printing. */
2234 return CF_PRINT_WRITE_ERROR;
2237 write_psml_finale(fh);
2240 return CF_PRINT_WRITE_ERROR;
2243 /* XXX - check for an error */
2250 write_csv_packet(capture_file *cf, frame_data *fdata,
2251 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2255 epan_dissect_t *edt;
2257 /* Fill in the column information, but don't create the protocol tree. */
2258 edt = epan_dissect_new(FALSE, FALSE);
2259 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2260 epan_dissect_fill_in_columns(edt);
2262 /* Write out the information in that tree. */
2263 proto_tree_write_csv(edt, fh);
2265 epan_dissect_free(edt);
2271 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2276 fh = eth_fopen(print_args->file, "w");
2278 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2280 write_csv_preamble(fh);
2283 return CF_PRINT_WRITE_ERROR;
2286 /* Iterate through the list of packets, printing the packets we were
2288 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2289 "selected packets", TRUE,
2290 write_csv_packet, fh);
2295 /* Completed successfully. */
2299 /* Well, the user decided to abort the printing. */
2303 /* Error while printing. */
2305 return CF_PRINT_WRITE_ERROR;
2308 write_csv_finale(fh);
2311 return CF_PRINT_WRITE_ERROR;
2314 /* XXX - check for an error */
2320 /* Scan through the packet list and change all columns that use the
2321 "command-line-specified" time stamp format to use the current
2322 value of that format. */
2324 cf_change_time_formats(capture_file *cf)
2327 progdlg_t *progbar = NULL;
2333 GTimeVal start_time;
2334 gchar status_str[100];
2335 int progbar_nextstep;
2336 int progbar_quantum;
2338 gboolean sorted_by_frame_column;
2341 /* adjust timestamp precision if auto is selected */
2342 cf_timestamp_auto_precision(cf);
2344 /* Are there any columns with time stamps in the "command-line-specified"
2347 XXX - we have to force the "column is writable" flag on, as it
2348 might be off from the last frame that was dissected. */
2349 col_set_writable(&cf->cinfo, TRUE);
2350 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2351 /* No, there aren't any columns in that format, so we have no work
2355 first = cf->cinfo.col_first[COL_CLS_TIME];
2356 g_assert(first >= 0);
2357 last = cf->cinfo.col_last[COL_CLS_TIME];
2359 /* Freeze the packet list while we redo it, so we don't get any
2360 screen updates while it happens. */
2361 packet_list_freeze();
2363 /* Update the progress bar when it gets to this value. */
2364 progbar_nextstep = 0;
2365 /* When we reach the value that triggers a progress bar update,
2366 bump that value by this amount. */
2367 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2368 /* Count of packets at which we've looked. */
2370 /* Progress so far. */
2373 /* If the rows are currently sorted by the frame column then we know
2374 * the row number of each packet: it's the row number of the previously
2375 * displayed packet + 1.
2377 * Otherwise, if the display is sorted by a different column then we have
2378 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2379 * of changing the time display format O(N**2)).
2381 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2382 * the row number and walks that many elements down the clist to find
2383 * the appropriate element.)
2385 sorted_by_frame_column = FALSE;
2386 for (i = 0; i < cf->cinfo.num_cols; i++) {
2387 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2389 sorted_by_frame_column = (i == packet_list_get_sort_column());
2395 g_get_current_time(&start_time);
2397 /* Iterate through the list of packets, checking whether the packet
2398 is in a row of the summary list and, if so, whether there are
2399 any columns that show the time in the "command-line-specified"
2400 format and, if so, update that row. */
2401 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2402 /* Create the progress bar if necessary.
2403 We check on every iteration of the loop, so that it takes no
2404 longer than the standard time to create it (otherwise, for a
2405 large file, we might take considerably longer than that standard
2406 time in order to get to the next progress bar step). */
2407 if (progbar == NULL)
2408 progbar = delayed_create_progress_dlg("Changing", "time display",
2409 TRUE, &stop_flag, &start_time, progbar_val);
2411 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2412 when we update it, we have to run the GTK+ main loop to get it
2413 to repaint what's pending, and doing so may involve an "ioctl()"
2414 to see if there's any pending input from an X server, and doing
2415 that for every packet can be costly, especially on a big file. */
2416 if (count >= progbar_nextstep) {
2417 /* let's not divide by zero. I should never be started
2418 * with count == 0, so let's assert that
2420 g_assert(cf->count > 0);
2422 progbar_val = (gfloat) count / cf->count;
2424 if (progbar != NULL) {
2425 g_snprintf(status_str, sizeof(status_str),
2426 "%4u of %u packets", count, cf->count);
2427 update_progress_dlg(progbar, progbar_val, status_str);
2430 progbar_nextstep += progbar_quantum;
2434 /* Well, the user decided to abort the redisplay. Just stop.
2436 XXX - this leaves the time field in the old format in
2437 frames we haven't yet processed. So it goes; should we
2438 simply not offer them the option of stopping? */
2444 /* Find what row this packet is in. */
2445 if (!sorted_by_frame_column) {
2446 /* This function is O(N), so we try to avoid using it... */
2447 row = packet_list_find_row_from_data(fdata);
2449 /* ...which we do by maintaining a count of packets that are
2450 being displayed (i.e., that have passed the display filter),
2451 and using the current value of that count as the row number
2452 (which is why we can only do it when the display is sorted
2453 by the frame number). */
2454 if (fdata->flags.passed_dfilter)
2461 /* This packet is in the summary list, on row "row". */
2463 for (i = first; i <= last; i++) {
2464 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2465 /* This is one of the columns that shows the time in
2466 "command-line-specified" format; update it. */
2467 cf->cinfo.col_buf[i][0] = '\0';
2468 col_set_cls_time(fdata, &cf->cinfo, i);
2469 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2475 /* We're done redisplaying the packets; destroy the progress bar if it
2477 if (progbar != NULL)
2478 destroy_progress_dlg(progbar);
2480 /* Set the column widths of those columns that show the time in
2481 "command-line-specified" format. */
2482 for (i = first; i <= last; i++) {
2483 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2484 packet_list_set_cls_time_width(i);
2488 /* Unfreeze the packet list. */
2496 gboolean frame_matched;
2500 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2504 mdata.string = string;
2505 mdata.string_len = strlen(string);
2506 return find_packet(cf, match_protocol_tree, &mdata);
2510 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2512 match_data *mdata = criterion;
2513 epan_dissect_t *edt;
2515 /* Construct the protocol tree, including the displayed text */
2516 edt = epan_dissect_new(TRUE, TRUE);
2517 /* We don't need the column information */
2518 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2520 /* Iterate through all the nodes, seeing if they have text that matches. */
2522 mdata->frame_matched = FALSE;
2523 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2524 epan_dissect_free(edt);
2525 return mdata->frame_matched;
2529 match_subtree_text(proto_node *node, gpointer data)
2531 match_data *mdata = (match_data*) data;
2532 const gchar *string = mdata->string;
2533 size_t string_len = mdata->string_len;
2534 capture_file *cf = mdata->cf;
2535 field_info *fi = PITEM_FINFO(node);
2536 gchar label_str[ITEM_LABEL_LENGTH];
2543 if (mdata->frame_matched) {
2544 /* We already had a match; don't bother doing any more work. */
2548 /* Don't match invisible entries. */
2549 if (PROTO_ITEM_IS_HIDDEN(node))
2552 /* was a free format label produced? */
2554 label_ptr = fi->rep->representation;
2556 /* no, make a generic label */
2557 label_ptr = label_str;
2558 proto_item_fill_label(fi, label_str);
2561 /* Does that label match? */
2562 label_len = strlen(label_ptr);
2563 for (i = 0; i < label_len; i++) {
2564 c_char = label_ptr[i];
2566 c_char = toupper(c_char);
2567 if (c_char == string[c_match]) {
2569 if (c_match == string_len) {
2570 /* No need to look further; we have a match */
2571 mdata->frame_matched = TRUE;
2578 /* Recurse into the subtree, if it exists */
2579 if (node->first_child != NULL)
2580 proto_tree_children_foreach(node, match_subtree_text, mdata);
2584 cf_find_packet_summary_line(capture_file *cf, const char *string)
2588 mdata.string = string;
2589 mdata.string_len = strlen(string);
2590 return find_packet(cf, match_summary_line, &mdata);
2594 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2596 match_data *mdata = criterion;
2597 const gchar *string = mdata->string;
2598 size_t string_len = mdata->string_len;
2599 epan_dissect_t *edt;
2600 const char *info_column;
2601 size_t info_column_len;
2602 gboolean frame_matched = FALSE;
2608 /* Don't bother constructing the protocol tree */
2609 edt = epan_dissect_new(FALSE, FALSE);
2610 /* Get the column information */
2611 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2613 /* Find the Info column */
2614 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2615 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2616 /* Found it. See if we match. */
2617 info_column = edt->pi.cinfo->col_data[colx];
2618 info_column_len = strlen(info_column);
2619 for (i = 0; i < info_column_len; i++) {
2620 c_char = info_column[i];
2622 c_char = toupper(c_char);
2623 if (c_char == string[c_match]) {
2625 if (c_match == string_len) {
2626 frame_matched = TRUE;
2635 epan_dissect_free(edt);
2636 return frame_matched;
2642 } cbs_t; /* "Counted byte string" */
2645 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2650 info.data_len = string_size;
2652 /* String or hex search? */
2654 /* String search - what type of string? */
2655 switch (cf->scs_type) {
2657 case SCS_ASCII_AND_UNICODE:
2658 return find_packet(cf, match_ascii_and_unicode, &info);
2661 return find_packet(cf, match_ascii, &info);
2664 return find_packet(cf, match_unicode, &info);
2667 g_assert_not_reached();
2671 return find_packet(cf, match_binary, &info);
2675 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2677 cbs_t *info = criterion;
2678 const char *ascii_text = info->data;
2679 size_t textlen = info->data_len;
2680 gboolean frame_matched;
2686 frame_matched = FALSE;
2687 buf_len = fdata->pkt_len;
2688 for (i = 0; i < buf_len; i++) {
2691 c_char = toupper(c_char);
2693 if (c_char == ascii_text[c_match]) {
2695 if (c_match == textlen) {
2696 frame_matched = TRUE;
2697 cf->search_pos = i; /* Save the position of the last character
2698 for highlighting the field. */
2705 return frame_matched;
2709 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2711 cbs_t *info = criterion;
2712 const char *ascii_text = info->data;
2713 size_t textlen = info->data_len;
2714 gboolean frame_matched;
2720 frame_matched = FALSE;
2721 buf_len = fdata->pkt_len;
2722 for (i = 0; i < buf_len; i++) {
2725 c_char = toupper(c_char);
2726 if (c_char == ascii_text[c_match]) {
2728 if (c_match == textlen) {
2729 frame_matched = TRUE;
2730 cf->search_pos = i; /* Save the position of the last character
2731 for highlighting the field. */
2737 return frame_matched;
2741 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2743 cbs_t *info = criterion;
2744 const char *ascii_text = info->data;
2745 size_t textlen = info->data_len;
2746 gboolean frame_matched;
2752 frame_matched = FALSE;
2753 buf_len = fdata->pkt_len;
2754 for (i = 0; i < buf_len; i++) {
2757 c_char = toupper(c_char);
2758 if (c_char == ascii_text[c_match]) {
2761 if (c_match == textlen) {
2762 frame_matched = TRUE;
2763 cf->search_pos = i; /* Save the position of the last character
2764 for highlighting the field. */
2770 return frame_matched;
2774 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2776 cbs_t *info = criterion;
2777 const guint8 *binary_data = info->data;
2778 size_t datalen = info->data_len;
2779 gboolean frame_matched;
2784 frame_matched = FALSE;
2785 buf_len = fdata->pkt_len;
2786 for (i = 0; i < buf_len; i++) {
2787 if (cf->pd[i] == binary_data[c_match]) {
2789 if (c_match == datalen) {
2790 frame_matched = TRUE;
2791 cf->search_pos = i; /* Save the position of the last character
2792 for highlighting the field. */
2798 return frame_matched;
2802 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2804 return find_packet(cf, match_dfilter, sfcode);
2808 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2810 dfilter_t *sfcode = criterion;
2811 epan_dissect_t *edt;
2812 gboolean frame_matched;
2814 edt = epan_dissect_new(TRUE, FALSE);
2815 epan_dissect_prime_dfilter(edt, sfcode);
2816 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2817 frame_matched = dfilter_apply_edt(sfcode, edt);
2818 epan_dissect_free(edt);
2819 return frame_matched;
2823 find_packet(capture_file *cf,
2824 gboolean (*match_function)(capture_file *, frame_data *, void *),
2827 frame_data *start_fd;
2829 frame_data *new_fd = NULL;
2830 progdlg_t *progbar = NULL;
2837 GTimeVal start_time;
2838 gchar status_str[100];
2839 int progbar_nextstep;
2840 int progbar_quantum;
2843 start_fd = cf->current_frame;
2844 if (start_fd != NULL) {
2845 /* Iterate through the list of packets, starting at the packet we've
2846 picked, calling a routine to run the filter on the packet, see if
2847 it matches, and stop if so. */
2851 /* Update the progress bar when it gets to this value. */
2852 progbar_nextstep = 0;
2853 /* When we reach the value that triggers a progress bar update,
2854 bump that value by this amount. */
2855 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2856 /* Progress so far. */
2860 g_get_current_time(&start_time);
2863 title = cf->sfilter?cf->sfilter:"";
2865 /* Create the progress bar if necessary.
2866 We check on every iteration of the loop, so that it takes no
2867 longer than the standard time to create it (otherwise, for a
2868 large file, we might take considerably longer than that standard
2869 time in order to get to the next progress bar step). */
2870 if (progbar == NULL)
2871 progbar = delayed_create_progress_dlg("Searching", title,
2872 FALSE, &stop_flag, &start_time, progbar_val);
2874 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2875 when we update it, we have to run the GTK+ main loop to get it
2876 to repaint what's pending, and doing so may involve an "ioctl()"
2877 to see if there's any pending input from an X server, and doing
2878 that for every packet can be costly, especially on a big file. */
2879 if (count >= progbar_nextstep) {
2880 /* let's not divide by zero. I should never be started
2881 * with count == 0, so let's assert that
2883 g_assert(cf->count > 0);
2885 progbar_val = (gfloat) count / cf->count;
2887 if (progbar != NULL) {
2888 g_snprintf(status_str, sizeof(status_str),
2889 "%4u of %u packets", count, cf->count);
2890 update_progress_dlg(progbar, progbar_val, status_str);
2893 progbar_nextstep += progbar_quantum;
2897 /* Well, the user decided to abort the search. Go back to the
2898 frame where we started. */
2903 /* Go past the current frame. */
2904 if (cf->sbackward) {
2905 /* Go on to the previous frame. */
2906 fdata = fdata->prev;
2907 if (fdata == NULL) {
2909 * XXX - other apps have a bit more of a detailed message
2910 * for this, and instead of offering "OK" and "Cancel",
2911 * they offer things such as "Continue" and "Cancel";
2912 * we need an API for popping up alert boxes with
2913 * {Verb} and "Cancel".
2916 if (prefs.gui_find_wrap)
2918 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2919 "%sBeginning of capture exceeded!%s\n\n"
2920 "Search is continued from the end of the capture.",
2921 simple_dialog_primary_start(), simple_dialog_primary_end());
2922 fdata = cf->plist_end; /* wrap around */
2926 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2927 "%sBeginning of capture exceeded!%s\n\n"
2928 "Try searching forwards.",
2929 simple_dialog_primary_start(), simple_dialog_primary_end());
2930 fdata = start_fd; /* stay on previous packet */
2934 /* Go on to the next frame. */
2935 fdata = fdata->next;
2936 if (fdata == NULL) {
2937 if (prefs.gui_find_wrap)
2939 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2940 "%sEnd of capture exceeded!%s\n\n"
2941 "Search is continued from the start of the capture.",
2942 simple_dialog_primary_start(), simple_dialog_primary_end());
2943 fdata = cf->plist; /* wrap around */
2947 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2948 "%sEnd of capture exceeded!%s\n\n"
2949 "Try searching backwards.",
2950 simple_dialog_primary_start(), simple_dialog_primary_end());
2951 fdata = start_fd; /* stay on previous packet */
2958 /* Is this packet in the display? */
2959 if (fdata->flags.passed_dfilter) {
2960 /* Yes. Load its data. */
2961 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2962 cf->pd, fdata->cap_len, &err, &err_info)) {
2963 /* Read error. Report the error, and go back to the frame
2964 where we started. */
2965 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2966 cf_read_error_message(err, err_info), cf->filename);
2971 /* Does it match the search criterion? */
2972 if ((*match_function)(cf, fdata, criterion)) {
2974 break; /* found it! */
2978 if (fdata == start_fd) {
2979 /* We're back to the frame we were on originally, and that frame
2980 doesn't match the search filter. The search failed. */
2985 /* We're done scanning the packets; destroy the progress bar if it
2987 if (progbar != NULL)
2988 destroy_progress_dlg(progbar);
2991 if (new_fd != NULL) {
2992 /* We found a frame. Find what row it's in. */
2993 row = packet_list_find_row_from_data(new_fd);
2994 g_assert(row != -1);
2996 /* Select that row, make it the focus row, and make it visible. */
2997 packet_list_set_selected_row(row);
2998 return TRUE; /* success */
3000 return FALSE; /* failure */
3004 cf_goto_frame(capture_file *cf, guint fnumber)
3009 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3012 if (fdata == NULL) {
3013 /* we didn't find a packet with that packet number */
3014 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3015 "There is no packet with the packet number %u.", fnumber);
3016 return FALSE; /* we failed to go to that packet */
3018 if (!fdata->flags.passed_dfilter) {
3019 /* that packet currently isn't displayed */
3020 /* XXX - add it to the set of displayed packets? */
3021 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3022 "The packet number %u isn't currently being displayed.", fnumber);
3023 return FALSE; /* we failed to go to that packet */
3026 /* We found that packet, and it's currently being displayed.
3027 Find what row it's in. */
3028 row = packet_list_find_row_from_data(fdata);
3029 g_assert(row != -1);
3031 /* Select that row, make it the focus row, and make it visible. */
3032 packet_list_set_selected_row(row);
3033 return TRUE; /* we got to that packet */
3037 cf_goto_top_frame(capture_file *cf)
3041 frame_data *lowest_fdata = NULL;
3043 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3044 if (fdata->flags.passed_dfilter) {
3045 lowest_fdata = fdata;
3050 if (lowest_fdata == NULL) {
3054 /* We found that packet, and it's currently being displayed.
3055 Find what row it's in. */
3056 row = packet_list_find_row_from_data(lowest_fdata);
3057 g_assert(row != -1);
3059 /* Select that row, make it the focus row, and make it visible. */
3060 packet_list_set_selected_row(row);
3061 return TRUE; /* we got to that packet */
3065 cf_goto_bottom_frame(capture_file *cf)
3069 frame_data *highest_fdata = NULL;
3071 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3072 if (fdata->flags.passed_dfilter) {
3073 highest_fdata = fdata;
3077 if (highest_fdata == NULL) {
3081 /* We found that packet, and it's currently being displayed.
3082 Find what row it's in. */
3083 row = packet_list_find_row_from_data(highest_fdata);
3084 g_assert(row != -1);
3086 /* Select that row, make it the focus row, and make it visible. */
3087 packet_list_set_selected_row(row);
3088 return TRUE; /* we got to that packet */
3092 * Go to frame specified by currently selected protocol tree item.
3095 cf_goto_framenum(capture_file *cf)
3097 header_field_info *hfinfo;
3100 if (cf->finfo_selected) {
3101 hfinfo = cf->finfo_selected->hfinfo;
3103 if (hfinfo->type == FT_FRAMENUM) {
3104 framenum = fvalue_get_integer(&cf->finfo_selected->value);
3106 return cf_goto_frame(cf, framenum);
3113 /* Select the packet on a given row. */
3115 cf_select_packet(capture_file *cf, int row)
3121 /* Get the frame data struct pointer for this frame */
3122 fdata = (frame_data *)packet_list_get_row_data(row);
3124 if (fdata == NULL) {
3125 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3126 the first entry is added to it by "real_insert_row()", that row
3127 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3128 our version and the vanilla GTK+ version).
3130 This means that a "select-row" signal is emitted; this causes
3131 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3134 "cf_select_packet()" fetches, above, the data associated with the
3135 row that was selected; however, as "gtk_clist_append()", which
3136 called "real_insert_row()", hasn't yet returned, we haven't yet
3137 associated any data with that row, so we get back a null pointer.
3139 We can't assume that there's only one frame in the frame list,
3140 either, as we may be filtering the display.
3142 We therefore assume that, if "row" is 0, i.e. the first row
3143 is being selected, and "cf->first_displayed" equals
3144 "cf->last_displayed", i.e. there's only one frame being
3145 displayed, that frame is the frame we want.
3147 This means we have to set "cf->first_displayed" and
3148 "cf->last_displayed" before adding the row to the
3149 GtkCList; see the comment in "add_packet_to_packet_list()". */
3151 if (row == 0 && cf->first_displayed == cf->last_displayed)
3152 fdata = cf->first_displayed;
3155 /* If fdata _still_ isn't set simply give up. */
3156 if (fdata == NULL) {
3160 /* Get the data in that frame. */
3161 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3162 cf->pd, fdata->cap_len, &err, &err_info)) {
3163 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3164 cf_read_error_message(err, err_info), cf->filename);
3168 /* Record that this frame is the current frame. */
3169 cf->current_frame = fdata;
3171 /* Create the logical protocol tree. */
3172 if (cf->edt != NULL) {
3173 epan_dissect_free(cf->edt);
3176 /* We don't need the columns here. */
3177 cf->edt = epan_dissect_new(TRUE, TRUE);
3179 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3182 cf_callback_invoke(cf_cb_packet_selected, cf);
3185 /* Unselect the selected packet, if any. */
3187 cf_unselect_packet(capture_file *cf)
3189 /* Destroy the epan_dissect_t for the unselected packet. */
3190 if (cf->edt != NULL) {
3191 epan_dissect_free(cf->edt);
3195 /* No packet is selected. */
3196 cf->current_frame = NULL;
3198 cf_callback_invoke(cf_cb_packet_unselected, cf);
3200 /* No protocol tree means no selected field. */
3201 cf_unselect_field(cf);
3204 /* Unset the selected protocol tree field, if any. */
3206 cf_unselect_field(capture_file *cf)
3208 cf->finfo_selected = NULL;
3210 cf_callback_invoke(cf_cb_field_unselected, cf);
3214 * Mark a particular frame.
3217 cf_mark_frame(capture_file *cf, frame_data *frame)
3219 if (! frame->flags.marked) {
3220 frame->flags.marked = TRUE;
3221 if (cf->count > cf->marked_count)
3227 * Unmark a particular frame.
3230 cf_unmark_frame(capture_file *cf, frame_data *frame)
3232 if (frame->flags.marked) {
3233 frame->flags.marked = FALSE;
3234 if (cf->marked_count > 0)
3242 } save_callback_args_t;
3245 * Save a capture to a file, in a particular format, saving either
3246 * all packets, all currently-displayed packets, or all marked packets.
3248 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3249 * up a message box for the failure.
3252 save_packet(capture_file *cf _U_, frame_data *fdata,
3253 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3256 save_callback_args_t *args = argsp;
3257 struct wtap_pkthdr hdr;
3260 /* init the wtap header for saving */
3261 hdr.ts = *(struct wtap_nstime *) &fdata->abs_ts;
3262 hdr.caplen = fdata->cap_len;
3263 hdr.len = fdata->pkt_len;
3264 hdr.pkt_encap = fdata->lnk_t;
3266 /* and save the packet */
3267 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3268 cf_write_failure_alert_box(args->fname, err);
3275 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3277 gchar *from_filename;
3281 save_callback_args_t callback_args;
3283 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3285 /* don't write over an existing file. */
3286 /* this should've been already checked by our caller, just to be sure... */
3287 if (file_exists(fname)) {
3288 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3289 "%sCapture file: \"%s\" already exists!%s\n\n"
3290 "Please choose a different filename.",
3291 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3295 packet_range_process_init(range);
3298 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3299 /* We're not filtering packets, and we're saving it in the format
3300 it's already in, so we can just move or copy the raw data. */
3302 if (cf->is_tempfile) {
3303 /* The file being saved is a temporary file from a live
3304 capture, so it doesn't need to stay around under that name;
3305 first, try renaming the capture buffer file to the new name. */
3307 if (eth_rename(cf->filename, fname) == 0) {
3308 /* That succeeded - there's no need to copy the source file. */
3309 from_filename = NULL;
3312 if (errno == EXDEV) {
3313 /* They're on different file systems, so we have to copy the
3316 from_filename = cf->filename;
3318 /* The rename failed, but not because they're on different
3319 file systems - put up an error message. (Or should we
3320 just punt and try to copy? The only reason why I'd
3321 expect the rename to fail and the copy to succeed would
3322 be if we didn't have permission to remove the file from
3323 the temporary directory, and that might be fixable - but
3324 is it worth requiring the user to go off and fix it?) */
3325 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3326 file_rename_error_message(errno), fname);
3332 from_filename = cf->filename;
3335 /* It's a permanent file, so we should copy it, and not remove the
3338 from_filename = cf->filename;
3342 /* Copy the file, if we haven't moved it. */
3343 if (!copy_binary_file(from_filename, fname))
3347 /* Either we're filtering packets, or we're saving in a different
3348 format; we can't do that by copying or moving the capture file,
3349 we have to do it by writing the packets out in Wiretap. */
3350 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3353 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3357 /* XXX - we let the user save a subset of the packets.
3359 If we do that, should we make that file the current file? If so,
3360 it means we can no longer get at the other packets. What does
3363 /* Iterate through the list of packets, processing the packets we were
3366 XXX - we've already called "packet_range_process_init(range)", but
3367 "process_specified_packets()" will do it again. Fortunately,
3368 that's harmless in this case, as we haven't done anything to
3369 "range" since we initialized it. */
3370 callback_args.pdh = pdh;
3371 callback_args.fname = fname;
3372 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3373 TRUE, save_packet, &callback_args)) {
3376 /* Completed successfully. */
3380 /* The user decided to abort the saving.
3381 XXX - remove the output file? */
3385 /* Error while saving. */
3386 wtap_dump_close(pdh, &err);
3390 if (!wtap_dump_close(pdh, &err)) {
3391 cf_close_failure_alert_box(fname, err);
3396 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3398 if (packet_range_process_all(range)) {
3399 /* We saved the entire capture, not just some packets from it.
3400 Open and read the file we saved it to.
3402 XXX - this is somewhat of a waste; we already have the
3403 packets, all this gets us is updated file type information
3404 (which we could just stuff into "cf"), and having the new
3405 file be the one we have opened and from which we're reading
3406 the data, and it means we have to spend time opening and
3407 reading the file, which could be a significant amount of
3408 time if the file is large. */
3409 cf->user_saved = TRUE;
3411 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3412 /* XXX - report errors if this fails?
3413 What should we return if it fails or is aborted? */
3414 switch (cf_read(cf)) {
3418 /* Just because we got an error, that doesn't mean we were unable
3419 to read any of the file; we handle what we could get from the
3423 case CF_READ_ABORTED:
3424 /* The user bailed out of re-reading the capture file; the
3425 capture file has been closed - just return (without
3426 changing any menu settings; "cf_close()" set them
3427 correctly for the "no capture file open" state). */
3430 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3436 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3441 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3442 gboolean for_writing, int file_type)
3445 /* Wiretap error. */
3448 case WTAP_ERR_NOT_REGULAR_FILE:
3449 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3450 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3454 case WTAP_ERR_RANDOM_OPEN_PIPE:
3455 /* Seen only when opening a capture file for reading. */
3456 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3457 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3461 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3462 /* Seen only when opening a capture file for reading. */
3463 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3464 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3468 case WTAP_ERR_UNSUPPORTED:
3469 /* Seen only when opening a capture file for reading. */
3470 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3471 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3473 filename, err_info);
3477 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3478 /* Seen only when opening a capture file for writing. */
3479 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3480 "The file \"%s\" is a pipe, and %s capture files can't be "
3481 "written to a pipe.",
3482 filename, wtap_file_type_string(file_type));
3485 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3486 /* Seen only when opening a capture file for writing. */
3487 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3488 "Wireshark doesn't support writing capture files in that format.");
3491 case WTAP_ERR_UNSUPPORTED_ENCAP:
3493 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3494 "Wireshark can't save this capture in that format.");
3496 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3497 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3499 filename, err_info);
3504 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3506 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3507 "Wireshark can't save this capture in that format.");
3509 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3510 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3515 case WTAP_ERR_BAD_RECORD:
3516 /* Seen only when opening a capture file for reading. */
3517 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3518 "The file \"%s\" appears to be damaged or corrupt.\n"
3520 filename, err_info);
3524 case WTAP_ERR_CANT_OPEN:
3526 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3527 "The file \"%s\" could not be created for some unknown reason.",
3530 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3531 "The file \"%s\" could not be opened for some unknown reason.",
3536 case WTAP_ERR_SHORT_READ:
3537 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3538 "The file \"%s\" appears to have been cut short"
3539 " in the middle of a packet or other data.",
3543 case WTAP_ERR_SHORT_WRITE:
3544 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3545 "A full header couldn't be written to the file \"%s\".",
3549 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3550 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3551 "Gzip compression not supported by this file type.");
3555 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3556 "The file \"%s\" could not be %s: %s.",
3558 for_writing ? "created" : "opened",
3559 wtap_strerror(err));
3564 open_failure_alert_box(filename, err, for_writing);
3569 file_rename_error_message(int err)
3572 static char errmsg_errno[1024+1];
3577 errmsg = "The path to the file \"%s\" doesn't exist.";
3581 errmsg = "You don't have permission to move the capture file to \"%s\".";
3585 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3586 "The file \"%%s\" could not be moved: %s.",
3587 wtap_strerror(err));
3588 errmsg = errmsg_errno;
3595 cf_read_error_message(int err, const gchar *err_info)
3597 static char errmsg_errno[1024+1];
3601 case WTAP_ERR_UNSUPPORTED_ENCAP:
3602 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3603 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
3607 case WTAP_ERR_BAD_RECORD:
3608 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3609 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3610 wtap_strerror(err), err_info);
3614 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3615 "An error occurred while reading from the file \"%%s\": %s.",
3616 wtap_strerror(err));
3619 return errmsg_errno;
3623 cf_write_failure_alert_box(const char *filename, int err)
3626 /* Wiretap error. */
3627 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3628 "An error occurred while writing to the file \"%s\": %s.",
3629 filename, wtap_strerror(err));
3632 write_failure_alert_box(filename, err);
3636 /* Check for write errors - if the file is being written to an NFS server,
3637 a write error may not show up until the file is closed, as NFS clients
3638 might not send writes to the server until the "write()" call finishes,
3639 so that the write may fail on the server but the "write()" may succeed. */
3641 cf_close_failure_alert_box(const char *filename, int err)
3644 /* Wiretap error. */
3647 case WTAP_ERR_CANT_CLOSE:
3648 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3649 "The file \"%s\" couldn't be closed for some unknown reason.",
3653 case WTAP_ERR_SHORT_WRITE:
3654 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3655 "Not all the packets could be written to the file \"%s\".",
3660 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3661 "An error occurred while closing the file \"%s\": %s.",
3662 filename, wtap_strerror(err));
3667 We assume that a close error from the OS is really a write error. */
3668 write_failure_alert_box(filename, err);
3672 /* Reload the current capture file. */
3674 cf_reload(capture_file *cf) {
3676 gboolean is_tempfile;
3679 /* If the file could be opened, "cf_open()" calls "cf_close()"
3680 to get rid of state for the old capture file before filling in state
3681 for the new capture file. "cf_close()" will remove the file if
3682 it's a temporary file; we don't want that to happen (for one thing,
3683 it'd prevent subsequent reopens from working). Remember whether it's
3684 a temporary file, mark it as not being a temporary file, and then
3685 reopen it as the type of file it was.
3687 Also, "cf_close()" will free "cf->filename", so we must make
3688 a copy of it first. */
3689 filename = g_strdup(cf->filename);
3690 is_tempfile = cf->is_tempfile;
3691 cf->is_tempfile = FALSE;
3692 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3693 switch (cf_read(cf)) {
3697 /* Just because we got an error, that doesn't mean we were unable
3698 to read any of the file; we handle what we could get from the
3702 case CF_READ_ABORTED:
3703 /* The user bailed out of re-reading the capture file; the
3704 capture file has been closed - just free the capture file name
3705 string and return (without changing the last containing
3711 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3712 Instead, the file was left open, so we should restore "cf->is_tempfile"
3715 XXX - change the menu? Presumably "cf_open()" will do that;
3716 make sure it does! */
3717 cf->is_tempfile = is_tempfile;
3719 /* "cf_open()" made a copy of the file name we handed it, so
3720 we should free up our copy. */
3724 /* Copies a file in binary mode, for those operating systems that care about
3726 * Returns TRUE on success, FALSE on failure. If a failure, it also
3727 * displays a simple dialog window with the error message.
3730 copy_binary_file(const char *from_filename, const char *to_filename)
3732 int from_fd, to_fd, nread, nwritten, err;
3735 /* Copy the raw bytes of the file. */
3736 from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
3738 open_failure_alert_box(from_filename, errno, FALSE);
3742 /* Use open() instead of creat() so that we can pass the O_BINARY
3743 flag, which is relevant on Win32; it appears that "creat()"
3744 may open the file in text mode, not binary mode, but we want
3745 to copy the raw bytes of the file, so we need the output file
3746 to be open in binary mode. */
3747 to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3749 open_failure_alert_box(to_filename, errno, TRUE);
3754 while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
3755 nwritten = eth_write(to_fd, pd, nread);
3756 if (nwritten < nread) {
3760 err = WTAP_ERR_SHORT_WRITE;
3761 write_failure_alert_box(to_filename, err);
3769 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3770 "An error occurred while reading from the file \"%s\": %s.",
3771 from_filename, strerror(err));
3777 if (eth_close(to_fd) < 0) {
3778 write_failure_alert_box(to_filename, errno);