6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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.
50 #ifdef NEED_STRERROR_H
54 #include <epan/epan.h>
55 #include <epan/filesystem.h>
58 #include "color_filters.h"
59 #include <epan/column.h>
60 #include <epan/packet.h>
61 #include "packet-range.h"
67 #include "alert_box.h"
68 #include "simple_dialog.h"
69 #include "progress_dlg.h"
71 #include <epan/prefs.h>
72 #include <epan/dfilter/dfilter.h>
73 #include <epan/conversation.h>
74 #include <epan/epan_dissect.h>
76 #include "tap_dfilter_dlg.h"
77 #include <epan/dissectors/packet-data.h>
79 /* Win32 needs the O_BINARY flag for open() */
85 gboolean auto_scroll_live;
88 static guint32 firstsec, firstusec;
89 static guint32 prevsec, prevusec;
90 static guint32 cum_bytes = 0;
92 static void cf_reset_state(capture_file *cf);
94 static void read_packet(capture_file *cf, long offset);
96 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
97 gboolean refilter, gboolean redissect);
99 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
101 static void match_subtree_text(proto_node *node, gpointer data);
102 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
104 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
106 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
108 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
110 static gboolean match_binary(capture_file *cf, frame_data *fdata,
112 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
114 static gboolean find_packet(capture_file *cf,
115 gboolean (*match_function)(capture_file *, frame_data *, void *),
118 static void cf_open_failure_alert_box(const char *filename, int err,
119 gchar *err_info, gboolean for_writing,
121 static const char *file_rename_error_message(int err);
122 static void cf_write_failure_alert_box(const char *filename, int err);
123 static void cf_close_failure_alert_box(const char *filename, int err);
124 static gboolean copy_binary_file(const char *from_filename, const char *to_filename);
126 /* Update the progress bar this many times when reading a file. */
127 #define N_PROGBAR_UPDATES 100
129 /* Number of "frame_data" structures per memory chunk.
130 XXX - is this the right number? */
131 #define FRAME_DATA_CHUNK_SIZE 1024
134 /* one callback for now, we could have a list later */
135 static cf_callback_t cf_cb = NULL;
136 static gpointer cf_cb_user_data = NULL;
139 cf_callback_invoke(int event, gpointer data)
141 g_assert(cf_cb != NULL);
142 cf_cb(event, data, cf_cb_user_data);
147 cf_callback_add(cf_callback_t func, gpointer user_data)
149 /* More than one callback listener is currently not implemented,
150 but should be easy to do. */
151 g_assert(cf_cb == NULL);
153 cf_cb_user_data = user_data;
157 cf_callback_remove(cf_callback_t func _U_)
159 g_assert(cf_cb != NULL);
161 cf_cb_user_data = NULL;
166 cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
171 wth = wtap_open_offline(fname, err, &err_info, TRUE);
175 /* The open succeeded. Close whatever capture file we had open,
176 and fill in the information for this file. */
179 /* Initialize all data structures used for dissection. */
182 /* We're about to start reading the file. */
183 cf->state = FILE_READ_IN_PROGRESS;
188 /* Set the file name because we need it to set the follow stream filter.
189 XXX - is that still true? We need it for other reasons, though,
191 cf->filename = g_strdup(fname);
193 /* Indicate whether it's a permanent or temporary file. */
194 cf->is_tempfile = is_tempfile;
196 /* If it's a temporary capture buffer file, mark it as not saved. */
197 cf->user_saved = !is_tempfile;
199 cf->cd_t = wtap_file_type(cf->wth);
201 cf->displayed_count = 0;
202 cf->marked_count = 0;
203 cf->drops_known = FALSE;
207 cf->snap = wtap_snapshot_length(cf->wth);
209 /* Snapshot length not known. */
210 cf->has_snap = FALSE;
211 cf->snap = WTAP_MAX_PACKET_SIZE;
214 firstsec = 0, firstusec = 0;
215 prevsec = 0, prevusec = 0;
217 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
219 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
221 g_assert(cf->plist_chunk);
223 fileset_file_opened(fname);
228 cf_open_failure_alert_box(fname, *err, err_info, FALSE, 0);
234 * Reset the state for the currently closed file, but don't do the
235 * UI callbacks; this is for use in "cf_open()", where we don't
236 * want the UI to go from "file open" to "file closed" back to
237 * "file open", we want it to go from "old file open" to "new file
238 * open and being read".
241 cf_reset_state(capture_file *cf)
243 /* Die if we're in the middle of reading a file. */
244 g_assert(cf->state != FILE_READ_IN_PROGRESS);
250 /* We have no file open... */
251 if (cf->filename != NULL) {
252 /* If it's a temporary file, remove it. */
254 unlink(cf->filename);
255 g_free(cf->filename);
258 /* ...which means we have nothing to save. */
259 cf->user_saved = FALSE;
261 if (cf->plist_chunk != NULL) {
262 g_mem_chunk_destroy(cf->plist_chunk);
263 cf->plist_chunk = NULL;
265 if (cf->rfcode != NULL) {
266 dfilter_free(cf->rfcode);
270 cf->plist_end = NULL;
271 cf_unselect_packet(cf); /* nothing to select */
272 cf->first_displayed = NULL;
273 cf->last_displayed = NULL;
275 /* No frame selected, no field in that frame selected. */
276 cf->current_frame = NULL;
277 cf->finfo_selected = NULL;
279 /* Clear the packet list. */
280 packet_list_freeze();
289 reset_tap_listeners();
291 /* We have no file open. */
292 cf->state = FILE_CLOSED;
294 fileset_file_closed();
297 /* Reset everything to a pristine state */
299 cf_close(capture_file *cf)
303 cleanup_dissection();
305 cf_callback_invoke(cf_cb_file_closed, cf);
309 cf_read(capture_file *cf)
313 const gchar *name_ptr;
315 char errmsg_errno[1024+1];
316 gchar err_str[2048+1];
318 progdlg_t *progbar = NULL;
320 gint64 size, file_pos;
323 gchar status_str[100];
324 int progbar_nextstep;
329 reset_tap_listeners();
330 tap_dfilter_dlg_update();
332 cf_callback_invoke(cf_cb_file_read_start, cf);
334 name_ptr = get_basename(cf->filename);
336 /* Find the size of the file. */
337 size = wtap_file_size(cf->wth, NULL);
339 /* Update the progress bar when it gets to this value. */
340 progbar_nextstep = 0;
341 /* When we reach the value that triggers a progress bar update,
342 bump that value by this amount. */
344 progbar_quantum = size/N_PROGBAR_UPDATES;
348 packet_list_freeze();
351 g_get_current_time(&start_time);
353 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
355 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
356 when we update it, we have to run the GTK+ main loop to get it
357 to repaint what's pending, and doing so may involve an "ioctl()"
358 to see if there's any pending input from an X server, and doing
359 that for every packet can be costly, especially on a big file. */
360 if (data_offset >= progbar_nextstep) {
361 file_pos = wtap_read_so_far(cf->wth, NULL);
362 prog_val = (gfloat) file_pos / (gfloat) size;
363 if (prog_val > 1.0) {
364 /* The file probably grew while we were reading it.
365 Update file size, and try again. */
366 size = wtap_file_size(cf->wth, NULL);
368 prog_val = (gfloat) file_pos / (gfloat) size;
369 /* If it's still > 1, either "wtap_file_size()" failed (in which
370 case there's not much we can do about it), or the file
371 *shrank* (in which case there's not much we can do about
372 it); just clip the progress value at 1.0. */
376 if (progbar == NULL) {
377 /* Create the progress bar if necessary */
378 progbar = delayed_create_progress_dlg("Loading", name_ptr,
379 &stop_flag, &start_time, prog_val);
381 if (progbar != NULL) {
382 g_snprintf(status_str, sizeof(status_str),
383 "%" PRId64 "KB of %" PRId64 "KB",
384 file_pos / 1024, size / 1024);
385 update_progress_dlg(progbar, prog_val, status_str);
387 progbar_nextstep += progbar_quantum;
392 /* Well, the user decided to abort the read. Destroy the progress
393 bar, close the capture file, and return CF_READ_ABORTED so our caller
394 can do whatever is appropriate when that happens. */
395 destroy_progress_dlg(progbar);
396 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
397 packet_list_thaw(); /* undo our freeze */
399 return CF_READ_ABORTED;
401 read_packet(cf, data_offset);
404 /* We're done reading the file; destroy the progress bar if it was created. */
406 destroy_progress_dlg(progbar);
408 /* We're done reading sequentially through the file. */
409 cf->state = FILE_READ_DONE;
411 /* Close the sequential I/O side, to free up memory it requires. */
412 wtap_sequential_close(cf->wth);
414 /* Allow the protocol dissectors to free up memory that they
415 * don't need after the sequential run-through of the packets. */
416 postseq_cleanup_all_protocols();
418 /* Set the file encapsulation type now; we don't know what it is until
419 we've looked at all the packets, as we don't know until then whether
420 there's more than one type (and thus whether it's
421 WTAP_ENCAP_PER_PACKET). */
422 cf->lnk_t = wtap_file_encap(cf->wth);
424 cf->current_frame = cf->first_displayed;
427 cf_callback_invoke(cf_cb_file_read_finished, cf);
429 /* If we have any displayed packets to select, select the first of those
430 packets by making the first row the selected row. */
431 if (cf->first_displayed != NULL)
432 packet_list_select_row(0);
435 /* Put up a message box noting that the read failed somewhere along
436 the line. Don't throw out the stuff we managed to read, though,
440 case WTAP_ERR_UNSUPPORTED_ENCAP:
441 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
442 "The capture file has a packet with a network type that Ethereal doesn't support.\n(%s)",
445 errmsg = errmsg_errno;
448 case WTAP_ERR_CANT_READ:
449 errmsg = "An attempt to read from the capture file failed for"
450 " some unknown reason.";
453 case WTAP_ERR_SHORT_READ:
454 errmsg = "The capture file appears to have been cut short"
455 " in the middle of a packet.";
458 case WTAP_ERR_BAD_RECORD:
459 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
460 "The capture file appears to be damaged or corrupt.\n(%s)",
463 errmsg = errmsg_errno;
467 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
468 "An error occurred while reading the"
469 " capture file: %s.", wtap_strerror(err));
470 errmsg = errmsg_errno;
473 g_snprintf(err_str, sizeof err_str, errmsg);
474 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
475 return CF_READ_ERROR;
482 cf_start_tail(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
484 cf_status_t cf_status;
486 cf_status = cf_open(cf, fname, is_tempfile, err);
491 cf_continue_tail(capture_file *cf, int to_read, int *err)
493 long data_offset = 0;
498 packet_list_freeze();
500 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
501 if (cf->state == FILE_READ_ABORTED) {
502 /* Well, the user decided to exit Ethereal. Break out of the
503 loop, and let the code below (which is called even if there
504 aren't any packets left to read) exit. */
507 read_packet(cf, data_offset);
513 /* XXX - this cheats and looks inside the packet list to find the final
515 if (auto_scroll_live && cf->plist_end != NULL)
516 packet_list_moveto_end();
518 if (cf->state == FILE_READ_ABORTED) {
519 /* Well, the user decided to exit Ethereal. Return CF_READ_ABORTED
520 so that our caller can kill off the capture child process;
521 this will cause an EOF on the pipe from the child, so
522 "cf_finish_tail()" will be called, and it will clean up
524 return CF_READ_ABORTED;
525 } else if (*err != 0) {
526 /* We got an error reading the capture file.
527 XXX - pop up a dialog box? */
528 return CF_READ_ERROR;
534 cf_finish_tail(capture_file *cf, int *err)
539 if(cf->wth == NULL) {
541 return CF_READ_ERROR;
544 packet_list_freeze();
546 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
547 if (cf->state == FILE_READ_ABORTED) {
548 /* Well, the user decided to abort the read. Break out of the
549 loop, and let the code below (which is called even if there
550 aren't any packets left to read) exit. */
553 read_packet(cf, data_offset);
556 if (cf->state == FILE_READ_ABORTED) {
557 /* Well, the user decided to abort the read. We're only called
558 when the child capture process closes the pipe to us (meaning
559 it's probably exited), so we can just close the capture
560 file; we return CF_READ_ABORTED so our caller can do whatever
561 is appropriate when that happens. */
563 return CF_READ_ABORTED;
567 if (auto_scroll_live && cf->plist_end != NULL)
568 /* XXX - this cheats and looks inside the packet list to find the final
570 packet_list_moveto_end();
572 /* We're done reading sequentially through the file. */
573 cf->state = FILE_READ_DONE;
575 /* We're done reading sequentially through the file; close the
576 sequential I/O side, to free up memory it requires. */
577 wtap_sequential_close(cf->wth);
579 /* Allow the protocol dissectors to free up memory that they
580 * don't need after the sequential run-through of the packets. */
581 postseq_cleanup_all_protocols();
583 /* Set the file encapsulation type now; we don't know what it is until
584 we've looked at all the packets, as we don't know until then whether
585 there's more than one type (and thus whether it's
586 WTAP_ENCAP_PER_PACKET). */
587 cf->lnk_t = wtap_file_encap(cf->wth);
590 /* We got an error reading the capture file.
591 XXX - pop up a dialog box? */
592 return CF_READ_ERROR;
597 #endif /* HAVE_LIBPCAP */
600 cf_get_display_name(capture_file *cf)
602 const gchar *displayname;
604 /* Return a name to use in displays */
605 if (!cf->is_tempfile) {
606 /* Get the last component of the file name, and use that. */
608 displayname = get_basename(cf->filename);
610 displayname="(No file)";
613 /* The file we read is a temporary file from a live capture;
614 we don't mention its name. */
615 displayname = "(Untitled)";
620 /* XXX - use a macro instead? */
622 cf_packet_count(capture_file *cf)
627 /* XXX - use a macro instead? */
629 cf_is_tempfile(capture_file *cf)
631 return cf->is_tempfile;
634 void cf_set_tempfile(capture_file *cf, gboolean is_tempfile)
636 cf->is_tempfile = is_tempfile;
640 /* XXX - use a macro instead? */
641 void cf_set_drops_known(capture_file *cf, gboolean drops_known)
643 cf->drops_known = drops_known;
646 /* XXX - use a macro instead? */
647 void cf_set_drops(capture_file *cf, guint32 drops)
652 /* XXX - use a macro instead? */
653 gboolean cf_get_drops_known(capture_file *cf)
655 return cf->drops_known;
658 /* XXX - use a macro instead? */
659 guint32 cf_get_drops(capture_file *cf)
664 void cf_set_rfcode(capture_file *cf, dfilter_t *rfcode)
670 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
671 union wtap_pseudo_header *pseudo_header, const guchar *buf,
675 gboolean create_proto_tree = FALSE;
678 /* just add some value here until we know if it is being displayed or not */
679 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
681 /* If we don't have the time stamp of the first packet in the
682 capture, it's because this is the first packet. Save the time
683 stamp of this packet as the time stamp of the first packet. */
684 if (!firstsec && !firstusec) {
685 firstsec = fdata->abs_secs;
686 firstusec = fdata->abs_usecs;
688 /* if this frames is marked as a reference time frame, reset
689 firstsec and firstusec to this frame */
690 if(fdata->flags.ref_time){
691 firstsec = fdata->abs_secs;
692 firstusec = fdata->abs_usecs;
695 /* If we don't have the time stamp of the previous displayed packet,
696 it's because this is the first displayed packet. Save the time
697 stamp of this packet as the time stamp of the previous displayed
699 if (!prevsec && !prevusec) {
700 prevsec = fdata->abs_secs;
701 prevusec = fdata->abs_usecs;
704 /* Get the time elapsed between the first packet and this packet. */
705 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
706 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
708 /* If it's greater than the current elapsed time, set the elapsed time
709 to it (we check for "greater than" so as not to be confused by
710 time moving backwards). */
711 if ((gint32)cf->esec < fdata->rel_secs
712 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
713 cf->esec = fdata->rel_secs;
714 cf->eusec = fdata->rel_usecs;
717 /* Get the time elapsed between the previous displayed packet and
719 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
720 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
724 we have a display filter and are re-applying it;
726 we have a list of color filters;
728 we have tap listeners;
730 allocate a protocol tree root node, so that we'll construct
731 a protocol tree against which a filter expression can be
733 if ((cf->dfcode != NULL && refilter) || color_filters_used()
734 || num_tap_filters != 0)
735 create_proto_tree = TRUE;
737 /* Dissect the frame. */
738 edt = epan_dissect_new(create_proto_tree, FALSE);
740 if (cf->dfcode != NULL && refilter) {
741 epan_dissect_prime_dfilter(edt, cf->dfcode);
743 if (color_filters_used()) {
744 color_filters_prime_edt(edt);
747 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
748 tap_push_tapped_queue(edt);
750 /* If we have a display filter, apply it if we're refiltering, otherwise
751 leave the "passed_dfilter" flag alone.
753 If we don't have a display filter, set "passed_dfilter" to 1. */
754 if (cf->dfcode != NULL) {
756 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
759 fdata->flags.passed_dfilter = 1;
761 if( (fdata->flags.passed_dfilter)
762 || (edt->pi.fd->flags.ref_time) ){
763 /* This frame either passed the display filter list or is marked as
764 a time reference frame. All time reference frames are displayed
765 even if they dont pass the display filter */
766 /* if this was a TIME REF frame we should reset the cul bytes field */
767 if(edt->pi.fd->flags.ref_time){
768 cum_bytes = fdata->pkt_len;
769 fdata->cum_bytes = cum_bytes;
772 /* increase cum_bytes with this packets length */
773 cum_bytes += fdata->pkt_len;
775 epan_dissect_fill_in_columns(edt);
777 /* If we haven't yet seen the first frame, this is it.
779 XXX - we must do this before we add the row to the display,
780 as, if the display's GtkCList's selection mode is
781 GTK_SELECTION_BROWSE, when the first entry is added to it,
782 "cf_select_packet()" will be called, and it will fetch the row
783 data for the 0th row, and will get a null pointer rather than
784 "fdata", as "gtk_clist_append()" won't yet have returned and
785 thus "gtk_clist_set_row_data()" won't yet have been called.
787 We thus need to leave behind bread crumbs so that
788 "cf_select_packet()" can find this frame. See the comment
789 in "cf_select_packet()". */
790 if (cf->first_displayed == NULL)
791 cf->first_displayed = fdata;
793 /* This is the last frame we've seen so far. */
794 cf->last_displayed = fdata;
796 row = packet_list_append(cf->cinfo.col_data, fdata);
798 /* colorize packet: if packet is marked, use preferences,
799 otherwise try to apply color filters */
800 if (fdata->flags.marked) {
801 fdata->color_filter = NULL;
802 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
804 fdata->color_filter = color_filters_colorize_packet(row, edt);
807 /* Set the time of the previous displayed frame to the time of this
809 prevsec = fdata->abs_secs;
810 prevusec = fdata->abs_usecs;
812 cf->displayed_count++;
814 /* This frame didn't pass the display filter, so it's not being added
815 to the clist, and thus has no row. */
818 epan_dissect_free(edt);
823 read_packet(capture_file *cf, long offset)
825 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
826 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
827 const guchar *buf = wtap_buf_ptr(cf->wth);
830 frame_data *plist_end;
833 /* Allocate the next list entry, and add it to the list. */
834 fdata = g_mem_chunk_alloc(cf->plist_chunk);
839 fdata->pkt_len = phdr->len;
840 fdata->cap_len = phdr->caplen;
841 fdata->file_off = offset;
842 fdata->lnk_t = phdr->pkt_encap;
843 fdata->abs_secs = phdr->ts.tv_sec;
844 fdata->abs_usecs = phdr->ts.tv_usec;
845 fdata->flags.encoding = CHAR_ASCII;
846 fdata->flags.visited = 0;
847 fdata->flags.marked = 0;
848 fdata->flags.ref_time = 0;
852 edt = epan_dissect_new(TRUE, FALSE);
853 epan_dissect_prime_dfilter(edt, cf->rfcode);
854 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
855 passed = dfilter_apply_edt(cf->rfcode, edt);
856 epan_dissect_free(edt);
859 plist_end = cf->plist_end;
860 fdata->prev = plist_end;
861 if (plist_end != NULL)
862 plist_end->next = fdata;
865 cf->plist_end = fdata;
868 cf->f_datalen = offset + phdr->caplen;
869 fdata->num = cf->count;
870 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
872 /* XXX - if we didn't have read filters, or if we could avoid
873 allocating the "frame_data" structure until we knew whether
874 the frame passed the read filter, we could use a G_ALLOC_ONLY
877 ...but, at least in one test I did, where I just made the chunk
878 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
879 seem to save a noticeable amount of time or space. */
880 g_mem_chunk_free(cf->plist_chunk, fdata);
885 cf_merge_files(char **out_filenamep, int in_file_count,
886 char *const *in_filenames, int file_type, gboolean do_append)
888 merge_in_file_t *in_files;
894 int open_err, read_err, write_err, close_err;
898 char errmsg_errno[1024+1];
899 gchar err_str[2048+1];
901 gboolean got_read_error = FALSE, got_write_error = FALSE;
903 progdlg_t *progbar = NULL;
905 gint64 f_len, file_pos;
908 gchar status_str[100];
909 int progbar_nextstep;
912 /* open the input files */
913 if (!merge_open_in_files(in_file_count, in_filenames, &in_files,
914 &open_err, &err_info, &err_fileno)) {
916 cf_open_failure_alert_box(in_filenames[err_fileno], open_err, err_info,
921 if (*out_filenamep != NULL) {
922 out_filename = *out_filenamep;
923 out_fd = open(out_filename, O_CREAT|O_TRUNC|O_BINARY, 0600);
927 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
930 out_filename = g_strdup(tmpname);
931 *out_filenamep = out_filename;
935 merge_close_in_files(in_file_count, in_files);
937 cf_open_failure_alert_box(out_filename, open_err, NULL, TRUE, file_type);
941 pdh = wtap_dump_fdopen(out_fd, file_type,
942 merge_select_frame_type(in_file_count, in_files),
943 merge_max_snapshot_length(in_file_count, in_files), &open_err);
946 merge_close_in_files(in_file_count, in_files);
948 cf_open_failure_alert_box(out_filename, open_err, err_info, TRUE,
953 /* Get the sum of the sizes of all the files. */
955 for (i = 0; i < in_file_count; i++)
956 f_len += in_files[i].size;
958 /* Update the progress bar when it gets to this value. */
959 progbar_nextstep = 0;
960 /* When we reach the value that triggers a progress bar update,
961 bump that value by this amount. */
962 progbar_quantum = f_len/N_PROGBAR_UPDATES;
965 g_get_current_time(&start_time);
967 /* do the merge (or append) */
970 wth = merge_append_read_packet(in_file_count, in_files, &read_err,
973 wth = merge_read_packet(in_file_count, in_files, &read_err,
977 got_read_error = TRUE;
981 /* Get the sum of the data offsets in all of the files. */
983 for (i = 0; i < in_file_count; i++)
984 data_offset += in_files[i].data_offset;
986 if (data_offset >= progbar_nextstep) {
987 /* Get the sum of the seek positions in all of the files. */
989 for (i = 0; i < in_file_count; i++)
990 file_pos += wtap_read_so_far(in_files[i].wth, NULL);
991 prog_val = (gfloat) file_pos / (gfloat) f_len;
992 if (prog_val > 1.0) {
993 /* Some file probably grew while we were reading it.
994 That "shouldn't happen", so we'll just clip the progress
998 if (progbar == NULL) {
999 /* Create the progress bar if necessary */
1000 progbar = delayed_create_progress_dlg("Merging", "files",
1001 &stop_flag, &start_time, prog_val);
1003 if (progbar != NULL) {
1004 g_snprintf(status_str, sizeof(status_str),
1005 "%" PRId64 "KB of %" PRId64 "KB",
1006 file_pos / 1024, f_len / 1024);
1007 update_progress_dlg(progbar, prog_val, status_str);
1009 progbar_nextstep += progbar_quantum;
1012 if (!wtap_dump(pdh, wtap_phdr(wth), wtap_pseudoheader(wth),
1013 wtap_buf_ptr(wth), &write_err)) {
1014 got_write_error = TRUE;
1019 /* We're done merging the files; destroy the progress bar if it was created. */
1020 if (progbar != NULL)
1021 destroy_progress_dlg(progbar);
1023 merge_close_in_files(in_file_count, in_files);
1024 if (!got_read_error && !got_write_error) {
1025 if (!wtap_dump_close(pdh, &write_err))
1026 got_write_error = TRUE;
1028 wtap_dump_close(pdh, &close_err);
1030 if (got_read_error) {
1032 * Find the file on which we got the error, and report the error.
1034 for (i = 0; i < in_file_count; i++) {
1035 if (in_files[i].state == GOT_ERROR) {
1036 /* Put up a message box noting that a read failed somewhere along
1040 case WTAP_ERR_UNSUPPORTED_ENCAP:
1041 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1042 "The capture file %%s has a packet with a network type that Ethereal doesn't support.\n(%s)",
1045 errmsg = errmsg_errno;
1048 case WTAP_ERR_CANT_READ:
1049 errmsg = "An attempt to read from the capture file %s failed for"
1050 " some unknown reason.";
1053 case WTAP_ERR_SHORT_READ:
1054 errmsg = "The capture file %s appears to have been cut short"
1055 " in the middle of a packet.";
1058 case WTAP_ERR_BAD_RECORD:
1059 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1060 "The capture file %%s appears to be damaged or corrupt.\n(%s)",
1063 errmsg = errmsg_errno;
1067 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
1068 "An error occurred while reading the"
1069 " capture file %%s: %s.", wtap_strerror(read_err));
1070 errmsg = errmsg_errno;
1073 g_snprintf(err_str, sizeof err_str, errmsg, in_files[i].filename);
1074 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
1079 if (got_write_error) {
1080 /* Put up an alert box for the write error. */
1081 cf_write_failure_alert_box(out_filename, write_err);
1084 return (!got_read_error && !got_write_error) ? CF_OK : CF_ERROR;
1088 cf_filter_packets(capture_file *cf, gchar *dftext, gboolean force)
1091 const char *filter_new = dftext ? dftext : "";
1092 const char *filter_old = cf->dfilter ? cf->dfilter : "";
1094 /* if new filter equals old one, do nothing unless told to do so */
1095 if (!force && strcmp(filter_new, filter_old) == 0) {
1099 if (dftext == NULL) {
1100 /* The new filter is an empty filter (i.e., display all packets). */
1104 * We have a filter; make a copy of it (as we'll be saving it),
1105 * and try to compile it.
1107 dftext = g_strdup(dftext);
1108 if (!dfilter_compile(dftext, &dfcode)) {
1109 /* The attempt failed; report an error. */
1110 gchar *safe_dftext = simple_dialog_format_message(dftext);
1111 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
1113 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1116 "The following display filter isn't a valid display filter:\n%s\n"
1117 "See the help for a description of the display filter syntax.",
1118 simple_dialog_primary_start(), safe_dfilter_error_msg,
1119 simple_dialog_primary_end(), safe_dftext);
1120 g_free(safe_dfilter_error_msg);
1121 g_free(safe_dftext);
1127 if (dfcode == NULL) {
1128 /* Yes - free the filter text, and set it to null. */
1134 /* We have a valid filter. Replace the current filter. */
1135 if (cf->dfilter != NULL)
1136 g_free(cf->dfilter);
1137 cf->dfilter = dftext;
1138 if (cf->dfcode != NULL)
1139 dfilter_free(cf->dfcode);
1140 cf->dfcode = dfcode;
1142 /* Now rescan the packet list, applying the new filter, but not
1143 throwing away information constructed on a previous pass. */
1144 if (dftext == NULL) {
1145 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1147 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1153 cf_colorize_packets(capture_file *cf)
1155 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1159 cf_reftime_packets(capture_file *cf)
1161 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1165 cf_redissect_packets(capture_file *cf)
1167 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1170 /* Rescan the list of packets, reconstructing the CList.
1172 "action" describes why we're doing this; it's used in the progress
1175 "action_item" describes what we're doing; it's used in the progress
1178 "refilter" is TRUE if we need to re-evaluate the filter expression.
1180 "redissect" is TRUE if we need to make the dissectors reconstruct
1181 any state information they have (because a preference that affects
1182 some dissector has changed, meaning some dissector might construct
1183 its state differently from the way it was constructed the last time). */
1185 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1186 gboolean refilter, gboolean redissect)
1189 progdlg_t *progbar = NULL;
1194 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1195 int selected_row, prev_row, preceding_row, following_row;
1196 gboolean selected_frame_seen;
1199 GTimeVal start_time;
1200 gchar status_str[100];
1201 int progbar_nextstep;
1202 int progbar_quantum;
1205 reset_tap_listeners();
1206 /* Which frame, if any, is the currently selected frame?
1207 XXX - should the selected frame or the focus frame be the "current"
1208 frame, that frame being the one from which "Find Frame" searches
1210 selected_frame = cf->current_frame;
1212 /* We don't yet know what row that frame will be on, if any, after we
1213 rebuild the clist, however. */
1217 /* We need to re-initialize all the state information that protocols
1218 keep, because some preference that controls a dissector has changed,
1219 which might cause the state information to be constructed differently
1220 by that dissector. */
1222 /* Initialize all data structures used for dissection. */
1226 /* Freeze the packet list while we redo it, so we don't get any
1227 screen updates while it happens. */
1228 packet_list_freeze();
1231 packet_list_clear();
1233 /* We don't yet know which will be the first and last frames displayed. */
1234 cf->first_displayed = NULL;
1235 cf->last_displayed = NULL;
1237 /* We currently don't display any packets */
1238 cf->displayed_count = 0;
1240 /* Iterate through the list of frames. Call a routine for each frame
1241 to check whether it should be displayed and, if so, add it to
1242 the display list. */
1248 /* Update the progress bar when it gets to this value. */
1249 progbar_nextstep = 0;
1250 /* When we reach the value that triggers a progress bar update,
1251 bump that value by this amount. */
1252 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1253 /* Count of packets at which we've looked. */
1257 g_get_current_time(&start_time);
1259 row = -1; /* no previous row yet */
1264 preceding_frame = NULL;
1266 following_frame = NULL;
1268 selected_frame_seen = FALSE;
1270 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1271 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1272 when we update it, we have to run the GTK+ main loop to get it
1273 to repaint what's pending, and doing so may involve an "ioctl()"
1274 to see if there's any pending input from an X server, and doing
1275 that for every packet can be costly, especially on a big file. */
1276 if (count >= progbar_nextstep) {
1277 /* let's not divide by zero. I should never be started
1278 * with count == 0, so let's assert that
1280 g_assert(cf->count > 0);
1281 prog_val = (gfloat) count / cf->count;
1283 if (progbar == NULL)
1284 /* Create the progress bar if necessary */
1285 progbar = delayed_create_progress_dlg(action, action_item, &stop_flag,
1286 &start_time, prog_val);
1288 if (progbar != NULL) {
1289 g_snprintf(status_str, sizeof(status_str),
1290 "%4u of %u frames", count, cf->count);
1291 update_progress_dlg(progbar, prog_val, status_str);
1294 progbar_nextstep += progbar_quantum;
1298 /* Well, the user decided to abort the filtering. Just stop.
1300 XXX - go back to the previous filter? Users probably just
1301 want not to wait for a filtering operation to finish;
1302 unless we cancel by having no filter, reverting to the
1303 previous filter will probably be even more expensive than
1304 continuing the filtering, as it involves going back to the
1305 beginning and filtering, and even with no filter we currently
1306 have to re-generate the entire clist, which is also expensive.
1308 I'm not sure what Network Monitor does, but it doesn't appear
1309 to give you an unfiltered display if you cancel. */
1316 /* Since all state for the frame was destroyed, mark the frame
1317 * as not visited, free the GSList referring to the state
1318 * data (the per-frame data itself was freed by
1319 * "init_dissection()"), and null out the GSList pointer. */
1320 fdata->flags.visited = 0;
1322 g_slist_free(fdata->pfd);
1327 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1328 cf->pd, fdata->cap_len, &err, &err_info)) {
1329 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1330 cf_read_error_message(err, err_info), cf->filename);
1334 /* If the previous frame is displayed, and we haven't yet seen the
1335 selected frame, remember that frame - it's the closest one we've
1336 yet seen before the selected frame. */
1337 if (prev_row != -1 && !selected_frame_seen) {
1338 preceding_row = prev_row;
1339 preceding_frame = prev_frame;
1341 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1344 /* If this frame is displayed, and this is the first frame we've
1345 seen displayed after the selected frame, remember this frame -
1346 it's the closest one we've yet seen at or after the selected
1348 if (row != -1 && selected_frame_seen && following_row == -1) {
1349 following_row = row;
1350 following_frame = fdata;
1352 if (fdata == selected_frame) {
1354 selected_frame_seen = TRUE;
1357 /* Remember this row/frame - it'll be the previous row/frame
1358 on the next pass through the loop. */
1364 /* Clear out what remains of the visited flags and per-frame data
1367 XXX - that may cause various forms of bogosity when dissecting
1368 these frames, as they won't have been seen by this sequential
1369 pass, but the only alternative I see is to keep scanning them
1370 even though the user requested that the scan stop, and that
1371 would leave the user stuck with an Ethereal grinding on
1372 until it finishes. Should we just stick them with that? */
1373 for (; fdata != NULL; fdata = fdata->next) {
1374 fdata->flags.visited = 0;
1376 g_slist_free(fdata->pfd);
1382 /* We're done filtering the packets; destroy the progress bar if it
1384 if (progbar != NULL)
1385 destroy_progress_dlg(progbar);
1387 /* Unfreeze the packet list. */
1390 if (selected_row == -1) {
1391 /* The selected frame didn't pass the filter. */
1392 if (selected_frame == NULL) {
1393 /* That's because there *was* no selected frame. Make the first
1394 displayed frame the current frame. */
1397 /* Find the nearest displayed frame to the selected frame (whether
1398 it's before or after that frame) and make that the current frame.
1399 If the next and previous displayed frames are equidistant from the
1400 selected frame, choose the next one. */
1401 g_assert(following_frame == NULL ||
1402 following_frame->num >= selected_frame->num);
1403 g_assert(preceding_frame == NULL ||
1404 preceding_frame->num <= selected_frame->num);
1405 if (following_frame == NULL) {
1406 /* No frame after the selected frame passed the filter, so we
1407 have to select the last displayed frame before the selected
1409 selected_row = preceding_row;
1410 } else if (preceding_frame == NULL) {
1411 /* No frame before the selected frame passed the filter, so we
1412 have to select the first displayed frame after the selected
1414 selected_row = following_row;
1416 /* Choose the closer of the last displayed frame before the
1417 selected frame and the first displayed frame after the
1418 selected frame; in case of a tie, choose the first displayed
1419 frame after the selected frame. */
1420 if (following_frame->num - selected_frame->num <=
1421 selected_frame->num - preceding_frame->num) {
1422 selected_row = following_row;
1424 /* The previous frame is closer to the selected frame than the
1426 selected_row = preceding_row;
1432 if (selected_row == -1) {
1433 /* There are no frames displayed at all. */
1434 cf_unselect_packet(cf);
1436 /* Either the frame that was selected passed the filter, or we've
1437 found the nearest displayed frame to that frame. Select it, make
1438 it the focus row, and make it visible. */
1439 packet_list_set_selected_row(selected_row);
1450 process_specified_packets(capture_file *cf, packet_range_t *range,
1451 const char *string1, const char *string2,
1452 gboolean (*callback)(capture_file *, frame_data *,
1453 union wtap_pseudo_header *, const guint8 *, void *),
1454 void *callback_args)
1459 union wtap_pseudo_header pseudo_header;
1460 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1461 psp_return_t ret = PSP_FINISHED;
1463 progdlg_t *progbar = NULL;
1466 gboolean progbar_stop_flag;
1467 GTimeVal progbar_start_time;
1468 gchar progbar_status_str[100];
1469 int progbar_nextstep;
1470 int progbar_quantum;
1471 range_process_e process_this;
1473 /* Update the progress bar when it gets to this value. */
1474 progbar_nextstep = 0;
1475 /* When we reach the value that triggers a progress bar update,
1476 bump that value by this amount. */
1477 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1478 /* Count of packets at which we've looked. */
1481 progbar_stop_flag = FALSE;
1482 g_get_current_time(&progbar_start_time);
1484 packet_range_process_init(range);
1486 /* Iterate through the list of packets, printing the packets that
1487 were selected by the current display filter. */
1488 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1489 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1490 when we update it, we have to run the GTK+ main loop to get it
1491 to repaint what's pending, and doing so may involve an "ioctl()"
1492 to see if there's any pending input from an X server, and doing
1493 that for every packet can be costly, especially on a big file. */
1494 if (progbar_count >= progbar_nextstep) {
1495 /* let's not divide by zero. I should never be started
1496 * with count == 0, so let's assert that
1498 g_assert(cf->count > 0);
1499 progbar_val = (gfloat) progbar_count / cf->count;
1501 if (progbar == NULL)
1502 /* Create the progress bar if necessary */
1503 progbar = delayed_create_progress_dlg(string1, string2,
1505 &progbar_start_time,
1508 if (progbar != NULL) {
1509 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1510 "%4u of %u packets", progbar_count, cf->count);
1511 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1514 progbar_nextstep += progbar_quantum;
1517 if (progbar_stop_flag) {
1518 /* Well, the user decided to abort the operation. Just stop,
1519 and arrange to return TRUE to our caller, so they know it
1520 was stopped explicitly. */
1527 /* do we have to process this packet? */
1528 process_this = packet_range_process_packet(range, fdata);
1529 if (process_this == range_process_next) {
1530 /* this packet uninteresting, continue with next one */
1532 } else if (process_this == range_processing_finished) {
1533 /* all interesting packets processed, stop the loop */
1537 /* Get the packet */
1538 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1539 pd, fdata->cap_len, &err, &err_info)) {
1540 /* Attempt to get the packet failed. */
1541 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1542 cf_read_error_message(err, err_info), cf->filename);
1546 /* Process the packet */
1547 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1548 /* Callback failed. We assume it reported the error appropriately. */
1554 /* We're done printing the packets; destroy the progress bar if
1556 if (progbar != NULL)
1557 destroy_progress_dlg(progbar);
1563 retap_packet(capture_file *cf _U_, frame_data *fdata,
1564 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1567 epan_dissect_t *edt;
1569 /* If we have tap listeners, allocate a protocol tree root node, so that
1570 we'll construct a protocol tree against which a filter expression can
1572 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1573 tap_queue_init(edt);
1574 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1575 tap_push_tapped_queue(edt);
1576 epan_dissect_free(edt);
1582 cf_retap_packets(capture_file *cf)
1584 packet_range_t range;
1586 /* Reset the tap listeners. */
1587 reset_tap_listeners();
1589 /* Iterate through the list of packets, dissecting all packets and
1590 re-running the taps. */
1591 packet_range_init(&range);
1592 packet_range_process_init(&range);
1593 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1594 "all packets", retap_packet,
1597 /* Completed successfully. */
1601 /* Well, the user decided to abort the refiltering.
1602 Return CF_READ_ABORTED so our caller knows they did that. */
1603 return CF_READ_ABORTED;
1606 /* Error while retapping. */
1607 return CF_READ_ERROR;
1610 g_assert_not_reached();
1615 print_args_t *print_args;
1616 gboolean print_header_line;
1617 char *header_line_buf;
1618 int header_line_buf_len;
1619 gboolean print_formfeed;
1620 gboolean print_separator;
1624 } print_callback_args_t;
1627 print_packet(capture_file *cf, frame_data *fdata,
1628 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1631 print_callback_args_t *args = argsp;
1632 epan_dissect_t *edt;
1638 gboolean proto_tree_needed;
1639 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1640 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1642 /* Create the protocol tree, and make it visible, if we're printing
1643 the dissection or the hex data.
1644 XXX - do we need it if we're just printing the hex data? */
1646 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1647 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1649 /* Fill in the column information if we're printing the summary
1651 if (args->print_args->print_summary) {
1652 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1653 epan_dissect_fill_in_columns(edt);
1655 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1657 if (args->print_formfeed) {
1658 if (!new_page(args->print_args->stream))
1661 if (args->print_separator) {
1662 if (!print_line(args->print_args->stream, 0, ""))
1668 * We generate bookmarks, if the output format supports them.
1669 * The name is "__frameN__".
1671 g_snprintf(bookmark_name, sizeof bookmark_name, "__frame%u__", fdata->num);
1673 if (args->print_args->print_summary) {
1674 if (args->print_header_line) {
1675 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1677 args->print_header_line = FALSE; /* we might not need to print any more */
1679 cp = &args->line_buf[0];
1681 for (i = 0; i < cf->cinfo.num_cols; i++) {
1682 /* Find the length of the string for this column. */
1683 column_len = strlen(cf->cinfo.col_data[i]);
1684 if (args->col_widths[i] > column_len)
1685 column_len = args->col_widths[i];
1687 /* Make sure there's room in the line buffer for the column; if not,
1688 double its length. */
1689 line_len += column_len + 1; /* "+1" for space */
1690 if (line_len > args->line_buf_len) {
1691 cp_off = cp - args->line_buf;
1692 args->line_buf_len = 2 * line_len;
1693 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1694 cp = args->line_buf + cp_off;
1697 /* Right-justify the packet number column. */
1698 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1699 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1701 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1703 if (i != cf->cinfo.num_cols - 1)
1709 * Generate a bookmark, using the summary line as the title.
1711 if (!print_bookmark(args->print_args->stream, bookmark_name,
1715 if (!print_line(args->print_args->stream, 0, args->line_buf))
1719 * Generate a bookmark, using "Frame N" as the title, as we're not
1720 * printing the summary line.
1722 g_snprintf(bookmark_title, sizeof bookmark_title, "Frame %u", fdata->num);
1723 if (!print_bookmark(args->print_args->stream, bookmark_name,
1726 } /* if (print_summary) */
1728 if (args->print_args->print_dissections != print_dissections_none) {
1729 if (args->print_args->print_summary) {
1730 /* Separate the summary line from the tree with a blank line. */
1731 if (!print_line(args->print_args->stream, 0, ""))
1735 /* Print the information in that tree. */
1736 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1739 /* Print a blank line if we print anything after this (aka more than one packet). */
1740 args->print_separator = TRUE;
1742 /* Print a header line if we print any more packet summaries */
1743 args->print_header_line = TRUE;
1746 if (args->print_args->print_hex) {
1747 /* Print the full packet data as hex. */
1748 if (!print_hex_data(args->print_args->stream, edt))
1751 /* Print a blank line if we print anything after this (aka more than one packet). */
1752 args->print_separator = TRUE;
1754 /* Print a header line if we print any more packet summaries */
1755 args->print_header_line = TRUE;
1756 } /* if (args->print_args->print_dissections != print_dissections_none) */
1758 epan_dissect_free(edt);
1760 /* do we want to have a formfeed between each packet from now on? */
1761 if(args->print_args->print_formfeed) {
1762 args->print_formfeed = TRUE;
1768 epan_dissect_free(edt);
1773 cf_print_packets(capture_file *cf, print_args_t *print_args)
1776 print_callback_args_t callback_args;
1784 callback_args.print_args = print_args;
1785 callback_args.print_header_line = TRUE;
1786 callback_args.header_line_buf = NULL;
1787 callback_args.header_line_buf_len = 256;
1788 callback_args.print_formfeed = FALSE;
1789 callback_args.print_separator = FALSE;
1790 callback_args.line_buf = NULL;
1791 callback_args.line_buf_len = 256;
1792 callback_args.col_widths = NULL;
1794 if (!print_preamble(print_args->stream, cf->filename)) {
1795 destroy_print_stream(print_args->stream);
1796 return CF_PRINT_WRITE_ERROR;
1799 if (print_args->print_summary) {
1800 /* We're printing packet summaries. Allocate the header line buffer
1801 and get the column widths. */
1802 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1804 /* Find the widths for each of the columns - maximum of the
1805 width of the title and the width of the data - and construct
1806 a buffer with a line containing the column titles. */
1807 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1808 cp = &callback_args.header_line_buf[0];
1810 for (i = 0; i < cf->cinfo.num_cols; i++) {
1811 /* Don't pad the last column. */
1812 if (i == cf->cinfo.num_cols - 1)
1813 callback_args.col_widths[i] = 0;
1815 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1816 data_width = get_column_char_width(get_column_format(i));
1817 if (data_width > callback_args.col_widths[i])
1818 callback_args.col_widths[i] = data_width;
1821 /* Find the length of the string for this column. */
1822 column_len = strlen(cf->cinfo.col_title[i]);
1823 if (callback_args.col_widths[i] > column_len)
1824 column_len = callback_args.col_widths[i];
1826 /* Make sure there's room in the line buffer for the column; if not,
1827 double its length. */
1828 line_len += column_len + 1; /* "+1" for space */
1829 if (line_len > callback_args.header_line_buf_len) {
1830 cp_off = cp - callback_args.header_line_buf;
1831 callback_args.header_line_buf_len = 2 * line_len;
1832 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1833 callback_args.header_line_buf_len + 1);
1834 cp = callback_args.header_line_buf + cp_off;
1837 /* Right-justify the packet number column. */
1838 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1839 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1841 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1843 if (i != cf->cinfo.num_cols - 1)
1848 /* Now start out the main line buffer with the same length as the
1849 header line buffer. */
1850 callback_args.line_buf_len = callback_args.header_line_buf_len;
1851 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1852 } /* if (print_summary) */
1854 /* Iterate through the list of packets, printing the packets we were
1856 ret = process_specified_packets(cf, &print_args->range, "Printing",
1857 "selected packets", print_packet,
1860 if (callback_args.header_line_buf != NULL)
1861 g_free(callback_args.header_line_buf);
1862 if (callback_args.line_buf != NULL)
1863 g_free(callback_args.line_buf);
1864 if (callback_args.col_widths != NULL)
1865 g_free(callback_args.col_widths);
1870 /* Completed successfully. */
1874 /* Well, the user decided to abort the printing.
1876 XXX - note that what got generated before they did that
1877 will get printed if we're piping to a print program; we'd
1878 have to write to a file and then hand that to the print
1879 program to make it actually not print anything. */
1883 /* Error while printing.
1885 XXX - note that what got generated before they did that
1886 will get printed if we're piping to a print program; we'd
1887 have to write to a file and then hand that to the print
1888 program to make it actually not print anything. */
1889 destroy_print_stream(print_args->stream);
1890 return CF_PRINT_WRITE_ERROR;
1893 if (!print_finale(print_args->stream)) {
1894 destroy_print_stream(print_args->stream);
1895 return CF_PRINT_WRITE_ERROR;
1898 if (!destroy_print_stream(print_args->stream))
1899 return CF_PRINT_WRITE_ERROR;
1905 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
1906 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1910 epan_dissect_t *edt;
1912 /* Create the protocol tree, but don't fill in the column information. */
1913 edt = epan_dissect_new(TRUE, TRUE);
1914 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1916 /* Write out the information in that tree. */
1917 proto_tree_write_pdml(edt, fh);
1919 epan_dissect_free(edt);
1925 cf_write_pdml_packets(capture_file *cf, print_args_t *print_args)
1930 fh = fopen(print_args->file, "w");
1932 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
1934 write_pdml_preamble(fh);
1937 return CF_PRINT_WRITE_ERROR;
1940 /* Iterate through the list of packets, printing the packets we were
1942 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
1943 "selected packets", write_pdml_packet,
1949 /* Completed successfully. */
1953 /* Well, the user decided to abort the printing. */
1957 /* Error while printing. */
1959 return CF_PRINT_WRITE_ERROR;
1962 write_pdml_finale(fh);
1965 return CF_PRINT_WRITE_ERROR;
1968 /* XXX - check for an error */
1975 write_psml_packet(capture_file *cf, frame_data *fdata,
1976 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1980 epan_dissect_t *edt;
1982 /* Fill in the column information, but don't create the protocol tree. */
1983 edt = epan_dissect_new(FALSE, FALSE);
1984 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1985 epan_dissect_fill_in_columns(edt);
1987 /* Write out the information in that tree. */
1988 proto_tree_write_psml(edt, fh);
1990 epan_dissect_free(edt);
1996 cf_write_psml_packets(capture_file *cf, print_args_t *print_args)
2001 fh = fopen(print_args->file, "w");
2003 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2005 write_psml_preamble(fh);
2008 return CF_PRINT_WRITE_ERROR;
2011 /* Iterate through the list of packets, printing the packets we were
2013 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
2014 "selected packets", write_psml_packet,
2020 /* Completed successfully. */
2024 /* Well, the user decided to abort the printing. */
2028 /* Error while printing. */
2030 return CF_PRINT_WRITE_ERROR;
2033 write_psml_finale(fh);
2036 return CF_PRINT_WRITE_ERROR;
2039 /* XXX - check for an error */
2046 write_csv_packet(capture_file *cf, frame_data *fdata,
2047 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2051 epan_dissect_t *edt;
2053 /* Fill in the column information, but don't create the protocol tree. */
2054 edt = epan_dissect_new(FALSE, FALSE);
2055 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
2056 epan_dissect_fill_in_columns(edt);
2058 /* Write out the information in that tree. */
2059 proto_tree_write_csv(edt, fh);
2061 epan_dissect_free(edt);
2067 cf_write_csv_packets(capture_file *cf, print_args_t *print_args)
2072 fh = fopen(print_args->file, "w");
2074 return CF_PRINT_OPEN_ERROR; /* attempt to open destination failed */
2076 write_csv_preamble(fh);
2079 return CF_PRINT_WRITE_ERROR;
2082 /* Iterate through the list of packets, printing the packets we were
2084 ret = process_specified_packets(cf, &print_args->range, "Writing CSV",
2085 "selected packets", write_csv_packet,
2091 /* Completed successfully. */
2095 /* Well, the user decided to abort the printing. */
2099 /* Error while printing. */
2101 return CF_PRINT_WRITE_ERROR;
2104 write_csv_finale(fh);
2107 return CF_PRINT_WRITE_ERROR;
2110 /* XXX - check for an error */
2116 /* Scan through the packet list and change all columns that use the
2117 "command-line-specified" time stamp format to use the current
2118 value of that format. */
2120 cf_change_time_formats(capture_file *cf)
2123 progdlg_t *progbar = NULL;
2129 GTimeVal start_time;
2130 gchar status_str[100];
2131 int progbar_nextstep;
2132 int progbar_quantum;
2134 gboolean sorted_by_frame_column;
2136 /* Are there any columns with time stamps in the "command-line-specified"
2139 XXX - we have to force the "column is writable" flag on, as it
2140 might be off from the last frame that was dissected. */
2141 col_set_writable(&cf->cinfo, TRUE);
2142 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
2143 /* No, there aren't any columns in that format, so we have no work
2147 first = cf->cinfo.col_first[COL_CLS_TIME];
2148 g_assert(first >= 0);
2149 last = cf->cinfo.col_last[COL_CLS_TIME];
2151 /* Freeze the packet list while we redo it, so we don't get any
2152 screen updates while it happens. */
2153 packet_list_freeze();
2155 /* Update the progress bar when it gets to this value. */
2156 progbar_nextstep = 0;
2157 /* When we reach the value that triggers a progress bar update,
2158 bump that value by this amount. */
2159 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2160 /* Count of packets at which we've looked. */
2163 /* If the rows are currently sorted by the frame column then we know
2164 * the row number of each packet: it's the row number of the previously
2165 * displayed packet + 1.
2167 * Otherwise, if the display is sorted by a different column then we have
2168 * to use the O(N) packet_list_find_row_from_data() (thus making the job
2169 * of changing the time display format O(N**2)).
2171 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
2172 * the row number and walks that many elements down the clist to find
2173 * the appropriate element.)
2175 sorted_by_frame_column = FALSE;
2176 for (i = 0; i < cf->cinfo.num_cols; i++) {
2177 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
2179 sorted_by_frame_column = (i == packet_list_get_sort_column());
2185 g_get_current_time(&start_time);
2187 /* Iterate through the list of packets, checking whether the packet
2188 is in a row of the summary list and, if so, whether there are
2189 any columns that show the time in the "command-line-specified"
2190 format and, if so, update that row. */
2191 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2192 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2193 when we update it, we have to run the GTK+ main loop to get it
2194 to repaint what's pending, and doing so may involve an "ioctl()"
2195 to see if there's any pending input from an X server, and doing
2196 that for every packet can be costly, especially on a big file. */
2197 if (count >= progbar_nextstep) {
2198 /* let's not divide by zero. I should never be started
2199 * with count == 0, so let's assert that
2201 g_assert(cf->count > 0);
2203 prog_val = (gfloat) count / cf->count;
2205 if (progbar == NULL)
2206 /* Create the progress bar if necessary */
2207 progbar = delayed_create_progress_dlg("Changing", "time display",
2208 &stop_flag, &start_time, prog_val);
2210 if (progbar != NULL) {
2211 g_snprintf(status_str, sizeof(status_str),
2212 "%4u of %u packets", count, cf->count);
2213 update_progress_dlg(progbar, prog_val, status_str);
2216 progbar_nextstep += progbar_quantum;
2220 /* Well, the user decided to abort the redisplay. Just stop.
2222 XXX - this leaves the time field in the old format in
2223 frames we haven't yet processed. So it goes; should we
2224 simply not offer them the option of stopping? */
2230 /* Find what row this packet is in. */
2231 if (!sorted_by_frame_column) {
2232 /* This function is O(N), so we try to avoid using it... */
2233 row = packet_list_find_row_from_data(fdata);
2235 /* ...which we do by maintaining a count of packets that are
2236 being displayed (i.e., that have passed the display filter),
2237 and using the current value of that count as the row number
2238 (which is why we can only do it when the display is sorted
2239 by the frame number). */
2240 if (fdata->flags.passed_dfilter)
2247 /* This packet is in the summary list, on row "row". */
2249 for (i = first; i <= last; i++) {
2250 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2251 /* This is one of the columns that shows the time in
2252 "command-line-specified" format; update it. */
2253 cf->cinfo.col_buf[i][0] = '\0';
2254 col_set_cls_time(fdata, &cf->cinfo, i);
2255 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2261 /* We're done redisplaying the packets; destroy the progress bar if it
2263 if (progbar != NULL)
2264 destroy_progress_dlg(progbar);
2266 /* Set the column widths of those columns that show the time in
2267 "command-line-specified" format. */
2268 for (i = first; i <= last; i++) {
2269 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2270 packet_list_set_cls_time_width(i);
2274 /* Unfreeze the packet list. */
2282 gboolean frame_matched;
2286 cf_find_packet_protocol_tree(capture_file *cf, const char *string)
2290 mdata.string = string;
2291 mdata.string_len = strlen(string);
2292 return find_packet(cf, match_protocol_tree, &mdata);
2296 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2298 match_data *mdata = criterion;
2299 epan_dissect_t *edt;
2301 /* Construct the protocol tree, including the displayed text */
2302 edt = epan_dissect_new(TRUE, TRUE);
2303 /* We don't need the column information */
2304 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2306 /* Iterate through all the nodes, seeing if they have text that matches. */
2308 mdata->frame_matched = FALSE;
2309 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2310 epan_dissect_free(edt);
2311 return mdata->frame_matched;
2315 match_subtree_text(proto_node *node, gpointer data)
2317 match_data *mdata = (match_data*) data;
2318 const gchar *string = mdata->string;
2319 size_t string_len = mdata->string_len;
2320 capture_file *cf = mdata->cf;
2321 field_info *fi = PITEM_FINFO(node);
2322 gchar label_str[ITEM_LABEL_LENGTH];
2329 if (mdata->frame_matched) {
2330 /* We already had a match; don't bother doing any more work. */
2334 /* Don't match invisible entries. */
2335 if (PROTO_ITEM_IS_HIDDEN(node))
2338 /* was a free format label produced? */
2340 label_ptr = fi->rep->representation;
2342 /* no, make a generic label */
2343 label_ptr = label_str;
2344 proto_item_fill_label(fi, label_str);
2347 /* Does that label match? */
2348 label_len = strlen(label_ptr);
2349 for (i = 0; i < label_len; i++) {
2350 c_char = label_ptr[i];
2352 c_char = toupper(c_char);
2353 if (c_char == string[c_match]) {
2355 if (c_match == string_len) {
2356 /* No need to look further; we have a match */
2357 mdata->frame_matched = TRUE;
2364 /* Recurse into the subtree, if it exists */
2365 if (node->first_child != NULL)
2366 proto_tree_children_foreach(node, match_subtree_text, mdata);
2370 cf_find_packet_summary_line(capture_file *cf, const char *string)
2374 mdata.string = string;
2375 mdata.string_len = strlen(string);
2376 return find_packet(cf, match_summary_line, &mdata);
2380 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2382 match_data *mdata = criterion;
2383 const gchar *string = mdata->string;
2384 size_t string_len = mdata->string_len;
2385 epan_dissect_t *edt;
2386 const char *info_column;
2387 size_t info_column_len;
2388 gboolean frame_matched = FALSE;
2394 /* Don't bother constructing the protocol tree */
2395 edt = epan_dissect_new(FALSE, FALSE);
2396 /* Get the column information */
2397 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2399 /* Find the Info column */
2400 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2401 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2402 /* Found it. See if we match. */
2403 info_column = edt->pi.cinfo->col_data[colx];
2404 info_column_len = strlen(info_column);
2405 for (i = 0; i < info_column_len; i++) {
2406 c_char = info_column[i];
2408 c_char = toupper(c_char);
2409 if (c_char == string[c_match]) {
2411 if (c_match == string_len) {
2412 frame_matched = TRUE;
2421 epan_dissect_free(edt);
2422 return frame_matched;
2428 } cbs_t; /* "Counted byte string" */
2431 cf_find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2436 info.data_len = string_size;
2438 /* String or hex search? */
2440 /* String search - what type of string? */
2441 switch (cf->scs_type) {
2443 case SCS_ASCII_AND_UNICODE:
2444 return find_packet(cf, match_ascii_and_unicode, &info);
2447 return find_packet(cf, match_ascii, &info);
2450 return find_packet(cf, match_unicode, &info);
2453 g_assert_not_reached();
2457 return find_packet(cf, match_binary, &info);
2461 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2463 cbs_t *info = criterion;
2464 const char *ascii_text = info->data;
2465 size_t textlen = info->data_len;
2466 gboolean frame_matched;
2472 frame_matched = FALSE;
2473 buf_len = fdata->pkt_len;
2474 for (i = 0; i < buf_len; i++) {
2477 c_char = toupper(c_char);
2479 if (c_char == ascii_text[c_match]) {
2481 if (c_match == textlen) {
2482 frame_matched = TRUE;
2489 return frame_matched;
2493 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2495 cbs_t *info = criterion;
2496 const char *ascii_text = info->data;
2497 size_t textlen = info->data_len;
2498 gboolean frame_matched;
2504 frame_matched = FALSE;
2505 buf_len = fdata->pkt_len;
2506 for (i = 0; i < buf_len; i++) {
2509 c_char = toupper(c_char);
2510 if (c_char == ascii_text[c_match]) {
2512 if (c_match == textlen) {
2513 frame_matched = TRUE;
2519 return frame_matched;
2523 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2525 cbs_t *info = criterion;
2526 const char *ascii_text = info->data;
2527 size_t textlen = info->data_len;
2528 gboolean frame_matched;
2534 frame_matched = FALSE;
2535 buf_len = fdata->pkt_len;
2536 for (i = 0; i < buf_len; i++) {
2539 c_char = toupper(c_char);
2540 if (c_char == ascii_text[c_match]) {
2543 if (c_match == textlen) {
2544 frame_matched = TRUE;
2550 return frame_matched;
2554 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2556 cbs_t *info = criterion;
2557 const guint8 *binary_data = info->data;
2558 size_t datalen = info->data_len;
2559 gboolean frame_matched;
2564 frame_matched = FALSE;
2565 buf_len = fdata->pkt_len;
2566 for (i = 0; i < buf_len; i++) {
2567 if (cf->pd[i] == binary_data[c_match]) {
2569 if (c_match == datalen) {
2570 frame_matched = TRUE;
2576 return frame_matched;
2580 cf_find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2582 return find_packet(cf, match_dfilter, sfcode);
2586 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2588 dfilter_t *sfcode = criterion;
2589 epan_dissect_t *edt;
2590 gboolean frame_matched;
2592 edt = epan_dissect_new(TRUE, FALSE);
2593 epan_dissect_prime_dfilter(edt, sfcode);
2594 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2595 frame_matched = dfilter_apply_edt(sfcode, edt);
2596 epan_dissect_free(edt);
2597 return frame_matched;
2601 find_packet(capture_file *cf,
2602 gboolean (*match_function)(capture_file *, frame_data *, void *),
2605 frame_data *start_fd;
2607 frame_data *new_fd = NULL;
2608 progdlg_t *progbar = NULL;
2615 GTimeVal start_time;
2616 gchar status_str[100];
2617 int progbar_nextstep;
2618 int progbar_quantum;
2620 start_fd = cf->current_frame;
2621 if (start_fd != NULL) {
2622 /* Iterate through the list of packets, starting at the packet we've
2623 picked, calling a routine to run the filter on the packet, see if
2624 it matches, and stop if so. */
2628 progbar_nextstep = 0;
2629 /* When we reach the value that triggers a progress bar update,
2630 bump that value by this amount. */
2631 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2634 g_get_current_time(&start_time);
2638 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2639 when we update it, we have to run the GTK+ main loop to get it
2640 to repaint what's pending, and doing so may involve an "ioctl()"
2641 to see if there's any pending input from an X server, and doing
2642 that for every packet can be costly, especially on a big file. */
2643 if (count >= progbar_nextstep) {
2644 /* let's not divide by zero. I should never be started
2645 * with count == 0, so let's assert that
2647 g_assert(cf->count > 0);
2649 prog_val = (gfloat) count / cf->count;
2651 /* Create the progress bar if necessary */
2652 if (progbar == NULL)
2653 progbar = delayed_create_progress_dlg("Searching", cf->sfilter,
2654 &stop_flag, &start_time, prog_val);
2656 if (progbar != NULL) {
2657 g_snprintf(status_str, sizeof(status_str),
2658 "%4u of %u packets", count, cf->count);
2659 update_progress_dlg(progbar, prog_val, status_str);
2662 progbar_nextstep += progbar_quantum;
2666 /* Well, the user decided to abort the search. Go back to the
2667 frame where we started. */
2672 /* Go past the current frame. */
2673 if (cf->sbackward) {
2674 /* Go on to the previous frame. */
2675 fdata = fdata->prev;
2676 if (fdata == NULL) {
2678 * XXX - other apps have a bit more of a detailed message
2679 * for this, and instead of offering "OK" and "Cancel",
2680 * they offer things such as "Continue" and "Cancel";
2681 * we need an API for popping up alert boxes with
2682 * {Verb} and "Cancel".
2685 if (prefs.gui_find_wrap)
2687 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2688 "%sBeginning of capture exceeded!%s\n\n"
2689 "Search is continued from the end of the capture.",
2690 simple_dialog_primary_start(), simple_dialog_primary_end());
2691 fdata = cf->plist_end; /* wrap around */
2695 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2696 "%sBeginning of capture exceeded!%s\n\n"
2697 "Try searching forwards.",
2698 simple_dialog_primary_start(), simple_dialog_primary_end());
2699 fdata = start_fd; /* stay on previous packet */
2703 /* Go on to the next frame. */
2704 fdata = fdata->next;
2705 if (fdata == NULL) {
2706 if (prefs.gui_find_wrap)
2708 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2709 "%sEnd of capture exceeded!%s\n\n"
2710 "Search is continued from the start of the capture.",
2711 simple_dialog_primary_start(), simple_dialog_primary_end());
2712 fdata = cf->plist; /* wrap around */
2716 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2717 "%sEnd of capture exceeded!%s\n\n"
2718 "Try searching backwards.",
2719 simple_dialog_primary_start(), simple_dialog_primary_end());
2720 fdata = start_fd; /* stay on previous packet */
2727 /* Is this packet in the display? */
2728 if (fdata->flags.passed_dfilter) {
2729 /* Yes. Load its data. */
2730 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2731 cf->pd, fdata->cap_len, &err, &err_info)) {
2732 /* Read error. Report the error, and go back to the frame
2733 where we started. */
2734 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2735 cf_read_error_message(err, err_info), cf->filename);
2740 /* Does it match the search criterion? */
2741 if ((*match_function)(cf, fdata, criterion)) {
2743 break; /* found it! */
2747 if (fdata == start_fd) {
2748 /* We're back to the frame we were on originally, and that frame
2749 doesn't match the search filter. The search failed. */
2754 /* We're done scanning the packets; destroy the progress bar if it
2756 if (progbar != NULL)
2757 destroy_progress_dlg(progbar);
2760 if (new_fd != NULL) {
2761 /* We found a frame. Find what row it's in. */
2762 row = packet_list_find_row_from_data(new_fd);
2763 g_assert(row != -1);
2765 /* Select that row, make it the focus row, and make it visible. */
2766 packet_list_set_selected_row(row);
2767 return TRUE; /* success */
2769 return FALSE; /* failure */
2773 cf_goto_frame(capture_file *cf, guint fnumber)
2778 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2781 if (fdata == NULL) {
2782 /* we didn't find a packet with that packet number */
2783 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2784 "There is no packet with the packet number %u.", fnumber);
2785 return FALSE; /* we failed to go to that packet */
2787 if (!fdata->flags.passed_dfilter) {
2788 /* that packet currently isn't displayed */
2789 /* XXX - add it to the set of displayed packets? */
2790 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2791 "The packet number %u isn't currently being displayed.", fnumber);
2792 return FALSE; /* we failed to go to that packet */
2795 /* We found that packet, and it's currently being displayed.
2796 Find what row it's in. */
2797 row = packet_list_find_row_from_data(fdata);
2798 g_assert(row != -1);
2800 /* Select that row, make it the focus row, and make it visible. */
2801 packet_list_set_selected_row(row);
2802 return TRUE; /* we got to that packet */
2806 cf_goto_top_frame(capture_file *cf)
2810 frame_data *lowest_fdata = NULL;
2812 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2813 if (fdata->flags.passed_dfilter) {
2814 lowest_fdata = fdata;
2819 if (lowest_fdata == NULL) {
2823 /* We found that packet, and it's currently being displayed.
2824 Find what row it's in. */
2825 row = packet_list_find_row_from_data(lowest_fdata);
2826 g_assert(row != -1);
2828 /* Select that row, make it the focus row, and make it visible. */
2829 packet_list_set_selected_row(row);
2830 return TRUE; /* we got to that packet */
2834 cf_goto_bottom_frame(capture_file *cf)
2838 frame_data *highest_fdata = NULL;
2840 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2841 if (fdata->flags.passed_dfilter) {
2842 highest_fdata = fdata;
2846 if (highest_fdata == NULL) {
2850 /* We found that packet, and it's currently being displayed.
2851 Find what row it's in. */
2852 row = packet_list_find_row_from_data(highest_fdata);
2853 g_assert(row != -1);
2855 /* Select that row, make it the focus row, and make it visible. */
2856 packet_list_set_selected_row(row);
2857 return TRUE; /* we got to that packet */
2861 * Go to frame specified by currently selected protocol tree item.
2864 cf_goto_framenum(capture_file *cf)
2866 header_field_info *hfinfo;
2869 if (cf->finfo_selected) {
2870 hfinfo = cf->finfo_selected->hfinfo;
2872 if (hfinfo->type == FT_FRAMENUM) {
2873 framenum = fvalue_get_integer(&cf->finfo_selected->value);
2875 return cf_goto_frame(cf, framenum);
2882 /* Select the packet on a given row. */
2884 cf_select_packet(capture_file *cf, int row)
2890 /* Get the frame data struct pointer for this frame */
2891 fdata = (frame_data *)packet_list_get_row_data(row);
2893 if (fdata == NULL) {
2894 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
2895 the first entry is added to it by "real_insert_row()", that row
2896 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
2897 our version and the vanilla GTK+ version).
2899 This means that a "select-row" signal is emitted; this causes
2900 "packet_list_select_cb()" to be called, which causes "cf_select_packet()"
2903 "cf_select_packet()" fetches, above, the data associated with the
2904 row that was selected; however, as "gtk_clist_append()", which
2905 called "real_insert_row()", hasn't yet returned, we haven't yet
2906 associated any data with that row, so we get back a null pointer.
2908 We can't assume that there's only one frame in the frame list,
2909 either, as we may be filtering the display.
2911 We therefore assume that, if "row" is 0, i.e. the first row
2912 is being selected, and "cf->first_displayed" equals
2913 "cf->last_displayed", i.e. there's only one frame being
2914 displayed, that frame is the frame we want.
2916 This means we have to set "cf->first_displayed" and
2917 "cf->last_displayed" before adding the row to the
2918 GtkCList; see the comment in "add_packet_to_packet_list()". */
2920 if (row == 0 && cf->first_displayed == cf->last_displayed)
2921 fdata = cf->first_displayed;
2924 /* Get the data in that frame. */
2925 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
2926 cf->pd, fdata->cap_len, &err, &err_info)) {
2927 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2928 cf_read_error_message(err, err_info), cf->filename);
2932 /* Record that this frame is the current frame. */
2933 cf->current_frame = fdata;
2935 /* Create the logical protocol tree. */
2936 if (cf->edt != NULL) {
2937 epan_dissect_free(cf->edt);
2940 /* We don't need the columns here. */
2941 cf->edt = epan_dissect_new(TRUE, TRUE);
2942 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
2945 cf_callback_invoke(cf_cb_packet_selected, cf);
2948 /* Unselect the selected packet, if any. */
2950 cf_unselect_packet(capture_file *cf)
2952 /* Destroy the epan_dissect_t for the unselected packet. */
2953 if (cf->edt != NULL) {
2954 epan_dissect_free(cf->edt);
2958 /* No packet is selected. */
2959 cf->current_frame = NULL;
2961 cf_callback_invoke(cf_cb_packet_unselected, cf);
2963 /* No protocol tree means no selected field. */
2964 cf_unselect_field(cf);
2967 /* Unset the selected protocol tree field, if any. */
2969 cf_unselect_field(capture_file *cf)
2971 cf->finfo_selected = NULL;
2973 cf_callback_invoke(cf_cb_field_unselected, cf);
2977 * Mark a particular frame.
2980 cf_mark_frame(capture_file *cf, frame_data *frame)
2982 if (! frame->flags.marked) {
2983 frame->flags.marked = TRUE;
2984 if (cf->count > cf->marked_count)
2990 * Unmark a particular frame.
2993 cf_unmark_frame(capture_file *cf, frame_data *frame)
2995 if (frame->flags.marked) {
2996 frame->flags.marked = FALSE;
2997 if (cf->marked_count > 0)
3005 } save_callback_args_t;
3008 * Save a capture to a file, in a particular format, saving either
3009 * all packets, all currently-displayed packets, or all marked packets.
3011 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
3012 * up a message box for the failure.
3015 save_packet(capture_file *cf _U_, frame_data *fdata,
3016 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
3019 save_callback_args_t *args = argsp;
3020 struct wtap_pkthdr hdr;
3023 /* init the wtap header for saving */
3024 hdr.ts.tv_sec = fdata->abs_secs;
3025 hdr.ts.tv_usec = fdata->abs_usecs;
3026 hdr.caplen = fdata->cap_len;
3027 hdr.len = fdata->pkt_len;
3028 hdr.pkt_encap = fdata->lnk_t;
3030 /* and save the packet */
3031 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
3032 cf_write_failure_alert_box(args->fname, err);
3039 cf_save(capture_file *cf, const char *fname, packet_range_t *range, guint save_format)
3041 gchar *from_filename;
3045 save_callback_args_t callback_args;
3047 cf_callback_invoke(cf_cb_file_safe_started, (gpointer) fname);
3049 /* don't write over an existing file. */
3050 /* this should've been already checked by our caller, just to be sure... */
3051 if (file_exists(fname)) {
3052 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3053 "%sCapture file: \"%s\" already exists!%s\n\n"
3054 "Please choose a different filename.",
3055 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
3059 packet_range_process_init(range);
3062 * if (!save_filtered && !save_marked && !save_manual_range &&
3063 * !save_marked_range && !save_curr && save_format == cf->cd_t) {
3066 if (packet_range_process_all(range) && save_format == cf->cd_t) {
3067 /* We're not filtering packets, and we're saving it in the format
3068 it's already in, so we can just move or copy the raw data. */
3070 if (cf->is_tempfile) {
3071 /* The file being saved is a temporary file from a live
3072 capture, so it doesn't need to stay around under that name;
3073 first, try renaming the capture buffer file to the new name. */
3075 if (rename(cf->filename, fname) == 0) {
3076 /* That succeeded - there's no need to copy the source file. */
3077 from_filename = NULL;
3080 if (errno == EXDEV) {
3081 /* They're on different file systems, so we have to copy the
3084 from_filename = cf->filename;
3086 /* The rename failed, but not because they're on different
3087 file systems - put up an error message. (Or should we
3088 just punt and try to copy? The only reason why I'd
3089 expect the rename to fail and the copy to succeed would
3090 be if we didn't have permission to remove the file from
3091 the temporary directory, and that might be fixable - but
3092 is it worth requiring the user to go off and fix it?) */
3093 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3094 file_rename_error_message(errno), fname);
3100 from_filename = cf->filename;
3103 /* It's a permanent file, so we should copy it, and not remove the
3106 from_filename = cf->filename;
3110 /* Copy the file, if we haven't moved it. */
3111 if (!copy_binary_file(from_filename, fname))
3115 /* Either we're filtering packets, or we're saving in a different
3116 format; we can't do that by copying or moving the capture file,
3117 we have to do it by writing the packets out in Wiretap. */
3118 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
3120 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
3124 /* XXX - we let the user save a subset of the packets.
3126 If we do that, should we make that file the current file? If so,
3127 it means we can no longer get at the other packets. What does
3130 /* Iterate through the list of packets, processing the packets we were
3133 XXX - we've already called "packet_range_process_init(range)", but
3134 "process_specified_packets()" will do it again. Fortunately,
3135 that's harmless in this case, as we haven't done anything to
3136 "range" since we initialized it. */
3137 callback_args.pdh = pdh;
3138 callback_args.fname = fname;
3139 switch (process_specified_packets(cf, range, "Saving",
3140 "selected packets", save_packet,
3144 /* Completed successfully. */
3148 /* The user decided to abort the saving.
3149 XXX - remove the output file? */
3153 /* Error while saving. */
3154 wtap_dump_close(pdh, &err);
3158 if (!wtap_dump_close(pdh, &err)) {
3159 cf_close_failure_alert_box(fname, err);
3164 cf_callback_invoke(cf_cb_file_safe_finished, NULL);
3166 if (packet_range_process_all(range)) {
3167 /* We saved the entire capture, not just some packets from it.
3168 Open and read the file we saved it to.
3170 XXX - this is somewhat of a waste; we already have the
3171 packets, all this gets us is updated file type information
3172 (which we could just stuff into "cf"), and having the new
3173 file be the one we have opened and from which we're reading
3174 the data, and it means we have to spend time opening and
3175 reading the file, which could be a significant amount of
3176 time if the file is large. */
3177 cf->user_saved = TRUE;
3179 if ((cf_open(cf, fname, FALSE, &err)) == CF_OK) {
3180 /* XXX - report errors if this fails?
3181 What should we return if it fails or is aborted? */
3182 switch (cf_read(cf)) {
3186 /* Just because we got an error, that doesn't mean we were unable
3187 to read any of the file; we handle what we could get from the
3191 case CF_READ_ABORTED:
3192 /* The user bailed out of re-reading the capture file; the
3193 capture file has been closed - just return (without
3194 changing any menu settings; "cf_close()" set them
3195 correctly for the "no capture file open" state). */
3198 cf_callback_invoke(cf_cb_file_safe_reload_finished, NULL);
3204 cf_callback_invoke(cf_cb_file_safe_failed, NULL);
3209 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3210 gboolean for_writing, int file_type)
3213 /* Wiretap error. */
3216 case WTAP_ERR_NOT_REGULAR_FILE:
3217 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3218 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3222 case WTAP_ERR_RANDOM_OPEN_PIPE:
3223 /* Seen only when opening a capture file for reading. */
3224 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3225 "The file \"%s\" is a pipe or FIFO; Ethereal can't read pipe or FIFO files.",
3229 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3230 /* Seen only when opening a capture file for reading. */
3231 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3232 "The file \"%s\" isn't a capture file in a format Ethereal understands.",
3236 case WTAP_ERR_UNSUPPORTED:
3237 /* Seen only when opening a capture file for reading. */
3238 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3239 "The file \"%s\" isn't a capture file in a format Ethereal understands.\n"
3241 filename, err_info);
3245 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3246 /* Seen only when opening a capture file for writing. */
3247 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3248 "The file \"%s\" is a pipe, and %s capture files can't be "
3249 "written to a pipe.",
3250 filename, wtap_file_type_string(file_type));
3253 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3254 /* Seen only when opening a capture file for writing. */
3255 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3256 "Ethereal doesn't support writing capture files in that format.");
3259 case WTAP_ERR_UNSUPPORTED_ENCAP:
3261 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3262 "Ethereal can't save this capture in that format.");
3264 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3265 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.\n"
3267 filename, err_info);
3272 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3274 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3275 "Ethereal can't save this capture in that format.");
3277 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3278 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.",
3283 case WTAP_ERR_BAD_RECORD:
3284 /* Seen only when opening a capture file for reading. */
3285 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3286 "The file \"%s\" appears to be damaged or corrupt.\n"
3288 filename, err_info);
3292 case WTAP_ERR_CANT_OPEN:
3294 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3295 "The file \"%s\" could not be created for some unknown reason.",
3298 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3299 "The file \"%s\" could not be opened for some unknown reason.",
3304 case WTAP_ERR_SHORT_READ:
3305 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3306 "The file \"%s\" appears to have been cut short"
3307 " in the middle of a packet or other data.",
3311 case WTAP_ERR_SHORT_WRITE:
3312 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3313 "A full header couldn't be written to the file \"%s\".",
3318 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3319 "The file \"%s\" could not be %s: %s.",
3321 for_writing ? "created" : "opened",
3322 wtap_strerror(err));
3327 open_failure_alert_box(filename, err, for_writing);
3332 file_rename_error_message(int err)
3335 static char errmsg_errno[1024+1];
3340 errmsg = "The path to the file \"%s\" doesn't exist.";
3344 errmsg = "You don't have permission to move the capture file to \"%s\".";
3348 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3349 "The file \"%%s\" could not be moved: %s.",
3350 wtap_strerror(err));
3351 errmsg = errmsg_errno;
3358 cf_read_error_message(int err, const gchar *err_info)
3360 static char errmsg_errno[1024+1];
3364 case WTAP_ERR_UNSUPPORTED_ENCAP:
3365 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3366 "The file \"%%s\" has a packet with a network type that Ethereal doesn't support.\n(%s)",
3370 case WTAP_ERR_BAD_RECORD:
3371 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3372 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3373 wtap_strerror(err), err_info);
3377 g_snprintf(errmsg_errno, sizeof(errmsg_errno),
3378 "An error occurred while reading from the file \"%%s\": %s.",
3379 wtap_strerror(err));
3382 return errmsg_errno;
3386 cf_write_failure_alert_box(const char *filename, int err)
3389 /* Wiretap error. */
3390 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3391 "An error occurred while writing to the file \"%s\": %s.",
3392 filename, wtap_strerror(err));
3395 write_failure_alert_box(filename, err);
3399 /* Check for write errors - if the file is being written to an NFS server,
3400 a write error may not show up until the file is closed, as NFS clients
3401 might not send writes to the server until the "write()" call finishes,
3402 so that the write may fail on the server but the "write()" may succeed. */
3404 cf_close_failure_alert_box(const char *filename, int err)
3407 /* Wiretap error. */
3410 case WTAP_ERR_CANT_CLOSE:
3411 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3412 "The file \"%s\" couldn't be closed for some unknown reason.",
3416 case WTAP_ERR_SHORT_WRITE:
3417 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3418 "Not all the packets could be written to the file \"%s\".",
3423 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3424 "An error occurred while closing the file \"%s\": %s.",
3425 filename, wtap_strerror(err));
3430 We assume that a close error from the OS is really a write error. */
3431 write_failure_alert_box(filename, err);
3435 /* Reload the current capture file. */
3437 cf_reload(capture_file *cf) {
3439 gboolean is_tempfile;
3442 /* If the file could be opened, "cf_open()" calls "cf_close()"
3443 to get rid of state for the old capture file before filling in state
3444 for the new capture file. "cf_close()" will remove the file if
3445 it's a temporary file; we don't want that to happen (for one thing,
3446 it'd prevent subsequent reopens from working). Remember whether it's
3447 a temporary file, mark it as not being a temporary file, and then
3448 reopen it as the type of file it was.
3450 Also, "cf_close()" will free "cf->filename", so we must make
3451 a copy of it first. */
3452 filename = g_strdup(cf->filename);
3453 is_tempfile = cf->is_tempfile;
3454 cf->is_tempfile = FALSE;
3455 if (cf_open(cf, filename, is_tempfile, &err) == CF_OK) {
3456 switch (cf_read(cf)) {
3460 /* Just because we got an error, that doesn't mean we were unable
3461 to read any of the file; we handle what we could get from the
3465 case CF_READ_ABORTED:
3466 /* The user bailed out of re-reading the capture file; the
3467 capture file has been closed - just free the capture file name
3468 string and return (without changing the last containing
3474 /* The open failed, so "cf->is_tempfile" wasn't set to "is_tempfile".
3475 Instead, the file was left open, so we should restore "cf->is_tempfile"
3478 XXX - change the menu? Presumably "cf_open()" will do that;
3479 make sure it does! */
3480 cf->is_tempfile = is_tempfile;
3482 /* "cf_open()" made a copy of the file name we handed it, so
3483 we should free up our copy. */
3487 /* Copies a file in binary mode, for those operating systems that care about
3489 * Returns TRUE on success, FALSE on failure. If a failure, it also
3490 * displays a simple dialog window with the error message.
3493 copy_binary_file(const char *from_filename, const char *to_filename)
3495 int from_fd, to_fd, nread, nwritten, err;
3498 /* Copy the raw bytes of the file. */
3499 from_fd = open(from_filename, O_RDONLY | O_BINARY);
3501 open_failure_alert_box(from_filename, errno, FALSE);
3505 /* Use open() instead of creat() so that we can pass the O_BINARY
3506 flag, which is relevant on Win32; it appears that "creat()"
3507 may open the file in text mode, not binary mode, but we want
3508 to copy the raw bytes of the file, so we need the output file
3509 to be open in binary mode. */
3510 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3512 open_failure_alert_box(to_filename, errno, TRUE);
3517 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
3518 nwritten = write(to_fd, pd, nread);
3519 if (nwritten < nread) {
3523 err = WTAP_ERR_SHORT_WRITE;
3524 write_failure_alert_box(to_filename, err);
3532 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3533 "An error occurred while reading from the file \"%s\": %s.",
3534 from_filename, strerror(err));
3540 if (close(to_fd) < 0) {
3541 write_failure_alert_box(to_filename, errno);