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_dis_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_dis_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);
366 /* an out of memory exception occured, wait for a user button press to exit */
367 void outofmemory_cb(gpointer dialog _U_, gint btn _U_, gpointer data _U_)
373 cf_read(capture_file *cf)
377 const gchar *name_ptr;
379 char errmsg_errno[1024+1];
380 gchar err_str[2048+1];
382 progdlg_t *volatile progbar = NULL;
384 volatile gint64 size;
386 volatile float progbar_val;
388 gchar status_str[100];
389 volatile gint64 progbar_nextstep;
390 volatile gint64 progbar_quantum;
393 /* Compile the current display filter.
394 * We assume this will not fail since cf->dfilter is only set in
395 * cf_filter IFF the filter was valid.
399 dfilter_compile(cf->dfilter, &dfcode);
404 reset_tap_listeners();
405 tap_dfilter_dlg_update();
407 cf_callback_invoke(cf_cb_file_read_start, cf);
409 name_ptr = get_basename(cf->filename);
411 /* Find the size of the file. */
412 size = wtap_file_size(cf->wth, NULL);
414 /* Update the progress bar when it gets to this value. */
415 progbar_nextstep = 0;
416 /* When we reach the value that triggers a progress bar update,
417 bump that value by this amount. */
419 progbar_quantum = size/N_PROGBAR_UPDATES;
422 /* Progress so far. */
425 packet_list_freeze();
428 g_get_current_time(&start_time);
430 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
432 /* Create the progress bar if necessary.
433 We check on every iteration of the loop, so that it takes no
434 longer than the standard time to create it (otherwise, for a
435 large file, we might take considerably longer than that standard
436 time in order to get to the next progress bar step). */
437 if (progbar == NULL) {
438 progbar = delayed_create_progress_dlg("Loading", name_ptr,
439 TRUE, &stop_flag, &start_time, progbar_val);
442 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
443 when we update it, we have to run the GTK+ main loop to get it
444 to repaint what's pending, and doing so may involve an "ioctl()"
445 to see if there's any pending input from an X server, and doing
446 that for every packet can be costly, especially on a big file. */
447 if (data_offset >= progbar_nextstep) {
448 file_pos = wtap_read_so_far(cf->wth, NULL);
449 progbar_val = (gfloat) file_pos / (gfloat) size;
450 if (progbar_val > 1.0) {
451 /* The file probably grew while we were reading it.
452 Update file size, and try again. */
453 size = wtap_file_size(cf->wth, NULL);
455 progbar_val = (gfloat) file_pos / (gfloat) size;
456 /* If it's still > 1, either "wtap_file_size()" failed (in which
457 case there's not much we can do about it), or the file
458 *shrank* (in which case there's not much we can do about
459 it); just clip the progress value at 1.0. */
460 if (progbar_val > 1.0)
463 if (progbar != NULL) {
464 /* update the packet lists content on the first run or frequently on very large files */
465 /* (on smaller files the display update takes longer than reading the file) */
467 if(progbar_quantum > 500000 || progbar_nextstep == 0) {
469 if (auto_scroll_live && cf->plist_end != NULL)
470 packet_list_moveto_end();
471 packet_list_freeze();
475 g_snprintf(status_str, sizeof(status_str),
476 "%" PRId64 "KB of %" PRId64 "KB",
477 file_pos / 1024, size / 1024);
478 update_progress_dlg(progbar, progbar_val, status_str);
480 progbar_nextstep += progbar_quantum;
485 /* Well, the user decided to abort the read. He/She will be warned and
486 it might be enough for him/her to work with the already loaded
488 This is especially true for very large capture files, where you don't
489 want to wait loading the whole file (which may last minutes or even
490 hours even on fast machines) just to see that it was the wrong file. */
494 read_packet(cf, dfcode, data_offset);
496 CATCH(OutOfMemoryError) {
499 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
500 "%sOut Of Memory!%s\n"
502 "Sorry, but Wireshark has to terminate now!\n"
504 "Some infos / workarounds can be found at:\n"
505 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
506 simple_dialog_primary_start(), simple_dialog_primary_end());
507 /* we have to terminate, as we cannot recover from the memory error */
508 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
510 main_window_update();
511 /* XXX - how to avoid a busy wait? */
519 /* Cleanup and release all dfilter resources */
521 dfilter_free(dfcode);
524 /* We're done reading the file; destroy the progress bar if it was created. */
526 destroy_progress_dlg(progbar);
528 /* We're done reading sequentially through the file. */
529 cf->state = FILE_READ_DONE;
531 /* Close the sequential I/O side, to free up memory it requires. */
532 wtap_sequential_close(cf->wth);
534 /* Allow the protocol dissectors to free up memory that they
535 * don't need after the sequential run-through of the packets. */
536 postseq_cleanup_all_protocols();
538 /* Set the file encapsulation type now; we don't know what it is until
539 we've looked at all the packets, as we don't know until then whether
540 there's more than one type (and thus whether it's
541 WTAP_ENCAP_PER_PACKET). */
542 cf->lnk_t = wtap_file_encap(cf->wth);
544 cf->current_frame = cf->first_displayed;
547 cf_callback_invoke(cf_cb_file_read_finished, cf);
549 /* If we have any displayed packets to select, select the first of those
550 packets by making the first row the selected row. */
551 if (cf->first_displayed != NULL)
552 packet_list_select_row(0);
555 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
556 "%sFile loading was cancelled!%s\n"
558 "The remaining packets in the file were discarded.\n"
560 "As a lot of packets from the original file will be missing,\n"
561 "remember to be careful when saving the current content to a file.\n",
562 simple_dialog_primary_start(), simple_dialog_primary_end());
563 return CF_READ_ERROR;
567 /* Put up a message box noting that the read failed somewhere along
568 the line. Don't throw out the stuff we managed to read, though,
572 case WTAP_ERR_UNSUPPORTED_ENCAP:
573 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
574 "The capture file has a packet with a network type that Wireshark doesn't support.\n(%s)",
577 errmsg = errmsg_errno;
580 case WTAP_ERR_CANT_READ:
581 errmsg = "An attempt to read from the capture file failed for"
582 " some unknown reason.";
585 case WTAP_ERR_SHORT_READ:
586 errmsg = "The capture file appears to have been cut short"
587 " in the middle of a packet.";
590 case WTAP_ERR_BAD_RECORD:
591 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
592 "The capture file appears to be damaged or corrupt.\n(%s)",
595 errmsg = errmsg_errno;
599 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
600 "An error occurred while reading the"
601 " capture file: %s.", wtap_strerror(err));
602 errmsg = errmsg_errno;
605 g_snprintf(err_str, sizeof err_str, errmsg);
606 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
607 return CF_READ_ERROR;
614 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
616 cf_status_t cf_status;
618 cf_status = cf_open(cf, fname, is_tempfile, err);
623 cf_continue_tail(capture_file *cf, volatile int to_read, int *err)
625 gint64 data_offset = 0;
627 volatile int newly_displayed_packets = 0;
630 /* Compile the current display filter.
631 * We assume this will not fail since cf->dfilter is only set in
632 * cf_filter IFF the filter was valid.
636 dfilter_compile(cf->dfilter, &dfcode);
641 packet_list_freeze();
643 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: %u new: %u", cf->count, to_read);*/
645 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
646 if (cf->state == FILE_READ_ABORTED) {
647 /* Well, the user decided to exit Wireshark. Break out of the
648 loop, and let the code below (which is called even if there
649 aren't any packets left to read) exit. */
653 if (read_packet(cf, dfcode, data_offset) != -1) {
654 newly_displayed_packets++;
657 CATCH(OutOfMemoryError) {
660 dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
661 "%sOut Of Memory!%s\n"
663 "Sorry, but Wireshark has to terminate now!\n"
665 "The capture file is not lost, it can be found at:\n"
668 "Some infos / workarounds can be found at:\n"
669 "http://wiki.wireshark.org/KnownBugs/OutOfMemory",
670 simple_dialog_primary_start(), simple_dialog_primary_end(), cf->filename);
671 /* we have to terminate, as we cannot recover from the memory error */
672 simple_dialog_set_cb(dialog, outofmemory_cb, NULL);
674 main_window_update();
675 /* XXX - how to avoid a busy wait? */
679 return CF_READ_ABORTED;
685 /* Cleanup and release all dfilter resources */
687 dfilter_free(dfcode);
690 /*g_log(NULL, G_LOG_LEVEL_MESSAGE, "cf_continue_tail: count %u state: %u err: %u",
691 cf->count, cf->state, *err);*/
693 /* XXX - this causes "flickering" of the list */
696 /* moving to the end of the packet list - if the user requested so and
697 we have some new packets.
698 this doesn't seem to work well with a frozen GTK_Clist, so do this after
699 packet_list_thaw() is done, see bugzilla 1188 */
700 /* XXX - this cheats and looks inside the packet list to find the final
702 if (newly_displayed_packets && auto_scroll_live && cf->plist_end != NULL)
703 packet_list_moveto_end();
705 if (cf->state == FILE_READ_ABORTED) {
706 /* Well, the user decided to exit Wireshark. Return CF_READ_ABORTED
707 so that our caller can kill off the capture child process;
708 this will cause an EOF on the pipe from the child, so
709 "cf_finish_tail()" will be called, and it will clean up
711 return CF_READ_ABORTED;
712 } else if (*err != 0) {
713 /* We got an error reading the capture file.
714 XXX - pop up a dialog box instead? */
715 g_warning("Error \"%s\" while reading: \"%s\"\n",
716 wtap_strerror(*err), cf->filename);
718 return CF_READ_ERROR;
724 cf_finish_tail(capture_file *cf, int *err)
730 /* Compile the current display filter.
731 * We assume this will not fail since cf->dfilter is only set in
732 * cf_filter IFF the filter was valid.
736 dfilter_compile(cf->dfilter, &dfcode);
739 if(cf->wth == NULL) {
741 return CF_READ_ERROR;
744 packet_list_freeze();
746 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
747 if (cf->state == FILE_READ_ABORTED) {
748 /* Well, the user decided to abort the read. Break out of the
749 loop, and let the code below (which is called even if there
750 aren't any packets left to read) exit. */
753 read_packet(cf, dfcode, data_offset);
756 /* Cleanup and release all dfilter resources */
758 dfilter_free(dfcode);
763 if (cf->state == FILE_READ_ABORTED) {
764 /* Well, the user decided to abort the read. We're only called
765 when the child capture process closes the pipe to us (meaning
766 it's probably exited), so we can just close the capture
767 file; we return CF_READ_ABORTED so our caller can do whatever
768 is appropriate when that happens. */
770 return CF_READ_ABORTED;
773 if (auto_scroll_live && cf->plist_end != NULL)
774 /* XXX - this cheats and looks inside the packet list to find the final
776 packet_list_moveto_end();
778 /* We're done reading sequentially through the file. */
779 cf->state = FILE_READ_DONE;
781 /* We're done reading sequentially through the file; close the
782 sequential I/O side, to free up memory it requires. */
783 wtap_sequential_close(cf->wth);
785 /* Allow the protocol dissectors to free up memory that they
786 * don't need after the sequential run-through of the packets. */
787 postseq_cleanup_all_protocols();
789 /* Set the file encapsulation type now; we don't know what it is until
790 we've looked at all the packets, as we don't know until then whether
791 there's more than one type (and thus whether it's
792 WTAP_ENCAP_PER_PACKET). */
793 cf->lnk_t = wtap_file_encap(cf->wth);
796 /* We got an error reading the capture file.
797 XXX - pop up a dialog box? */
798 return CF_READ_ERROR;
803 #endif /* HAVE_LIBPCAP */
806 cf_get_display_name(capture_file *cf)
808 const gchar *displayname;
810 /* Return a name to use in displays */
811 if (!cf->is_tempfile) {
812 /* Get the last component of the file name, and use that. */
814 displayname = get_basename(cf->filename);
816 displayname="(No file)";
819 /* The file we read is a temporary file from a live capture;
820 we don't mention its name. */
821 displayname = "(Untitled)";
826 /* XXX - use a macro instead? */
828 cf_get_packet_count(capture_file *cf)
833 /* XXX - use a macro instead? */
835 cf_set_packet_count(capture_file *cf, int packet_count)
837 cf->count = packet_count;
840 /* XXX - use a macro instead? */
842 cf_is_tempfile(capture_file *cf)
844 return cf->is_tempfile;
847 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
849 cf->is_tempfile = is_tempfile;
853 /* XXX - use a macro instead? */
854 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
856 cf->drops_known = drops_known;
859 /* XXX - use a macro instead? */
860 void cf_set_drops(capture_file *cf, guint32 drops)
865 /* XXX - use a macro instead? */
866 gboolean cf_get_drops_known(capture_file *cf)
868 return cf->drops_known;
871 /* XXX - use a macro instead? */
872 guint32 cf_get_drops(capture_file *cf)
877 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
883 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
885 union wtap_pseudo_header *pseudo_header, const guchar *buf,
889 gboolean create_proto_tree = FALSE;
892 /* just add some value here until we know if it is being displayed or not */
893 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
895 /* If we don't have the time stamp of the first packet in the
896 capture, it's because this is the first packet. Save the time
897 stamp of this packet as the time stamp of the first packet. */
898 if (nstime_is_zero(&first_ts)) {
899 first_ts = fdata->abs_ts;
901 /* if this frames is marked as a reference time frame, reset
902 firstsec and firstusec to this frame */
903 if(fdata->flags.ref_time){
904 first_ts = fdata->abs_ts;
907 /* If we don't have the time stamp of the previous displayed packet,
908 it's because this is the first displayed packet. Save the time
909 stamp of this packet as the time stamp of the previous displayed
911 if (nstime_is_zero(&prev_dis_ts)) {
912 prev_dis_ts = fdata->abs_ts;
915 /* Get the time elapsed between the first packet and this packet. */
916 nstime_delta(&fdata->rel_ts, &fdata->abs_ts, &first_ts);
918 /* If it's greater than the current elapsed time, set the elapsed time
919 to it (we check for "greater than" so as not to be confused by
920 time moving backwards). */
921 if ((gint32)cf->elapsed_time.secs < fdata->rel_ts.secs
922 || ((gint32)cf->elapsed_time.secs == fdata->rel_ts.secs && (gint32)cf->elapsed_time.nsecs < fdata->rel_ts.nsecs)) {
923 cf->elapsed_time = fdata->rel_ts;
926 /* Get the time elapsed between the previous displayed packet and
928 nstime_delta(&fdata->del_dis_ts, &fdata->abs_ts, &prev_dis_ts);
932 we have a display filter and are re-applying it;
934 we have a list of color filters;
936 we have tap listeners;
938 allocate a protocol tree root node, so that we'll construct
939 a protocol tree against which a filter expression can be
941 if ((dfcode != NULL && refilter) || color_filters_used()
942 || num_tap_filters != 0)
943 create_proto_tree = TRUE;
945 /* Dissect the frame. */
946 edt = epan_dissect_new(create_proto_tree, FALSE);
948 if (dfcode != NULL && refilter) {
949 epan_dissect_prime_dfilter(edt, dfcode);
951 /* prepare color filters */
952 if (color_filters_used()) {
953 color_filters_prime_edt(edt);
956 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
957 tap_push_tapped_queue(edt);
959 /* If we have a display filter, apply it if we're refiltering, otherwise
960 leave the "passed_dfilter" flag alone.
962 If we don't have a display filter, set "passed_dfilter" to 1. */
963 if (dfcode != NULL) {
965 fdata->flags.passed_dfilter = dfilter_apply_edt(dfcode, edt) ? 1 : 0;
968 fdata->flags.passed_dfilter = 1;
970 if( (fdata->flags.passed_dfilter)
971 || (edt->pi.fd->flags.ref_time) ){
972 /* This frame either passed the display filter list or is marked as
973 a time reference frame. All time reference frames are displayed
974 even if they dont pass the display filter */
975 /* if this was a TIME REF frame we should reset the cul bytes field */
976 if(edt->pi.fd->flags.ref_time){
977 cum_bytes = fdata->pkt_len;
978 fdata->cum_bytes = cum_bytes;
981 /* increase cum_bytes with this packets length */
982 cum_bytes += fdata->pkt_len;
984 epan_dissect_fill_in_columns(edt);
986 /* If we haven't yet seen the first frame, this is it.
988 XXX - we must do this before we add the row to the display,
989 as, if the display's GtkCList's selection mode is
990 GTK_SELECTION_BROWSE, when the first entry is added to it,
991 "cf_select_packet()" will be called, and it will fetch the row
992 data for the 0th row, and will get a null pointer rather than
993 "fdata", as "gtk_clist_append()" won't yet have returned and
994 thus "gtk_clist_set_row_data()" won't yet have been called.
996 We thus need to leave behind bread crumbs so that
997 "cf_select_packet()" can find this frame. See the comment
998 in "cf_select_packet()". */
999 if (cf->first_displayed == NULL)
1000 cf->first_displayed = fdata;
1002 /* This is the last frame we've seen so far. */
1003 cf->last_displayed = fdata;
1005 row = packet_list_append(cf->cinfo.col_data, fdata);
1007 /* colorize packet: if packet is marked, use preferences,
1008 otherwise try to apply color filters */
1009 if (fdata->flags.marked) {
1010 fdata->color_filter = NULL;
1011 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
1013 fdata->color_filter = color_filters_colorize_packet(row, edt);
1016 /* Set the time of the previous displayed frame to the time of this
1018 prev_dis_ts = fdata->abs_ts;
1020 cf->displayed_count++;
1022 /* This frame didn't pass the display filter, so it's not being added
1023 to the clist, and thus has no row. */
1026 epan_dissect_free(edt);
1030 /* read in a new packet */
1031 /* returns the row of the new packet in the packet list or -1 if not displayed */
1033 read_packet(capture_file *cf, dfilter_t *dfcode, gint64 offset)
1035 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
1036 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
1037 const guchar *buf = wtap_buf_ptr(cf->wth);
1040 frame_data *plist_end;
1041 epan_dissect_t *edt;
1044 /* Allocate the next list entry, and add it to the list. */
1045 fdata = g_mem_chunk_alloc(cf->plist_chunk);
1051 fdata->pkt_len = phdr->len;
1052 fdata->cap_len = phdr->caplen;
1053 fdata->file_off = offset;
1054 fdata->lnk_t = phdr->pkt_encap;
1055 fdata->flags.encoding = CHAR_ASCII;
1056 fdata->flags.visited = 0;
1057 fdata->flags.marked = 0;
1058 fdata->flags.ref_time = 0;
1059 fdata->color_filter = NULL;
1061 fdata->abs_ts.secs = phdr->ts.secs;
1062 fdata->abs_ts.nsecs = phdr->ts.nsecs;
1064 if (cf->plist_end != NULL)
1065 nstime_delta(&fdata->del_cap_ts, &fdata->abs_ts, &cf->plist_end->abs_ts);
1067 nstime_set_zero(&fdata->del_cap_ts);
1071 edt = epan_dissect_new(TRUE, FALSE);
1072 epan_dissect_prime_dfilter(edt, cf->rfcode);
1073 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
1074 passed = dfilter_apply_edt(cf->rfcode, edt);
1075 epan_dissect_free(edt);
1078 plist_end = cf->plist_end;
1079 fdata->prev = plist_end;
1080 if (plist_end != NULL)
1081 plist_end->next = fdata;
1084 cf->plist_end = fdata;
1087 cf->f_datalen = offset + phdr->caplen;
1088 fdata->num = cf->count;
1089 row = add_packet_to_packet_list(fdata, cf, dfcode, pseudo_header, buf, TRUE);
1091 /* XXX - if we didn't have read filters, or if we could avoid
1092 allocating the "frame_data" structure until we knew whether
1093 the frame passed the read filter, we could use a G_ALLOC_ONLY
1096 ...but, at least in one test I did, where I just made the chunk
1097 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
1098 seem to save a noticeable amount of time or space. */
1099 g_mem_chunk_free(cf->plist_chunk, fdata);
1106 cf_merge_files(char **out_filenamep, int in_file_count,
1107 char *const *in_filenames, int file_type, gboolean do_append)
1109 merge_in_file_t *in_files;
1112 char tmpname[128+1];
1115 int open_err, read_err, write_err, close_err;
1119 char errmsg_errno[1024+1];
1120 gchar err_str[2048+1];
1122 gboolean got_read_error = FALSE, got_write_error = FALSE;
1124 progdlg_t *progbar = NULL;
1126 gint64 f_len, file_pos;
1128 GTimeVal start_time;
1129 gchar status_str[100];
1130 gint64 progbar_nextstep;
1131 gint64 progbar_quantum;
1133 /* open the input files */
1134 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
1135 &open_err, &err_info, &err_fileno)) {
1137 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
1142 if (*out_filenamep != NULL) {
1143 out_filename = *out_filenamep;
1144 out_fd = eth_open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
1148 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
1151 out_filename = g_strdup(tmpname);
1152 *out_filenamep = out_filename;
1156 merge_close_in_files(in_file_count, in_files);
1158 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
1162 pdh = wtap_dump_fdopen(out_fd, file_type,
1163 merge_select_frame_type(in_file_count, in_files),
1164 merge_max_snapshot_length(in_file_count, in_files),
1165 FALSE /* compressed */, &open_err);
1168 merge_close_in_files(in_file_count, in_files);
1170 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
1175 /* Get the sum of the sizes of all the files. */
1177 for (i = 0; i < in_file_count; i++)
1178 f_len += in_files[i].size;
1180 /* Update the progress bar when it gets to this value. */
1181 progbar_nextstep = 0;
1182 /* When we reach the value that triggers a progress bar update,
1183 bump that value by this amount. */
1184 progbar_quantum = f_len/N_PROGBAR_UPDATES;
1185 /* Progress so far. */
1189 g_get_current_time(&start_time);
1191 /* do the merge (or append) */
1194 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
1197 wth = merge_read_packet(in_file_count, in_files, &read_err,
1201 got_read_error = TRUE;
1205 /* Get the sum of the data offsets in all of the files. */
1207 for (i = 0; i < in_file_count; i++)
1208 data_offset += in_files[i].data_offset;
1210 /* Create the progress bar if necessary.
1211 We check on every iteration of the loop, so that it takes no
1212 longer than the standard time to create it (otherwise, for a
1213 large file, we might take considerably longer than that standard
1214 time in order to get to the next progress bar step). */
1215 if (progbar == NULL) {
1216 progbar = delayed_create_progress_dlg("Merging", "files",
1217 FALSE, &stop_flag, &start_time, progbar_val);
1220 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1221 when we update it, we have to run the GTK+ main loop to get it
1222 to repaint what's pending, and doing so may involve an "ioctl()"
1223 to see if there's any pending input from an X server, and doing
1224 that for every packet can be costly, especially on a big file. */
1225 if (data_offset >= progbar_nextstep) {
1226 /* Get the sum of the seek positions in all of the files. */
1228 for (i = 0; i < in_file_count; i++)
1229 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
1230 progbar_val = (gfloat) file_pos / (gfloat) f_len;
1231 if (progbar_val > 1.0) {
1232 /* Some file probably grew while we were reading it.
1233 That "shouldn't happen", so we'll just clip the progress
1237 if (progbar != NULL) {
1238 g_snprintf(status_str, sizeof(status_str),
1239 "%" PRId64 "KB of %" PRId64 "KB",
1240 file_pos / 1024, f_len / 1024);
1241 update_progress_dlg(progbar, progbar_val, status_str);
1243 progbar_nextstep += progbar_quantum;
1247 /* Well, the user decided to abort the merge. */
1251 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1252 wtap_buf_ptr(wth), &write_err)) {
1253 got_write_error = TRUE;
1258 /* We're done merging the files; destroy the progress bar if it was created. */
1259 if (progbar != NULL)
1260 destroy_progress_dlg(progbar);
1262 merge_close_in_files(in_file_count, in_files);
1263 if (!got_read_error && !got_write_error) {
1264 if (!wtap_dump_close(pdh, &write_err))
1265 got_write_error = TRUE;
1267 wtap_dump_close(pdh, &close_err);
1269 if (got_read_error) {
1271 * Find the file on which we got the error, and report the error.
1273 for (i = 0; i < in_file_count; i++) {
1274 if (in_files[i].state == GOT_ERROR) {
1275 /* Put up a message box noting that a read failed somewhere along
1279 case WTAP_ERR_UNSUPPORTED_ENCAP:
1280 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1281 "The capture file %%s has a packet with a network type that Wireshark doesn't support.\n(%s)",
1284 errmsg = errmsg_errno;
1287 case WTAP_ERR_CANT_READ:
1288 errmsg = "An attempt to read from the capture file %s failed for"
1289 " some unknown reason.";
1292 case WTAP_ERR_SHORT_READ:
1293 errmsg = "The capture file %s appears to have been cut short"
1294 " in the middle of a packet.";
1297 case WTAP_ERR_BAD_RECORD:
1298 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1299 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1302 errmsg = errmsg_errno;
1306 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1307 "An error occurred while reading the"
1308 " capture file %%s: %s.", wtap_strerror(read_err));
1309 errmsg = errmsg_errno;
1312 g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
1313 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
1318 if (got_write_error) {
1319 /* Put up an alert box for the write error. */
1320 cf_write_failure_alert_box(out_filename, write_err);
1323 if (got_read_error || got_write_error || stop_flag) {
1324 /* Callers aren't expected to treat an error or an explicit abort
1325 differently - we put up error dialogs ourselves, so they don't
1333 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1335 const char *filter_new = dftext ? dftext : "";
1336 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1339 /* if new filter equals old one, do nothing unless told to do so */
1340 if (!force && strcmp(filter_new, filter_old) == 0) {
1346 if (dftext == NULL) {
1347 /* The new filter is an empty filter (i.e., display all packets).
1348 * so leave dfcode==NULL
1352 * We have a filter; make a copy of it (as we'll be saving it),
1353 * and try to compile it.
1355 dftext = g_strdup(dftext);
1356 if (!dfilter_compile(dftext, &dfcode)) {
1357 /* The attempt failed; report an error. */
1358 gchar *safe_dftext = simple_dialog_format_message(dftext);
1359 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1361 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1364 "The following display filter isn't a valid display filter:\n%s\n"
1365 "See the help for a description of the display filter syntax.",
1366 simple_dialog_primary_start(), safe_dfilter_error_msg,
1367 simple_dialog_primary_end(), safe_dftext);
1368 g_free(safe_dfilter_error_msg);
1369 g_free(safe_dftext);
1375 if (dfcode == NULL) {
1376 /* Yes - free the filter text, and set it to null. */
1382 /* We have a valid filter. Replace the current filter. */
1383 if (cf->dfilter != NULL)
1384 g_free(cf->dfilter);
1385 cf->dfilter = dftext;
1387 /* Now rescan the packet list, applying the new filter, but not
1388 throwing away information constructed on a previous pass. */
1389 if (dftext == NULL) {
1390 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1392 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1395 /* Cleanup and release all dfilter resources */
1396 if (dfcode != NULL){
1397 dfilter_free(dfcode);
1403 cf_colorize_packets(capture_file *cf)
1405 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1409 cf_reftime_packets(capture_file *cf)
1411 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1415 cf_redissect_packets(capture_file *cf)
1417 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1420 /* Rescan the list of packets, reconstructing the CList.
1422 "action" describes why we're doing this; it's used in the progress
1425 "action_item" describes what we're doing; it's used in the progress
1428 "refilter" is TRUE if we need to re-evaluate the filter expression.
1430 "redissect" is TRUE if we need to make the dissectors reconstruct
1431 any state information they have (because a preference that affects
1432 some dissector has changed, meaning some dissector might construct
1433 its state differently from the way it was constructed the last time). */
1435 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1436 gboolean refilter, gboolean redissect)
1439 progdlg_t *progbar = NULL;
1444 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1445 int selected_row, prev_row, preceding_row, following_row;
1446 gboolean selected_frame_seen;
1449 GTimeVal start_time;
1450 gchar status_str[100];
1451 int progbar_nextstep;
1452 int progbar_quantum;
1455 /* Compile the current display filter.
1456 * We assume this will not fail since cf->dfilter is only set in
1457 * cf_filter IFF the filter was valid.
1461 dfilter_compile(cf->dfilter, &dfcode);
1465 reset_tap_listeners();
1466 /* Which frame, if any, is the currently selected frame?
1467 XXX - should the selected frame or the focus frame be the "current"
1468 frame, that frame being the one from which "Find Frame" searches
1470 selected_frame = cf->current_frame;
1472 /* We don't yet know what row that frame will be on, if any, after we
1473 rebuild the clist, however. */
1477 /* We need to re-initialize all the state information that protocols
1478 keep, because some preference that controls a dissector has changed,
1479 which might cause the state information to be constructed differently
1480 by that dissector. */
1482 /* Initialize all data structures used for dissection. */
1486 /* Freeze the packet list while we redo it, so we don't get any
1487 screen updates while it happens. */
1488 packet_list_freeze();
1491 packet_list_clear();
1493 /* We don't yet know which will be the first and last frames displayed. */
1494 cf->first_displayed = NULL;
1495 cf->last_displayed = NULL;
1497 /* We currently don't display any packets */
1498 cf->displayed_count = 0;
1500 /* Iterate through the list of frames. Call a routine for each frame
1501 to check whether it should be displayed and, if so, add it to
1502 the display list. */
1503 nstime_set_zero(&first_ts);
1504 nstime_set_zero(&prev_dis_ts);
1506 /* Update the progress bar when it gets to this value. */
1507 progbar_nextstep = 0;
1508 /* When we reach the value that triggers a progress bar update,
1509 bump that value by this amount. */
1510 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1511 /* Count of packets at which we've looked. */
1513 /* Progress so far. */
1517 g_get_current_time(&start_time);
1519 row = -1; /* no previous row yet */
1524 preceding_frame = NULL;
1526 following_frame = NULL;
1528 selected_frame_seen = FALSE;
1530 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1531 /* Create the progress bar if necessary.
1532 We check on every iteration of the loop, so that it takes no
1533 longer than the standard time to create it (otherwise, for a
1534 large file, we might take considerably longer than that standard
1535 time in order to get to the next progress bar step). */
1536 if (progbar == NULL)
1537 progbar = delayed_create_progress_dlg(action, action_item, TRUE,
1538 &stop_flag, &start_time,
1541 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1542 when we update it, we have to run the GTK+ main loop to get it
1543 to repaint what's pending, and doing so may involve an "ioctl()"
1544 to see if there's any pending input from an X server, and doing
1545 that for every packet can be costly, especially on a big file. */
1546 if (count >= progbar_nextstep) {
1547 /* let's not divide by zero. I should never be started
1548 * with count == 0, so let's assert that
1550 g_assert(cf->count > 0);
1551 progbar_val = (gfloat) count / cf->count;
1553 if (progbar != NULL) {
1554 g_snprintf(status_str, sizeof(status_str),
1555 "%4u of %u frames", count, cf->count);
1556 update_progress_dlg(progbar, progbar_val, status_str);
1559 progbar_nextstep += progbar_quantum;
1563 /* Well, the user decided to abort the filtering. Just stop.
1565 XXX - go back to the previous filter? Users probably just
1566 want not to wait for a filtering operation to finish;
1567 unless we cancel by having no filter, reverting to the
1568 previous filter will probably be even more expensive than
1569 continuing the filtering, as it involves going back to the
1570 beginning and filtering, and even with no filter we currently
1571 have to re-generate the entire clist, which is also expensive.
1573 I'm not sure what Network Monitor does, but it doesn't appear
1574 to give you an unfiltered display if you cancel. */
1581 /* Since all state for the frame was destroyed, mark the frame
1582 * as not visited, free the GSList referring to the state
1583 * data (the per-frame data itself was freed by
1584 * "init_dissection()"), and null out the GSList pointer. */
1585 fdata->flags.visited = 0;
1587 g_slist_free(fdata->pfd);
1592 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1593 cf->pd, fdata->cap_len, &err, &err_info)) {
1594 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1595 cf_read_error_message(err, err_info), cf->filename);
1599 /* If the previous frame is displayed, and we haven't yet seen the
1600 selected frame, remember that frame - it's the closest one we've
1601 yet seen before the selected frame. */
1602 if (prev_row != -1 && !selected_frame_seen) {
1603 preceding_row = prev_row;
1604 preceding_frame = prev_frame;
1606 row = add_packet_to_packet_list(fdata, cf, dfcode, &cf->pseudo_header, cf->pd,
1609 /* If this frame is displayed, and this is the first frame we've
1610 seen displayed after the selected frame, remember this frame -
1611 it's the closest one we've yet seen at or after the selected
1613 if (row != -1 && selected_frame_seen && following_row == -1) {
1614 following_row = row;
1615 following_frame = fdata;
1617 if (fdata == selected_frame) {
1619 selected_frame_seen = TRUE;
1622 /* Remember this row/frame - it'll be the previous row/frame
1623 on the next pass through the loop. */
1628 /* Re-sort the list using the previously selected order */
1629 packet_list_set_sort_column();
1632 /* Clear out what remains of the visited flags and per-frame data
1635 XXX - that may cause various forms of bogosity when dissecting
1636 these frames, as they won't have been seen by this sequential
1637 pass, but the only alternative I see is to keep scanning them
1638 even though the user requested that the scan stop, and that
1639 would leave the user stuck with an Wireshark grinding on
1640 until it finishes. Should we just stick them with that? */
1641 for (; fdata != NULL; fdata = fdata->next) {
1642 fdata->flags.visited = 0;
1644 g_slist_free(fdata->pfd);
1650 /* We're done filtering the packets; destroy the progress bar if it
1652 if (progbar != NULL)
1653 destroy_progress_dlg(progbar);
1655 /* Unfreeze the packet list. */
1658 if (selected_row == -1) {
1659 /* The selected frame didn't pass the filter. */
1660 if (selected_frame == NULL) {
1661 /* That's because there *was* no selected frame. Make the first
1662 displayed frame the current frame. */
1665 /* Find the nearest displayed frame to the selected frame (whether
1666 it's before or after that frame) and make that the current frame.
1667 If the next and previous displayed frames are equidistant from the
1668 selected frame, choose the next one. */
1669 g_assert(following_frame == NULL ||
1670 following_frame->num >= selected_frame->num);
1671 g_assert(preceding_frame == NULL ||
1672 preceding_frame->num <= selected_frame->num);
1673 if (following_frame == NULL) {
1674 /* No frame after the selected frame passed the filter, so we
1675 have to select the last displayed frame before the selected
1677 selected_row = preceding_row;
1678 } else if (preceding_frame == NULL) {
1679 /* No frame before the selected frame passed the filter, so we
1680 have to select the first displayed frame after the selected
1682 selected_row = following_row;
1684 /* Frames before and after the selected frame passed the filter, so
1685 we'll select the previous frame */
1686 selected_row = preceding_row;
1691 if (selected_row == -1) {
1692 /* There are no frames displayed at all. */
1693 cf_unselect_packet(cf);
1695 /* Either the frame that was selected passed the filter, or we've
1696 found the nearest displayed frame to that frame. Select it, make
1697 it the focus row, and make it visible. */
1698 packet_list_set_selected_row(selected_row);
1701 /* Cleanup and release all dfilter resources */
1702 if (dfcode != NULL){
1703 dfilter_free(dfcode);
1714 process_specified_packets(capture_file *cf, packet_range_t *range,
1715 const char *string1, const char *string2, gboolean terminate_is_stop,
1716 gboolean (*callback)(capture_file *, frame_data *,
1717 union wtap_pseudo_header *, const guint8 *, void *),
1718 void *callback_args)
1723 union wtap_pseudo_header pseudo_header;
1724 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1725 psp_return_t ret = PSP_FINISHED;
1727 progdlg_t *progbar = NULL;
1730 gboolean progbar_stop_flag;
1731 GTimeVal progbar_start_time;
1732 gchar progbar_status_str[100];
1733 int progbar_nextstep;
1734 int progbar_quantum;
1735 range_process_e process_this;
1737 /* Update the progress bar when it gets to this value. */
1738 progbar_nextstep = 0;
1739 /* When we reach the value that triggers a progress bar update,
1740 bump that value by this amount. */
1741 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1742 /* Count of packets at which we've looked. */
1744 /* Progress so far. */
1747 progbar_stop_flag = FALSE;
1748 g_get_current_time(&progbar_start_time);
1750 packet_range_process_init(range);
1752 /* Iterate through the list of packets, printing the packets that
1753 were selected by the current display filter. */
1754 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1755 /* Create the progress bar if necessary.
1756 We check on every iteration of the loop, so that it takes no
1757 longer than the standard time to create it (otherwise, for a
1758 large file, we might take considerably longer than that standard
1759 time in order to get to the next progress bar step). */
1760 if (progbar == NULL)
1761 progbar = delayed_create_progress_dlg(string1, string2,
1764 &progbar_start_time,
1767 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1768 when we update it, we have to run the GTK+ main loop to get it
1769 to repaint what's pending, and doing so may involve an "ioctl()"
1770 to see if there's any pending input from an X server, and doing
1771 that for every packet can be costly, especially on a big file. */
1772 if (progbar_count >= progbar_nextstep) {
1773 /* let's not divide by zero. I should never be started
1774 * with count == 0, so let's assert that
1776 g_assert(cf->count > 0);
1777 progbar_val = (gfloat) progbar_count / cf->count;
1779 if (progbar != NULL) {
1780 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1781 "%4u of %u packets", progbar_count, cf->count);
1782 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1785 progbar_nextstep += progbar_quantum;
1788 if (progbar_stop_flag) {
1789 /* Well, the user decided to abort the operation. Just stop,
1790 and arrange to return PSP_STOPPED to our caller, so they know
1791 it was stopped explicitly. */
1798 /* do we have to process this packet? */
1799 process_this = packet_range_process_packet(range, fdata);
1800 if (process_this == range_process_next) {
1801 /* this packet uninteresting, continue with next one */
1803 } else if (process_this == range_processing_finished) {
1804 /* all interesting packets processed, stop the loop */
1808 /* Get the packet */
1809 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1810 pd, fdata->cap_len, &err, &err_info)) {
1811 /* Attempt to get the packet failed. */
1812 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1813 cf_read_error_message(err, err_info), cf->filename);
1817 /* Process the packet */
1818 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1819 /* Callback failed. We assume it reported the error appropriately. */
1825 /* We're done printing the packets; destroy the progress bar if
1827 if (progbar != NULL)
1828 destroy_progress_dlg(progbar);
1834 retap_packet(capture_file *cf _U_, frame_data *fdata,
1835 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1838 column_info *cinfo = argsp;
1839 epan_dissect_t *edt;
1841 /* If we have tap listeners, allocate a protocol tree root node, so that
1842 we'll construct a protocol tree against which a filter expression can
1844 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1845 tap_queue_init(edt);
1846 epan_dissect_run(edt, pseudo_header, pd, fdata, cinfo);
1847 tap_push_tapped_queue(edt);
1848 epan_dissect_free(edt);
1854 cf_retap_packets(capture_file *cf, gboolean do_columns)
1856 packet_range_t range;
1858 /* Reset the tap listeners. */
1859 reset_tap_listeners();
1861 /* Iterate through the list of packets, dissecting all packets and
1862 re-running the taps. */
1863 packet_range_init(&range);
1864 packet_range_process_init(&range);
1865 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1866 "all packets", TRUE, retap_packet,
1867 do_columns ? &cf->cinfo : NULL)) {
1869 /* Completed successfully. */
1873 /* Well, the user decided to abort the refiltering.
1874 Return CF_READ_ABORTED so our caller knows they did that. */
1875 return CF_READ_ABORTED;
1878 /* Error while retapping. */
1879 return CF_READ_ERROR;
1882 g_assert_not_reached();
1887 print_args_t *print_args;
1888 gboolean print_header_line;
1889 char *header_line_buf;
1890 int header_line_buf_len;
1891 gboolean print_formfeed;
1892 gboolean print_separator;
1896 } print_callback_args_t;
1899 print_packet(capture_file *cf, frame_data *fdata,
1900 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1903 print_callback_args_t *args = argsp;
1904 epan_dissect_t *edt;
1910 gboolean proto_tree_needed;
1911 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1912 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1914 /* Create the protocol tree, and make it visible, if we're printing
1915 the dissection or the hex data.
1916 XXX - do we need it if we're just printing the hex data? */
1918 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1919 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1921 /* Fill in the column information if we're printing the summary
1923 if (args->print_args->print_summary) {
1924 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1925 epan_dissect_fill_in_columns(edt);
1927 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1929 if (args->print_formfeed) {
1930 if (!new_page(args->print_args->stream))
1933 if (args->print_separator) {
1934 if (!print_line(args->print_args->stream, 0, ""))
1940 * We generate bookmarks, if the output format supports them.
1941 * The name is "__frameN__".
1943 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1945 if (args->print_args->print_summary) {
1946 if (args->print_header_line) {
1947 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1949 args->print_header_line = FALSE; /* we might not need to print any more */
1951 cp = &args->line_buf[0];
1953 for (i = 0; i < cf->cinfo.num_cols; i++) {
1954 /* Find the length of the string for this column. */
1955 column_len = strlen(cf->cinfo.col_data[i]);
1956 if (args->col_widths[i] > column_len)
1957 column_len = args->col_widths[i];
1959 /* Make sure there's room in the line buffer for the column; if not,
1960 double its length. */
1961 line_len += column_len + 1; /* "+1" for space */
1962 if (line_len > args->line_buf_len) {
1963 cp_off = cp - args->line_buf;
1964 args->line_buf_len = 2 * line_len;
1965 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1966 cp = args->line_buf + cp_off;
1969 /* Right-justify the packet number column. */
1970 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1971 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1973 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1975 if (i != cf->cinfo.num_cols - 1)
1981 * Generate a bookmark, using the summary line as the title.
1983 if (!print_bookmark(args->print_args->stream, bookmark_name,
1987 if (!print_line(args->print_args->stream, 0, args->line_buf))
1991 * Generate a bookmark, using "Frame N" as the title, as we're not
1992 * printing the summary line.
1994 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1995 if (!print_bookmark(args->print_args->stream, bookmark_name,
1998 } /* if (print_summary) */
2000 if (args->print_args->print_dissections != print_dissections_none) {
2001 if (args->print_args->print_summary) {
2002 /* Separate the summary line from the tree with a blank line. */
2003 if (!print_line(args->print_args->stream, 0, ""))
2007 /* Print the information in that tree. */
2008 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
2011 /* Print a blank line if we print anything after this (aka more than one packet). */
2012 args->print_separator = TRUE;
2014 /* Print a header line if we print any more packet summaries */
2015 args->print_header_line = TRUE;
2018 if (args->print_args->print_hex) {
2019 /* Print the full packet data as hex. */
2020 if (!print_hex_data(args->print_args->stream, edt))
2023 /* Print a blank line if we print anything after this (aka more than one packet). */
2024 args->print_separator = TRUE;
2026 /* Print a header line if we print any more packet summaries */
2027 args->print_header_line = TRUE;
2028 } /* if (args->print_args->print_dissections != print_dissections_none) */
2030 epan_dissect_free(edt);
2032 /* do we want to have a formfeed between each packet from now on? */
2033 if(args->print_args->print_formfeed) {
2034 args->print_formfeed = TRUE;
2040 epan_dissect_free(edt);
2045 cf_print_packets(capture_file *cf, print_args_t *print_args)
2048 print_callback_args_t callback_args;
2056 callback_args.print_args = print_args;
2057 callback_args.print_header_line = TRUE;
2058 callback_args.header_line_buf = NULL;
2059 callback_args.header_line_buf_len = 256;
2060 callback_args.print_formfeed = FALSE;
2061 callback_args.print_separator = FALSE;
2062 callback_args.line_buf = NULL;
2063 callback_args.line_buf_len = 256;
2064 callback_args.col_widths = NULL;
2066 if (!print_preamble(print_args->stream, cf->filename)) {
2067 destroy_print_stream(print_args->stream);
2068 return CF_PRINT_WRITE_ERROR;
2071 if (print_args->print_summary) {
2072 /* We're printing packet summaries. Allocate the header line buffer
2073 and get the column widths. */
2074 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
2076 /* Find the widths for each of the columns - maximum of the
2077 width of the title and the width of the data - and construct
2078 a buffer with a line containing the column titles. */
2079 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
2080 cp = &callback_args.header_line_buf[0];
2082 for (i = 0; i < cf->cinfo.num_cols; i++) {
2083 /* Don't pad the last column. */
2084 if (i == cf->cinfo.num_cols - 1)
2085 callback_args.col_widths[i] = 0;
2087 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
2088 data_width = get_column_char_width(get_column_format(i));
2089 if (data_width > callback_args.col_widths[i])
2090 callback_args.col_widths[i] = data_width;
2093 /* Find the length of the string for this column. */
2094 column_len = strlen(cf->cinfo.col_title[i]);
2095 if (callback_args.col_widths[i] > column_len)
2096 column_len = callback_args.col_widths[i];
2098 /* Make sure there's room in the line buffer for the column; if not,
2099 double its length. */
2100 line_len += column_len + 1; /* "+1" for space */
2101 if (line_len > callback_args.header_line_buf_len) {
2102 cp_off = cp - callback_args.header_line_buf;
2103 callback_args.header_line_buf_len = 2 * line_len;
2104 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
2105 callback_args.header_line_buf_len + 1);
2106 cp = callback_args.header_line_buf + cp_off;
2109 /* Right-justify the packet number column. */
2110 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2111 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2113 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
2115 if (i != cf->cinfo.num_cols - 1)
2120 /* Now start out the main line buffer with the same length as the
2121 header line buffer. */
2122 callback_args.line_buf_len = callback_args.header_line_buf_len;
2123 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
2124 } /* if (print_summary) */
2126 /* Iterate through the list of packets, printing the packets we were
2128 ret = process_specified_packets(cf, &print_args->range, "Printing",
2129 "selected packets", TRUE, print_packet,
2132 if (callback_args.header_line_buf != NULL)
2133 g_free(callback_args.header_line_buf);
2134 if (callback_args.line_buf != NULL)
2135 g_free(callback_args.line_buf);
2136 if (callback_args.col_widths != NULL)
2137 g_free(callback_args.col_widths);
2142 /* Completed successfully. */
2146 /* Well, the user decided to abort the printing.
2148 XXX - note that what got generated before they did that
2149 will get printed if we're piping to a print program; we'd
2150 have to write to a file and then hand that to the print
2151 program to make it actually not print anything. */
2155 /* Error while printing.
2157 XXX - note that what got generated before they did that
2158 will get printed if we're piping to a print program; we'd
2159 have to write to a file and then hand that to the print
2160 program to make it actually not print anything. */
2161 destroy_print_stream(print_args->stream);
2162 return CF_PRINT_WRITE_ERROR;
2165 if (!print_finale(print_args->stream)) {
2166 destroy_print_stream(print_args->stream);
2167 return CF_PRINT_WRITE_ERROR;
2170 if (!destroy_print_stream(print_args->stream))
2171 return CF_PRINT_WRITE_ERROR;
2177 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
2178 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2182 epan_dissect_t *edt;
2184 /* Create the protocol tree, but don't fill in the column information. */
2185 edt = epan_dissect_new(TRUE, TRUE);
2186 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
2188 /* Write out the information in that tree. */
2189 proto_tree_write_pdml(edt, fh);
2191 epan_dissect_free(edt);
2197 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
2202 fh = eth_fopen(print_args->file, "w");
2204 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2206 write_pdml_preamble(fh);
2209 return CF_PRINT_WRITE_ERROR;
2212 /* Iterate through the list of packets, printing the packets we were
2214 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
2215 "selected packets", TRUE,
2216 write_pdml_packet, fh);
2221 /* Completed successfully. */
2225 /* Well, the user decided to abort the printing. */
2229 /* Error while printing. */
2231 return CF_PRINT_WRITE_ERROR;
2234 write_pdml_finale(fh);
2237 return CF_PRINT_WRITE_ERROR;
2240 /* XXX - check for an error */
2247 write_psml_packet(capture_file *cf, frame_data *fdata,
2248 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2252 epan_dissect_t *edt;
2254 /* Fill in the column information, but don't create the protocol tree. */
2255 edt = epan_dissect_new(FALSE, FALSE);
2256 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2257 epan_dissect_fill_in_columns(edt);
2259 /* Write out the information in that tree. */
2260 proto_tree_write_psml(edt, fh);
2262 epan_dissect_free(edt);
2268 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2273 fh = eth_fopen(print_args->file, "w");
2275 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2277 write_psml_preamble(fh);
2280 return CF_PRINT_WRITE_ERROR;
2283 /* Iterate through the list of packets, printing the packets we were
2285 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2286 "selected packets", TRUE,
2287 write_psml_packet, fh);
2292 /* Completed successfully. */
2296 /* Well, the user decided to abort the printing. */
2300 /* Error while printing. */
2302 return CF_PRINT_WRITE_ERROR;
2305 write_psml_finale(fh);
2308 return CF_PRINT_WRITE_ERROR;
2311 /* XXX - check for an error */
2318 write_csv_packet(capture_file *cf, frame_data *fdata,
2319 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2323 epan_dissect_t *edt;
2325 /* Fill in the column information, but don't create the protocol tree. */
2326 edt = epan_dissect_new(FALSE, FALSE);
2327 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2328 epan_dissect_fill_in_columns(edt);
2330 /* Write out the information in that tree. */
2331 proto_tree_write_csv(edt, fh);
2333 epan_dissect_free(edt);
2339 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2344 fh = eth_fopen(print_args->file, "w");
2346 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2348 write_csv_preamble(fh);
2351 return CF_PRINT_WRITE_ERROR;
2354 /* Iterate through the list of packets, printing the packets we were
2356 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2357 "selected packets", TRUE,
2358 write_csv_packet, fh);
2363 /* Completed successfully. */
2367 /* Well, the user decided to abort the printing. */
2371 /* Error while printing. */
2373 return CF_PRINT_WRITE_ERROR;
2376 write_csv_finale(fh);
2379 return CF_PRINT_WRITE_ERROR;
2382 /* XXX - check for an error */
2388 /* Scan through the packet list and change all columns that use the
2389 "command-line-specified" time stamp format to use the current
2390 value of that format. */
2392 cf_change_time_formats(capture_file *cf)
2395 progdlg_t *progbar = NULL;
2401 GTimeVal start_time;
2402 gchar status_str[100];
2403 int progbar_nextstep;
2404 int progbar_quantum;
2406 gboolean sorted_by_frame_column;
2409 /* adjust timestamp precision if auto is selected */
2410 cf_timestamp_auto_precision(cf);
2412 /* Are there any columns with time stamps in the "command-line-specified"
2415 XXX - we have to force the "column is writable" flag on, as it
2416 might be off from the last frame that was dissected. */
2417 col_set_writable(&cf->cinfo, TRUE);
2418 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2419 /* No, there aren't any columns in that format, so we have no work
2423 first = cf->cinfo.col_first[COL_CLS_TIME];
2424 g_assert(first >= 0);
2425 last = cf->cinfo.col_last[COL_CLS_TIME];
2427 /* Freeze the packet list while we redo it, so we don't get any
2428 screen updates while it happens. */
2429 packet_list_freeze();
2431 /* Update the progress bar when it gets to this value. */
2432 progbar_nextstep = 0;
2433 /* When we reach the value that triggers a progress bar update,
2434 bump that value by this amount. */
2435 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2436 /* Count of packets at which we've looked. */
2438 /* Progress so far. */
2441 /* If the rows are currently sorted by the frame column then we know
2442 * the row number of each packet: it's the row number of the previously
2443 * displayed packet + 1.
2445 * Otherwise, if the display is sorted by a different column then we have
2446 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2447 * of changing the time display format O(N**2)).
2449 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2450 * the row number and walks that many elements down the clist to find
2451 * the appropriate element.)
2453 sorted_by_frame_column = FALSE;
2454 for (i = 0; i < cf->cinfo.num_cols; i++) {
2455 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2457 sorted_by_frame_column = (i == packet_list_get_sort_column());
2463 g_get_current_time(&start_time);
2465 /* Iterate through the list of packets, checking whether the packet
2466 is in a row of the summary list and, if so, whether there are
2467 any columns that show the time in the "command-line-specified"
2468 format and, if so, update that row. */
2469 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2470 /* Create the progress bar if necessary.
2471 We check on every iteration of the loop, so that it takes no
2472 longer than the standard time to create it (otherwise, for a
2473 large file, we might take considerably longer than that standard
2474 time in order to get to the next progress bar step). */
2475 if (progbar == NULL)
2476 progbar = delayed_create_progress_dlg("Changing", "time display",
2477 TRUE, &stop_flag, &start_time, progbar_val);
2479 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2480 when we update it, we have to run the GTK+ main loop to get it
2481 to repaint what's pending, and doing so may involve an "ioctl()"
2482 to see if there's any pending input from an X server, and doing
2483 that for every packet can be costly, especially on a big file. */
2484 if (count >= progbar_nextstep) {
2485 /* let's not divide by zero. I should never be started
2486 * with count == 0, so let's assert that
2488 g_assert(cf->count > 0);
2490 progbar_val = (gfloat) count / cf->count;
2492 if (progbar != NULL) {
2493 g_snprintf(status_str, sizeof(status_str),
2494 "%4u of %u packets", count, cf->count);
2495 update_progress_dlg(progbar, progbar_val, status_str);
2498 progbar_nextstep += progbar_quantum;
2502 /* Well, the user decided to abort the redisplay. Just stop.
2504 XXX - this leaves the time field in the old format in
2505 frames we haven't yet processed. So it goes; should we
2506 simply not offer them the option of stopping? */
2512 /* Find what row this packet is in. */
2513 if (!sorted_by_frame_column) {
2514 /* This function is O(N), so we try to avoid using it... */
2515 row = packet_list_find_row_from_data(fdata);
2517 /* ...which we do by maintaining a count of packets that are
2518 being displayed (i.e., that have passed the display filter),
2519 and using the current value of that count as the row number
2520 (which is why we can only do it when the display is sorted
2521 by the frame number). */
2522 if (fdata->flags.passed_dfilter)
2529 /* This packet is in the summary list, on row "row". */
2531 for (i = first; i <= last; i++) {
2532 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2533 /* This is one of the columns that shows the time in
2534 "command-line-specified" format; update it. */
2535 cf->cinfo.col_buf[i][0] = '\0';
2536 col_set_cls_time(fdata, &cf->cinfo, i);
2537 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2543 /* We're done redisplaying the packets; destroy the progress bar if it
2545 if (progbar != NULL)
2546 destroy_progress_dlg(progbar);
2548 /* Set the column widths of those columns that show the time in
2549 "command-line-specified" format. */
2550 for (i = first; i <= last; i++) {
2551 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2552 packet_list_set_cls_time_width(i);
2556 /* Unfreeze the packet list. */
2564 gboolean frame_matched;
2568 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2572 mdata.string = string;
2573 mdata.string_len = strlen(string);
2574 return find_packet(cf, match_protocol_tree, &mdata);
2578 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2580 match_data *mdata = criterion;
2581 epan_dissect_t *edt;
2583 /* Construct the protocol tree, including the displayed text */
2584 edt = epan_dissect_new(TRUE, TRUE);
2585 /* We don't need the column information */
2586 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2588 /* Iterate through all the nodes, seeing if they have text that matches. */
2590 mdata->frame_matched = FALSE;
2591 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2592 epan_dissect_free(edt);
2593 return mdata->frame_matched;
2597 match_subtree_text(proto_node *node, gpointer data)
2599 match_data *mdata = (match_data*) data;
2600 const gchar *string = mdata->string;
2601 size_t string_len = mdata->string_len;
2602 capture_file *cf = mdata->cf;
2603 field_info *fi = PITEM_FINFO(node);
2604 gchar label_str[ITEM_LABEL_LENGTH];
2611 if (mdata->frame_matched) {
2612 /* We already had a match; don't bother doing any more work. */
2616 /* Don't match invisible entries. */
2617 if (PROTO_ITEM_IS_HIDDEN(node))
2620 /* was a free format label produced? */
2622 label_ptr = fi->rep->representation;
2624 /* no, make a generic label */
2625 label_ptr = label_str;
2626 proto_item_fill_label(fi, label_str);
2629 /* Does that label match? */
2630 label_len = strlen(label_ptr);
2631 for (i = 0; i < label_len; i++) {
2632 c_char = label_ptr[i];
2634 c_char = toupper(c_char);
2635 if (c_char == string[c_match]) {
2637 if (c_match == string_len) {
2638 /* No need to look further; we have a match */
2639 mdata->frame_matched = TRUE;
2646 /* Recurse into the subtree, if it exists */
2647 if (node->first_child != NULL)
2648 proto_tree_children_foreach(node, match_subtree_text, mdata);
2652 cf_find_packet_summary_line(capture_file *cf, const char *string)
2656 mdata.string = string;
2657 mdata.string_len = strlen(string);
2658 return find_packet(cf, match_summary_line, &mdata);
2662 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2664 match_data *mdata = criterion;
2665 const gchar *string = mdata->string;
2666 size_t string_len = mdata->string_len;
2667 epan_dissect_t *edt;
2668 const char *info_column;
2669 size_t info_column_len;
2670 gboolean frame_matched = FALSE;
2676 /* Don't bother constructing the protocol tree */
2677 edt = epan_dissect_new(FALSE, FALSE);
2678 /* Get the column information */
2679 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2681 /* Find the Info column */
2682 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2683 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2684 /* Found it. See if we match. */
2685 info_column = edt->pi.cinfo->col_data[colx];
2686 info_column_len = strlen(info_column);
2687 for (i = 0; i < info_column_len; i++) {
2688 c_char = info_column[i];
2690 c_char = toupper(c_char);
2691 if (c_char == string[c_match]) {
2693 if (c_match == string_len) {
2694 frame_matched = TRUE;
2703 epan_dissect_free(edt);
2704 return frame_matched;
2710 } cbs_t; /* "Counted byte string" */
2713 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2718 info.data_len = string_size;
2720 /* String or hex search? */
2722 /* String search - what type of string? */
2723 switch (cf->scs_type) {
2725 case SCS_ASCII_AND_UNICODE:
2726 return find_packet(cf, match_ascii_and_unicode, &info);
2729 return find_packet(cf, match_ascii, &info);
2732 return find_packet(cf, match_unicode, &info);
2735 g_assert_not_reached();
2739 return find_packet(cf, match_binary, &info);
2743 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2745 cbs_t *info = criterion;
2746 const char *ascii_text = info->data;
2747 size_t textlen = info->data_len;
2748 gboolean frame_matched;
2754 frame_matched = FALSE;
2755 buf_len = fdata->pkt_len;
2756 for (i = 0; i < buf_len; i++) {
2759 c_char = toupper(c_char);
2761 if (c_char == ascii_text[c_match]) {
2763 if (c_match == textlen) {
2764 frame_matched = TRUE;
2765 cf->search_pos = i; /* Save the position of the last character
2766 for highlighting the field. */
2773 return frame_matched;
2777 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2779 cbs_t *info = criterion;
2780 const char *ascii_text = info->data;
2781 size_t textlen = info->data_len;
2782 gboolean frame_matched;
2788 frame_matched = FALSE;
2789 buf_len = fdata->pkt_len;
2790 for (i = 0; i < buf_len; i++) {
2793 c_char = toupper(c_char);
2794 if (c_char == ascii_text[c_match]) {
2796 if (c_match == textlen) {
2797 frame_matched = TRUE;
2798 cf->search_pos = i; /* Save the position of the last character
2799 for highlighting the field. */
2805 return frame_matched;
2809 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2811 cbs_t *info = criterion;
2812 const char *ascii_text = info->data;
2813 size_t textlen = info->data_len;
2814 gboolean frame_matched;
2820 frame_matched = FALSE;
2821 buf_len = fdata->pkt_len;
2822 for (i = 0; i < buf_len; i++) {
2825 c_char = toupper(c_char);
2826 if (c_char == ascii_text[c_match]) {
2829 if (c_match == textlen) {
2830 frame_matched = TRUE;
2831 cf->search_pos = i; /* Save the position of the last character
2832 for highlighting the field. */
2838 return frame_matched;
2842 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2844 cbs_t *info = criterion;
2845 const guint8 *binary_data = info->data;
2846 size_t datalen = info->data_len;
2847 gboolean frame_matched;
2852 frame_matched = FALSE;
2853 buf_len = fdata->pkt_len;
2854 for (i = 0; i < buf_len; i++) {
2855 if (cf->pd[i] == binary_data[c_match]) {
2857 if (c_match == datalen) {
2858 frame_matched = TRUE;
2859 cf->search_pos = i; /* Save the position of the last character
2860 for highlighting the field. */
2866 return frame_matched;
2870 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2872 return find_packet(cf, match_dfilter, sfcode);
2876 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2878 dfilter_t *sfcode = criterion;
2879 epan_dissect_t *edt;
2880 gboolean frame_matched;
2882 edt = epan_dissect_new(TRUE, FALSE);
2883 epan_dissect_prime_dfilter(edt, sfcode);
2884 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2885 frame_matched = dfilter_apply_edt(sfcode, edt);
2886 epan_dissect_free(edt);
2887 return frame_matched;
2891 find_packet(capture_file *cf,
2892 gboolean (*match_function)(capture_file *, frame_data *, void *),
2895 frame_data *start_fd;
2897 frame_data *new_fd = NULL;
2898 progdlg_t *progbar = NULL;
2905 GTimeVal start_time;
2906 gchar status_str[100];
2907 int progbar_nextstep;
2908 int progbar_quantum;
2911 start_fd = cf->current_frame;
2912 if (start_fd != NULL) {
2913 /* Iterate through the list of packets, starting at the packet we've
2914 picked, calling a routine to run the filter on the packet, see if
2915 it matches, and stop if so. */
2919 /* Update the progress bar when it gets to this value. */
2920 progbar_nextstep = 0;
2921 /* When we reach the value that triggers a progress bar update,
2922 bump that value by this amount. */
2923 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2924 /* Progress so far. */
2928 g_get_current_time(&start_time);
2931 title = cf->sfilter?cf->sfilter:"";
2933 /* Create the progress bar if necessary.
2934 We check on every iteration of the loop, so that it takes no
2935 longer than the standard time to create it (otherwise, for a
2936 large file, we might take considerably longer than that standard
2937 time in order to get to the next progress bar step). */
2938 if (progbar == NULL)
2939 progbar = delayed_create_progress_dlg("Searching", title,
2940 FALSE, &stop_flag, &start_time, progbar_val);
2942 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2943 when we update it, we have to run the GTK+ main loop to get it
2944 to repaint what's pending, and doing so may involve an "ioctl()"
2945 to see if there's any pending input from an X server, and doing
2946 that for every packet can be costly, especially on a big file. */
2947 if (count >= progbar_nextstep) {
2948 /* let's not divide by zero. I should never be started
2949 * with count == 0, so let's assert that
2951 g_assert(cf->count > 0);
2953 progbar_val = (gfloat) count / cf->count;
2955 if (progbar != NULL) {
2956 g_snprintf(status_str, sizeof(status_str),
2957 "%4u of %u packets", count, cf->count);
2958 update_progress_dlg(progbar, progbar_val, status_str);
2961 progbar_nextstep += progbar_quantum;
2965 /* Well, the user decided to abort the search. Go back to the
2966 frame where we started. */
2971 /* Go past the current frame. */
2972 if (cf->sbackward) {
2973 /* Go on to the previous frame. */
2974 fdata = fdata->prev;
2975 if (fdata == NULL) {
2977 * XXX - other apps have a bit more of a detailed message
2978 * for this, and instead of offering "OK" and "Cancel",
2979 * they offer things such as "Continue" and "Cancel";
2980 * we need an API for popping up alert boxes with
2981 * {Verb} and "Cancel".
2984 if (prefs.gui_find_wrap)
2986 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2987 "%sBeginning of capture exceeded!%s\n\n"
2988 "Search is continued from the end of the capture.",
2989 simple_dialog_primary_start(), simple_dialog_primary_end());
2990 fdata = cf->plist_end; /* wrap around */
2994 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2995 "%sBeginning of capture exceeded!%s\n\n"
2996 "Try searching forwards.",
2997 simple_dialog_primary_start(), simple_dialog_primary_end());
2998 fdata = start_fd; /* stay on previous packet */
3002 /* Go on to the next frame. */
3003 fdata = fdata->next;
3004 if (fdata == NULL) {
3005 if (prefs.gui_find_wrap)
3007 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3008 "%sEnd of capture exceeded!%s\n\n"
3009 "Search is continued from the start of the capture.",
3010 simple_dialog_primary_start(), simple_dialog_primary_end());
3011 fdata = cf->plist; /* wrap around */
3015 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
3016 "%sEnd of capture exceeded!%s\n\n"
3017 "Try searching backwards.",
3018 simple_dialog_primary_start(), simple_dialog_primary_end());
3019 fdata = start_fd; /* stay on previous packet */
3026 /* Is this packet in the display? */
3027 if (fdata->flags.passed_dfilter) {
3028 /* Yes. Load its data. */
3029 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
3030 cf->pd, fdata->cap_len, &err, &err_info)) {
3031 /* Read error. Report the error, and go back to the frame
3032 where we started. */
3033 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3034 cf_read_error_message(err, err_info), cf->filename);
3039 /* Does it match the search criterion? */
3040 if ((*match_function)(cf, fdata, criterion)) {
3042 break; /* found it! */
3046 if (fdata == start_fd) {
3047 /* We're back to the frame we were on originally, and that frame
3048 doesn't match the search filter. The search failed. */
3053 /* We're done scanning the packets; destroy the progress bar if it
3055 if (progbar != NULL)
3056 destroy_progress_dlg(progbar);
3059 if (new_fd != NULL) {
3060 /* We found a frame. Find what row it's in. */
3061 row = packet_list_find_row_from_data(new_fd);
3062 g_assert(row != -1);
3064 /* Select that row, make it the focus row, and make it visible. */
3065 packet_list_set_selected_row(row);
3066 return TRUE; /* success */
3068 return FALSE; /* failure */
3072 cf_goto_frame(capture_file *cf, guint fnumber)
3077 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
3080 if (fdata == NULL) {
3081 /* we didn't find a packet with that packet number */
3082 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3083 "There is no packet with the packet number %u.", fnumber);
3084 return FALSE; /* we failed to go to that packet */
3086 if (!fdata->flags.passed_dfilter) {
3087 /* that packet currently isn't displayed */
3088 /* XXX - add it to the set of displayed packets? */
3089 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3090 "The packet number %u isn't currently being displayed.", fnumber);
3091 return FALSE; /* we failed to go to that packet */
3094 /* We found that packet, and it's currently being displayed.
3095 Find what row it's in. */
3096 row = packet_list_find_row_from_data(fdata);
3097 g_assert(row != -1);
3099 /* Select that row, make it the focus row, and make it visible. */
3100 packet_list_set_selected_row(row);
3101 return TRUE; /* we got to that packet */
3105 cf_goto_top_frame(capture_file *cf)
3109 frame_data *lowest_fdata = NULL;
3111 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3112 if (fdata->flags.passed_dfilter) {
3113 lowest_fdata = fdata;
3118 if (lowest_fdata == NULL) {
3122 /* We found that packet, and it's currently being displayed.
3123 Find what row it's in. */
3124 row = packet_list_find_row_from_data(lowest_fdata);
3125 g_assert(row != -1);
3127 /* Select that row, make it the focus row, and make it visible. */
3128 packet_list_set_selected_row(row);
3129 return TRUE; /* we got to that packet */
3133 cf_goto_bottom_frame(capture_file *cf)
3137 frame_data *highest_fdata = NULL;
3139 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
3140 if (fdata->flags.passed_dfilter) {
3141 highest_fdata = fdata;
3145 if (highest_fdata == NULL) {
3149 /* We found that packet, and it's currently being displayed.
3150 Find what row it's in. */
3151 row = packet_list_find_row_from_data(highest_fdata);
3152 g_assert(row != -1);
3154 /* Select that row, make it the focus row, and make it visible. */
3155 packet_list_set_selected_row(row);
3156 return TRUE; /* we got to that packet */
3160 * Go to frame specified by currently selected protocol tree item.
3163 cf_goto_framenum(capture_file *cf)
3165 header_field_info *hfinfo;
3168 if (cf->finfo_selected) {
3169 hfinfo = cf->finfo_selected->hfinfo;
3171 if (hfinfo->type == FT_FRAMENUM) {
3172 framenum = fvalue_get_uinteger(&cf->finfo_selected->value);
3174 return cf_goto_frame(cf, framenum);
3181 /* Select the packet on a given row. */
3183 cf_select_packet(capture_file *cf, int row)
3189 /* Get the frame data struct pointer for this frame */
3190 fdata = (frame_data *)packet_list_get_row_data(row);
3192 if (fdata == NULL) {
3193 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
3194 the first entry is added to it by "real_insert_row()", that row
3195 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
3196 our version and the vanilla GTK+ version).
3198 This means that a "select-row" signal is emitted; this causes
3199 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
3202 "cf_select_packet()" fetches, above, the data associated with the
3203 row that was selected; however, as "gtk_clist_append()", which
3204 called "real_insert_row()", hasn't yet returned, we haven't yet
3205 associated any data with that row, so we get back a null pointer.
3207 We can't assume that there's only one frame in the frame list,
3208 either, as we may be filtering the display.
3210 We therefore assume that, if "row" is 0, i.e. the first row
3211 is being selected, and "cf->first_displayed" equals
3212 "cf->last_displayed", i.e. there's only one frame being
3213 displayed, that frame is the frame we want.
3215 This means we have to set "cf->first_displayed" and
3216 "cf->last_displayed" before adding the row to the
3217 GtkCList; see the comment in "add_packet_to_packet_list()". */
3219 if (row == 0 && cf->first_displayed == cf->last_displayed)
3220 fdata = cf->first_displayed;
3223 /* If fdata _still_ isn't set simply give up. */
3224 if (fdata == NULL) {
3228 /* Get the data in that frame. */
3229 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
3230 cf->pd, fdata->cap_len, &err, &err_info)) {
3231 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3232 cf_read_error_message(err, err_info), cf->filename);
3236 /* Record that this frame is the current frame. */
3237 cf->current_frame = fdata;
3239 /* Create the logical protocol tree. */
3240 if (cf->edt != NULL) {
3241 epan_dissect_free(cf->edt);
3244 /* We don't need the columns here. */
3245 cf->edt = epan_dissect_new(TRUE, TRUE);
3247 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
3250 cf_callback_invoke(cf_cb_packet_selected, cf);
3253 /* Unselect the selected packet, if any. */
3255 cf_unselect_packet(capture_file *cf)
3257 /* Destroy the epan_dissect_t for the unselected packet. */
3258 if (cf->edt != NULL) {
3259 epan_dissect_free(cf->edt);
3263 /* No packet is selected. */
3264 cf->current_frame = NULL;
3266 cf_callback_invoke(cf_cb_packet_unselected, cf);
3268 /* No protocol tree means no selected field. */
3269 cf_unselect_field(cf);
3272 /* Unset the selected protocol tree field, if any. */
3274 cf_unselect_field(capture_file *cf)
3276 cf->finfo_selected = NULL;
3278 cf_callback_invoke(cf_cb_field_unselected, cf);
3282 * Mark a particular frame.
3285 cf_mark_frame(capture_file *cf, frame_data *frame)
3287 if (! frame->flags.marked) {
3288 frame->flags.marked = TRUE;
3289 if (cf->count > cf->marked_count)
3295 * Unmark a particular frame.
3298 cf_unmark_frame(capture_file *cf, frame_data *frame)
3300 if (frame->flags.marked) {
3301 frame->flags.marked = FALSE;
3302 if (cf->marked_count > 0)
3310 } save_callback_args_t;
3313 * Save a capture to a file, in a particular format, saving either
3314 * all packets, all currently-displayed packets, or all marked packets.
3316 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3317 * up a message box for the failure.
3320 save_packet(capture_file *cf _U_, frame_data *fdata,
3321 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3324 save_callback_args_t *args = argsp;
3325 struct wtap_pkthdr hdr;
3328 /* init the wtap header for saving */
3329 hdr.ts.secs = fdata->abs_ts.secs;
3330 hdr.ts.nsecs = fdata->abs_ts.nsecs;
3331 hdr.caplen = fdata->cap_len;
3332 hdr.len = fdata->pkt_len;
3333 hdr.pkt_encap = fdata->lnk_t;
3335 /* and save the packet */
3336 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3337 cf_write_failure_alert_box(args->fname, err);
3344 * Can this capture file be saved in any format except by copying the raw data?
3347 cf_can_save_as(capture_file *cf)
3351 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
3352 /* To save a file with Wiretap, Wiretap has to handle that format,
3353 and its code to handle that format must be able to write a file
3354 with this file's encapsulation type. */
3355 if (wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cf->lnk_t)) {
3356 /* OK, we can write it out in this type. */
3361 /* No, we couldn't save it in any format. */
3366 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format, gboolean compressed)
3368 gchar *from_filename;
3372 save_callback_args_t callback_args;
3374 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3376 /* don't write over an existing file. */
3377 /* this should've been already checked by our caller, just to be sure... */
3378 if (file_exists(fname)) {
3379 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3380 "%sCapture file: \"%s\" already exists!%s\n\n"
3381 "Please choose a different filename.",
3382 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3386 packet_range_process_init(range);
3389 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3390 /* We're not filtering packets, and we're saving it in the format
3391 it's already in, so we can just move or copy the raw data. */
3393 if (cf->is_tempfile) {
3394 /* The file being saved is a temporary file from a live
3395 capture, so it doesn't need to stay around under that name;
3396 first, try renaming the capture buffer file to the new name. */
3398 if (eth_rename(cf->filename, fname) == 0) {
3399 /* That succeeded - there's no need to copy the source file. */
3400 from_filename = NULL;
3403 if (errno == EXDEV) {
3404 /* They're on different file systems, so we have to copy the
3407 from_filename = cf->filename;
3409 /* The rename failed, but not because they're on different
3410 file systems - put up an error message. (Or should we
3411 just punt and try to copy? The only reason why I'd
3412 expect the rename to fail and the copy to succeed would
3413 be if we didn't have permission to remove the file from
3414 the temporary directory, and that might be fixable - but
3415 is it worth requiring the user to go off and fix it?) */
3416 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3417 file_rename_error_message(errno), fname);
3423 from_filename = cf->filename;
3426 /* It's a permanent file, so we should copy it, and not remove the
3429 from_filename = cf->filename;
3433 /* Copy the file, if we haven't moved it. */
3434 if (!copy_binary_file(from_filename, fname))
3438 /* Either we're filtering packets, or we're saving in a different
3439 format; we can't do that by copying or moving the capture file,
3440 we have to do it by writing the packets out in Wiretap. */
3441 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap,
3444 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3448 /* XXX - we let the user save a subset of the packets.
3450 If we do that, should we make that file the current file? If so,
3451 it means we can no longer get at the other packets. What does
3454 /* Iterate through the list of packets, processing the packets we were
3457 XXX - we've already called "packet_range_process_init(range)", but
3458 "process_specified_packets()" will do it again. Fortunately,
3459 that's harmless in this case, as we haven't done anything to
3460 "range" since we initialized it. */
3461 callback_args.pdh = pdh;
3462 callback_args.fname = fname;
3463 switch (process_specified_packets(cf, range, "Saving", "selected packets",
3464 TRUE, save_packet, &callback_args)) {
3467 /* Completed successfully. */
3471 /* The user decided to abort the saving.
3472 XXX - remove the output file? */
3476 /* Error while saving. */
3477 wtap_dump_close(pdh, &err);
3481 if (!wtap_dump_close(pdh, &err)) {
3482 cf_close_failure_alert_box(fname, err);
3487 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3489 if (packet_range_process_all(range)) {
3490 /* We saved the entire capture, not just some packets from it.
3491 Open and read the file we saved it to.
3493 XXX - this is somewhat of a waste; we already have the
3494 packets, all this gets us is updated file type information
3495 (which we could just stuff into "cf"), and having the new
3496 file be the one we have opened and from which we're reading
3497 the data, and it means we have to spend time opening and
3498 reading the file, which could be a significant amount of
3499 time if the file is large. */
3500 cf->user_saved = TRUE;
3502 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3503 /* XXX - report errors if this fails?
3504 What should we return if it fails or is aborted? */
3505 switch (cf_read(cf)) {
3509 /* Just because we got an error, that doesn't mean we were unable
3510 to read any of the file; we handle what we could get from the
3514 case CF_READ_ABORTED:
3515 /* The user bailed out of re-reading the capture file; the
3516 capture file has been closed - just return (without
3517 changing any menu settings; "cf_close()" set them
3518 correctly for the "no capture file open" state). */
3521 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3527 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3532 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3533 gboolean for_writing, int file_type)
3536 /* Wiretap error. */
3539 case WTAP_ERR_NOT_REGULAR_FILE:
3540 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3541 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3545 case WTAP_ERR_RANDOM_OPEN_PIPE:
3546 /* Seen only when opening a capture file for reading. */
3547 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3548 "The file \"%s\" is a pipe or FIFO; Wireshark can't read pipe or FIFO files.",
3552 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3553 /* Seen only when opening a capture file for reading. */
3554 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3555 "The file \"%s\" isn't a capture file in a format Wireshark understands.",
3559 case WTAP_ERR_UNSUPPORTED:
3560 /* Seen only when opening a capture file for reading. */
3561 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3562 "The file \"%s\" isn't a capture file in a format Wireshark understands.\n"
3564 filename, err_info);
3568 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3569 /* Seen only when opening a capture file for writing. */
3570 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3571 "The file \"%s\" is a pipe, and %s capture files can't be "
3572 "written to a pipe.",
3573 filename, wtap_file_type_string(file_type));
3576 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3577 /* Seen only when opening a capture file for writing. */
3578 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3579 "Wireshark doesn't support writing capture files in that format.");
3582 case WTAP_ERR_UNSUPPORTED_ENCAP:
3584 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3585 "Wireshark can't save this capture in that format.");
3587 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3588 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.\n"
3590 filename, err_info);
3595 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3597 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3598 "Wireshark can't save this capture in that format.");
3600 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3601 "The file \"%s\" is a capture for a network type that Wireshark doesn't support.",
3606 case WTAP_ERR_BAD_RECORD:
3607 /* Seen only when opening a capture file for reading. */
3608 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3609 "The file \"%s\" appears to be damaged or corrupt.\n"
3611 filename, err_info);
3615 case WTAP_ERR_CANT_OPEN:
3617 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3618 "The file \"%s\" could not be created for some unknown reason.",
3621 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3622 "The file \"%s\" could not be opened for some unknown reason.",
3627 case WTAP_ERR_SHORT_READ:
3628 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3629 "The file \"%s\" appears to have been cut short"
3630 " in the middle of a packet or other data.",
3634 case WTAP_ERR_SHORT_WRITE:
3635 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3636 "A full header couldn't be written to the file \"%s\".",
3640 case WTAP_ERR_COMPRESSION_NOT_SUPPORTED:
3641 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3642 "Gzip compression not supported by this file type.");
3646 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3647 "The file \"%s\" could not be %s: %s.",
3649 for_writing ? "created" : "opened",
3650 wtap_strerror(err));
3655 open_failure_alert_box(filename, err, for_writing);
3660 file_rename_error_message(int err)
3663 static char errmsg_errno[1024+1];
3668 errmsg = "The path to the file \"%s\" doesn't exist.";
3672 errmsg = "You don't have permission to move the capture file to \"%s\".";
3676 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3677 "The file \"%%s\" could not be moved: %s.",
3678 wtap_strerror(err));
3679 errmsg = errmsg_errno;
3686 cf_read_error_message(int err, const gchar *err_info)
3688 static char errmsg_errno[1024+1];
3692 case WTAP_ERR_UNSUPPORTED_ENCAP:
3693 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3694 "The file \"%%s\" has a packet with a network type that Wireshark doesn't support.\n(%s)",
3698 case WTAP_ERR_BAD_RECORD:
3699 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3700 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3701 wtap_strerror(err), err_info);
3705 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3706 "An error occurred while reading from the file \"%%s\": %s.",
3707 wtap_strerror(err));
3710 return errmsg_errno;
3714 cf_write_failure_alert_box(const char *filename, int err)
3717 /* Wiretap error. */
3718 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3719 "An error occurred while writing to the file \"%s\": %s.",
3720 filename, wtap_strerror(err));
3723 write_failure_alert_box(filename, err);
3727 /* Check for write errors - if the file is being written to an NFS server,
3728 a write error may not show up until the file is closed, as NFS clients
3729 might not send writes to the server until the "write()" call finishes,
3730 so that the write may fail on the server but the "write()" may succeed. */
3732 cf_close_failure_alert_box(const char *filename, int err)
3735 /* Wiretap error. */
3738 case WTAP_ERR_CANT_CLOSE:
3739 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3740 "The file \"%s\" couldn't be closed for some unknown reason.",
3744 case WTAP_ERR_SHORT_WRITE:
3745 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3746 "Not all the packets could be written to the file \"%s\".",
3751 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3752 "An error occurred while closing the file \"%s\": %s.",
3753 filename, wtap_strerror(err));
3758 We assume that a close error from the OS is really a write error. */
3759 write_failure_alert_box(filename, err);
3763 /* Reload the current capture file. */
3765 cf_reload(capture_file *cf) {
3767 gboolean is_tempfile;
3770 /* If the file could be opened, "cf_open()" calls "cf_close()"
3771 to get rid of state for the old capture file before filling in state
3772 for the new capture file. "cf_close()" will remove the file if
3773 it's a temporary file; we don't want that to happen (for one thing,
3774 it'd prevent subsequent reopens from working). Remember whether it's
3775 a temporary file, mark it as not being a temporary file, and then
3776 reopen it as the type of file it was.
3778 Also, "cf_close()" will free "cf->filename", so we must make
3779 a copy of it first. */
3780 filename = g_strdup(cf->filename);
3781 is_tempfile = cf->is_tempfile;
3782 cf->is_tempfile = FALSE;
3783 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3784 switch (cf_read(cf)) {
3788 /* Just because we got an error, that doesn't mean we were unable
3789 to read any of the file; we handle what we could get from the
3793 case CF_READ_ABORTED:
3794 /* The user bailed out of re-reading the capture file; the
3795 capture file has been closed - just free the capture file name
3796 string and return (without changing the last containing
3802 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3803 Instead, the file was left open, so we should restore "cf->is_tempfile"
3806 XXX - change the menu? Presumably "cf_open()" will do that;
3807 make sure it does! */
3808 cf->is_tempfile = is_tempfile;
3810 /* "cf_open()" made a copy of the file name we handed it, so
3811 we should free up our copy. */
3815 /* Copies a file in binary mode, for those operating systems that care about
3817 * Returns TRUE on success, FALSE on failure. If a failure, it also
3818 * displays a simple dialog window with the error message.
3821 copy_binary_file(const char *from_filename, const char *to_filename)
3823 int from_fd, to_fd, nread, nwritten, err;
3826 /* Copy the raw bytes of the file. */
3827 from_fd = eth_open(from_filename, O_RDONLY | O_BINARY, 0000 /* no creation so don't matter */);
3829 open_failure_alert_box(from_filename, errno, FALSE);
3833 /* Use open() instead of creat() so that we can pass the O_BINARY
3834 flag, which is relevant on Win32; it appears that "creat()"
3835 may open the file in text mode, not binary mode, but we want
3836 to copy the raw bytes of the file, so we need the output file
3837 to be open in binary mode. */
3838 to_fd = eth_open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3840 open_failure_alert_box(to_filename, errno, TRUE);
3845 while ((nread = eth_read(from_fd, pd, sizeof pd)) > 0) {
3846 nwritten = eth_write(to_fd, pd, nread);
3847 if (nwritten < nread) {
3851 err = WTAP_ERR_SHORT_WRITE;
3852 write_failure_alert_box(to_filename, err);
3860 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3861 "An error occurred while reading from the file \"%s\": %s.",
3862 from_filename, strerror(err));
3868 if (eth_close(to_fd) < 0) {
3869 write_failure_alert_box(to_filename, errno);