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.
25 /* With MSVC and a libethereal.dll this file needs to import some variables
26 in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
27 #define _NEED_VAR_IMPORT_
50 #ifdef HAVE_SYS_STAT_H
58 #ifdef NEED_SNPRINTF_H
59 # include "snprintf.h"
62 #ifdef NEED_STRERROR_H
66 #include <epan/epan.h>
67 #include <epan/filesystem.h>
70 #include "color_filters.h"
71 #include <epan/column.h>
72 #include <epan/packet.h>
73 #include "packet-range.h"
78 #include "alert_box.h"
79 #include "simple_dialog.h"
80 #include "progress_dlg.h"
82 #include "statusbar.h"
83 #include <epan/prefs.h>
84 #include <epan/dfilter/dfilter.h>
85 #include <epan/conversation.h>
87 #include <epan/epan_dissect.h>
89 #include "tap_dfilter_dlg.h"
90 #include <epan/dissectors/packet-data.h>
92 /* Win32 needs the O_BINARY flag for open() */
98 gboolean auto_scroll_live;
101 static guint32 firstsec, firstusec;
102 static guint32 prevsec, prevusec;
103 static guint32 cum_bytes = 0;
105 static void read_packet(capture_file *cf, long offset);
107 static void rescan_packets(capture_file *cf, const char *action, const char *action_item,
108 gboolean refilter, gboolean redissect);
110 static gboolean match_protocol_tree(capture_file *cf, frame_data *fdata,
112 static void match_subtree_text(proto_node *node, gpointer data);
113 static gboolean match_summary_line(capture_file *cf, frame_data *fdata,
115 static gboolean match_ascii_and_unicode(capture_file *cf, frame_data *fdata,
117 static gboolean match_ascii(capture_file *cf, frame_data *fdata,
119 static gboolean match_unicode(capture_file *cf, frame_data *fdata,
121 static gboolean match_binary(capture_file *cf, frame_data *fdata,
123 static gboolean match_dfilter(capture_file *cf, frame_data *fdata,
125 static gboolean find_packet(capture_file *cf,
126 gboolean (*match_function)(capture_file *, frame_data *, void *),
129 static void cf_open_failure_alert_box(const char *filename, int err,
130 gchar *err_info, gboolean for_writing,
132 static char *file_rename_error_message(int err);
133 static void cf_write_failure_alert_box(const char *filename, int err);
134 static void cf_close_failure_alert_box(const char *filename, int err);
135 static gboolean copy_binary_file(char *from_filename, char *to_filename);
137 /* Update the progress bar this many times when reading a file. */
138 #define N_PROGBAR_UPDATES 100
140 /* Number of "frame_data" structures per memory chunk.
141 XXX - is this the right number? */
142 #define FRAME_DATA_CHUNK_SIZE 1024
146 cf_open(char *fname, gboolean is_tempfile, capture_file *cf)
154 wth = wtap_open_offline(fname, &err, &err_info, TRUE);
158 /* Find the size of the file. */
160 if (fstat(fd, &cf_stat) < 0) {
166 /* The open succeeded. Close whatever capture file we had open,
167 and fill in the information for this file. */
170 /* Initialize all data structures used for dissection. */
173 /* We're about to start reading the file. */
174 cf->state = FILE_READ_IN_PROGRESS;
178 cf->f_len = cf_stat.st_size;
180 /* Set the file name because we need it to set the follow stream filter.
181 XXX - is that still true? We need it for other reasons, though,
183 cf->filename = g_strdup(fname);
185 /* Indicate whether it's a permanent or temporary file. */
186 cf->is_tempfile = is_tempfile;
188 /* If it's a temporary capture buffer file, mark it as not saved. */
189 cf->user_saved = !is_tempfile;
191 cf->cd_t = wtap_file_type(cf->wth);
193 cf->displayed_count = 0;
194 cf->marked_count = 0;
195 cf->drops_known = FALSE;
199 cf->snap = wtap_snapshot_length(cf->wth);
201 /* Snapshot length not known. */
202 cf->has_snap = FALSE;
203 cf->snap = WTAP_MAX_PACKET_SIZE;
206 firstsec = 0, firstusec = 0;
207 prevsec = 0, prevusec = 0;
209 cf->plist_chunk = g_mem_chunk_new("frame_data_chunk",
211 FRAME_DATA_CHUNK_SIZE * sizeof(frame_data),
213 g_assert(cf->plist_chunk);
218 cf_open_failure_alert_box(fname, err, err_info, FALSE, 0);
222 /* Reset everything to a pristine state */
224 cf_close(capture_file *cf)
226 /* Die if we're in the middle of reading a file. */
227 g_assert(cf->state != FILE_READ_IN_PROGRESS);
229 /* Destroy all windows, which refer to the
230 capture file we're closing. */
231 destroy_cfile_wins();
237 /* We have no file open... */
238 if (cf->filename != NULL) {
239 /* If it's a temporary file, remove it. */
241 unlink(cf->filename);
242 g_free(cf->filename);
245 /* ...which means we have nothing to save. */
246 cf->user_saved = FALSE;
248 if (cf->plist_chunk != NULL) {
249 g_mem_chunk_destroy(cf->plist_chunk);
250 cf->plist_chunk = NULL;
252 if (cf->rfcode != NULL) {
253 dfilter_free(cf->rfcode);
257 cf->plist_end = NULL;
258 unselect_packet(cf); /* nothing to select */
259 cf->first_displayed = NULL;
260 cf->last_displayed = NULL;
262 /* No frame selected, no field in that frame selected. */
263 cf->current_frame = NULL;
264 cf->finfo_selected = NULL;
266 /* Clear the packet list. */
267 packet_list_freeze();
276 /* Clear any file-related status bar messages.
277 XXX - should be "clear *ALL* file-related status bar messages;
278 will there ever be more than one on the stack? */
279 statusbar_pop_file_msg();
281 /* Restore the standard title bar message. */
282 set_main_window_name("The Ethereal Network Analyzer");
284 /* Disable all menu items that make sense only if you have a capture. */
285 set_menus_for_capture_file(FALSE);
286 set_menus_for_unsaved_capture_file(FALSE);
287 set_menus_for_captured_packets(FALSE);
288 set_menus_for_selected_packet(cf);
289 set_menus_for_capture_in_progress(FALSE);
290 set_menus_for_selected_tree_row(cf);
292 reset_tap_listeners();
294 /* We have no file open. */
295 cf->state = FILE_CLOSED;
298 /* Set the file name in the status line, in the name for the main window,
299 and in the name for the main window's icon. */
301 set_display_filename(capture_file *cf)
305 static const gchar done_fmt_nodrops[] = " File: %s %s %02u:%02u:%02u";
306 static const gchar done_fmt_drops[] = " File: %s %s %02u:%02u:%02u Drops: %u";
308 gchar *win_name_fmt = "%s - Ethereal";
312 name_ptr = cf_get_display_name(cf);
314 if (!cf->is_tempfile) {
315 /* Add this filename to the list of recent files in the "Recent Files" submenu */
316 add_menu_recent_capture_file(cf->filename);
319 if (cf->f_len/1024/1024 > 10) {
320 size_str = g_strdup_printf("%ld MB", cf->f_len/1024/1024);
321 } else if (cf->f_len/1024 > 10) {
322 size_str = g_strdup_printf("%ld KB", cf->f_len/1024);
324 size_str = g_strdup_printf("%ld bytes", cf->f_len);
327 if (cf->drops_known) {
328 done_msg = g_strdup_printf(done_fmt_drops, name_ptr, size_str,
329 cf->esec/3600, cf->esec%3600/60, cf->esec%60, cf->drops);
331 done_msg = g_strdup_printf(done_fmt_nodrops, name_ptr, size_str,
332 cf->esec/3600, cf->esec%3600/60, cf->esec%60);
334 statusbar_push_file_msg(done_msg);
337 msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
338 win_name = g_malloc(msg_len);
339 snprintf(win_name, msg_len, win_name_fmt, name_ptr);
340 set_main_window_name(win_name);
345 cf_read(capture_file *cf)
349 gchar *name_ptr, *load_msg, *load_fmt = "%s";
351 char errmsg_errno[1024+1];
352 gchar err_str[2048+1];
354 progdlg_t *progbar = NULL;
357 * XXX - should be "off_t", but Wiretap would need more work to handle
358 * the full size of "off_t" on platforms where it's more than a "long"
366 gchar status_str[100];
367 int progbar_nextstep;
371 reset_tap_listeners();
372 tap_dfilter_dlg_update();
373 name_ptr = get_basename(cf->filename);
375 load_msg = g_strdup_printf(" Loading: %s", name_ptr);
376 statusbar_push_file_msg(load_msg);
379 load_msg = g_strdup_printf(load_fmt, name_ptr);
381 /* Update the progress bar when it gets to this value. */
382 progbar_nextstep = 0;
383 /* When we reach the value that triggers a progress bar update,
384 bump that value by this amount. */
385 progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
387 packet_list_freeze();
390 g_get_current_time(&start_time);
392 while ((wtap_read(cf->wth, &err, &err_info, &data_offset))) {
393 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
394 when we update it, we have to run the GTK+ main loop to get it
395 to repaint what's pending, and doing so may involve an "ioctl()"
396 to see if there's any pending input from an X server, and doing
397 that for every packet can be costly, especially on a big file. */
398 if (data_offset >= progbar_nextstep) {
399 file_pos = lseek(cf->filed, 0, SEEK_CUR);
400 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
401 if (prog_val > 1.0) {
402 /* The file probably grew while we were reading it.
403 Update "cf->f_len", and try again. */
404 fd = wtap_fd(cf->wth);
405 if (fstat(fd, &cf_stat) >= 0) {
406 cf->f_len = cf_stat.st_size;
407 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
409 /* If it's still > 1, either the "fstat()" failed (in which
410 case there's not much we can do about it), or the file
411 *shrank* (in which case there's not much we can do about
412 it); just clip the progress value at 1.0. */
416 if (progbar == NULL) {
417 /* Create the progress bar if necessary */
418 progbar = delayed_create_progress_dlg("Loading", load_msg,
419 &stop_flag, &start_time, prog_val);
423 if (progbar != NULL) {
424 g_snprintf(status_str, sizeof(status_str),
425 "%luKB of %luKB", file_pos / 1024, cf->f_len / 1024);
426 update_progress_dlg(progbar, prog_val, status_str);
428 progbar_nextstep += progbar_quantum;
432 /* Well, the user decided to abort the read. Destroy the progress
433 bar, close the capture file, and return READ_ABORTED so our caller
434 can do whatever is appropriate when that happens. */
435 destroy_progress_dlg(progbar);
436 cf->state = FILE_READ_ABORTED; /* so that we're allowed to close it */
437 packet_list_thaw(); /* undo our freeze */
439 return (READ_ABORTED);
441 read_packet(cf, data_offset);
444 /* We're done reading the file; destroy the progress bar if it was created. */
448 destroy_progress_dlg(progbar);
450 /* We're done reading sequentially through the file. */
451 cf->state = FILE_READ_DONE;
453 /* Close the sequential I/O side, to free up memory it requires. */
454 wtap_sequential_close(cf->wth);
456 /* Allow the protocol dissectors to free up memory that they
457 * don't need after the sequential run-through of the packets. */
458 postseq_cleanup_all_protocols();
460 /* Set the file encapsulation type now; we don't know what it is until
461 we've looked at all the packets, as we don't know until then whether
462 there's more than one type (and thus whether it's
463 WTAP_ENCAP_PER_PACKET). */
464 cf->lnk_t = wtap_file_encap(cf->wth);
466 cf->current_frame = cf->first_displayed;
469 statusbar_pop_file_msg();
470 set_display_filename(cf);
472 /* Enable menu items that make sense if you have a capture file you've
474 set_menus_for_capture_file(TRUE);
475 set_menus_for_unsaved_capture_file(!cf->user_saved);
477 /* Enable menu items that make sense if you have some captured packets. */
478 set_menus_for_captured_packets(TRUE);
480 /* If we have any displayed packets to select, select the first of those
481 packets by making the first row the selected row. */
482 if (cf->first_displayed != NULL)
483 packet_list_select_row(0);
486 /* Put up a message box noting that the read failed somewhere along
487 the line. Don't throw out the stuff we managed to read, though,
491 case WTAP_ERR_UNSUPPORTED_ENCAP:
492 snprintf(errmsg_errno, sizeof(errmsg_errno),
493 "The capture file has a packet with a network type that Ethereal doesn't support.\n(%s)",
495 errmsg = errmsg_errno;
498 case WTAP_ERR_CANT_READ:
499 errmsg = "An attempt to read from the file failed for"
500 " some unknown reason.";
503 case WTAP_ERR_SHORT_READ:
504 errmsg = "The capture file appears to have been cut short"
505 " in the middle of a packet.";
508 case WTAP_ERR_BAD_RECORD:
509 snprintf(errmsg_errno, sizeof(errmsg_errno),
510 "The capture file appears to be damaged or corrupt.\n(%s)",
512 errmsg = errmsg_errno;
516 snprintf(errmsg_errno, sizeof(errmsg_errno),
517 "An error occurred while reading the"
518 " capture file: %s.", wtap_strerror(err));
519 errmsg = errmsg_errno;
522 snprintf(err_str, sizeof err_str, errmsg);
523 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, err_str);
526 return (READ_SUCCESS);
531 cf_start_tail(char *fname, gboolean is_tempfile, capture_file *cf)
536 err = cf_open(fname, is_tempfile, cf);
538 /* Disable menu items that make no sense if you're currently running
540 set_menus_for_capture_in_progress(TRUE);
542 /* Enable menu items that make sense if you have some captured
543 packets (yes, I know, we don't have any *yet*). */
544 set_menus_for_captured_packets(TRUE);
546 capture_msg = g_strdup_printf(" %s: <live capture in progress>", cf->iface);
548 statusbar_push_file_msg(capture_msg);
556 cf_continue_tail(capture_file *cf, int to_read, int *err)
558 long data_offset = 0;
563 packet_list_freeze();
565 while (to_read != 0 && (wtap_read(cf->wth, err, &err_info, &data_offset))) {
566 if (cf->state == FILE_READ_ABORTED) {
567 /* Well, the user decided to exit Ethereal. Break out of the
568 loop, and let the code below (which is called even if there
569 aren't any packets left to read) exit. */
572 read_packet(cf, data_offset);
578 /* XXX - this cheats and looks inside the packet list to find the final
580 if (auto_scroll_live && cf->plist_end != NULL)
581 packet_list_moveto_end();
583 if (cf->state == FILE_READ_ABORTED) {
584 /* Well, the user decided to exit Ethereal. Return READ_ABORTED
585 so that our caller can kill off the capture child process;
586 this will cause an EOF on the pipe from the child, so
587 "cf_finish_tail()" will be called, and it will clean up
590 } else if (*err != 0) {
591 /* We got an error reading the capture file.
592 XXX - pop up a dialog box? */
595 return (READ_SUCCESS);
599 cf_finish_tail(capture_file *cf, int *err)
606 packet_list_freeze();
608 while ((wtap_read(cf->wth, err, &err_info, &data_offset))) {
609 if (cf->state == FILE_READ_ABORTED) {
610 /* Well, the user decided to abort the read. Break out of the
611 loop, and let the code below (which is called even if there
612 aren't any packets left to read) exit. */
615 read_packet(cf, data_offset);
618 if (cf->state == FILE_READ_ABORTED) {
619 /* Well, the user decided to abort the read. We're only called
620 when the child capture process closes the pipe to us (meaning
621 it's probably exited), so we can just close the capture
622 file; we return READ_ABORTED so our caller can do whatever
623 is appropriate when that happens. */
629 if (auto_scroll_live && cf->plist_end != NULL)
630 /* XXX - this cheats and looks inside the packet list to find the final
632 packet_list_moveto_end();
634 /* We're done reading sequentially through the file. */
635 cf->state = FILE_READ_DONE;
637 /* we have to update the f_len field */
638 /* Find the size of the file. */
639 fd = wtap_fd(cf->wth);
640 if (fstat(fd, &cf_stat) >= 0) {
641 cf->f_len = cf_stat.st_size;
644 /* We're done reading sequentially through the file; close the
645 sequential I/O side, to free up memory it requires. */
646 wtap_sequential_close(cf->wth);
648 /* Allow the protocol dissectors to free up memory that they
649 * don't need after the sequential run-through of the packets. */
650 postseq_cleanup_all_protocols();
652 /* Set the file encapsulation type now; we don't know what it is until
653 we've looked at all the packets, as we don't know until then whether
654 there's more than one type (and thus whether it's
655 WTAP_ENCAP_PER_PACKET). */
656 cf->lnk_t = wtap_file_encap(cf->wth);
658 /* Pop the "<live capture in progress>" message off the status bar. */
659 statusbar_pop_file_msg();
661 set_display_filename(cf);
663 /* Enable menu items that make sense if you're not currently running
665 set_menus_for_capture_in_progress(FALSE);
667 /* Enable menu items that make sense if you have a capture file
668 you've finished reading. */
669 set_menus_for_capture_file(TRUE);
670 set_menus_for_unsaved_capture_file(!cf->user_saved);
673 /* We got an error reading the capture file.
674 XXX - pop up a dialog box? */
677 return (READ_SUCCESS);
680 #endif /* HAVE_LIBPCAP */
683 cf_get_display_name(capture_file *cf)
687 /* Return a name to use in displays */
688 if (!cf->is_tempfile) {
689 /* Get the last component of the file name, and use that. */
691 displayname = get_basename(cf->filename);
693 /* Add this filename to the list of recent files in the "Recent Files" submenu */
694 add_menu_recent_capture_file(cf->filename);
696 displayname="(No file)";
699 /* The file we read is a temporary file from a live capture;
700 we don't mention its name. */
701 displayname = "(Untitled)";
707 color_filter_t *colorf;
709 } apply_color_filter_args;
712 * If no color filter has been applied, apply this one.
713 * (The "if no color filter has been applied" is to handle the case where
714 * more than one color filter matches the packet.)
717 apply_color_filter(gpointer filter_arg, gpointer argp)
719 color_filter_t *colorf = filter_arg;
720 apply_color_filter_args *args = argp;
722 if (colorf->c_colorfilter != NULL && args->colorf == NULL) {
723 if (dfilter_apply_edt(colorf->c_colorfilter, args->edt))
724 args->colorf = colorf;
729 add_packet_to_packet_list(frame_data *fdata, capture_file *cf,
730 union wtap_pseudo_header *pseudo_header, const guchar *buf,
733 apply_color_filter_args args;
735 gboolean create_proto_tree = FALSE;
738 /* just add some value here until we know if it is being displayed or not */
739 fdata->cum_bytes = cum_bytes + fdata->pkt_len;
741 /* We don't yet have a color filter to apply. */
744 /* If we don't have the time stamp of the first packet in the
745 capture, it's because this is the first packet. Save the time
746 stamp of this packet as the time stamp of the first packet. */
747 if (!firstsec && !firstusec) {
748 firstsec = fdata->abs_secs;
749 firstusec = fdata->abs_usecs;
751 /* if this frames is marked as a reference time frame, reset
752 firstsec and firstusec to this frame */
753 if(fdata->flags.ref_time){
754 firstsec = fdata->abs_secs;
755 firstusec = fdata->abs_usecs;
758 /* If we don't have the time stamp of the previous displayed packet,
759 it's because this is the first displayed packet. Save the time
760 stamp of this packet as the time stamp of the previous displayed
762 if (!prevsec && !prevusec) {
763 prevsec = fdata->abs_secs;
764 prevusec = fdata->abs_usecs;
767 /* Get the time elapsed between the first packet and this packet. */
768 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
769 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
771 /* If it's greater than the current elapsed time, set the elapsed time
772 to it (we check for "greater than" so as not to be confused by
773 time moving backwards). */
774 if ((gint32)cf->esec < fdata->rel_secs
775 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
776 cf->esec = fdata->rel_secs;
777 cf->eusec = fdata->rel_usecs;
780 /* Get the time elapsed between the previous displayed packet and
782 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
783 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
787 we have a display filter and are re-applying it;
789 we have a list of color filters;
791 we have tap listeners;
793 allocate a protocol tree root node, so that we'll construct
794 a protocol tree against which a filter expression can be
796 if ((cf->dfcode != NULL && refilter) || filter_list != NULL
797 || num_tap_filters != 0)
798 create_proto_tree = TRUE;
800 /* Dissect the frame. */
801 edt = epan_dissect_new(create_proto_tree, FALSE);
803 if (cf->dfcode != NULL && refilter) {
804 epan_dissect_prime_dfilter(edt, cf->dfcode);
807 filter_list_prime_edt(edt);
810 epan_dissect_run(edt, pseudo_header, buf, fdata, &cf->cinfo);
811 tap_push_tapped_queue(edt);
813 /* If we have a display filter, apply it if we're refiltering, otherwise
814 leave the "passed_dfilter" flag alone.
816 If we don't have a display filter, set "passed_dfilter" to 1. */
817 if (cf->dfcode != NULL) {
819 if (cf->dfcode != NULL)
820 fdata->flags.passed_dfilter = dfilter_apply_edt(cf->dfcode, edt) ? 1 : 0;
822 fdata->flags.passed_dfilter = 1;
825 fdata->flags.passed_dfilter = 1;
827 /* If we have color filters, and the frame is to be displayed, apply
828 the color filters. */
829 if (fdata->flags.passed_dfilter) {
830 if (filter_list != NULL) {
832 g_slist_foreach(filter_list, apply_color_filter, &args);
837 if( (fdata->flags.passed_dfilter)
838 || (edt->pi.fd->flags.ref_time) ){
839 /* This frame either passed the display filter list or is marked as
840 a time reference frame. All time reference frames are displayed
841 even if they dont pass the display filter */
842 /* if this was a TIME REF frame we should reset the cul bytes field */
843 if(edt->pi.fd->flags.ref_time){
844 cum_bytes = fdata->pkt_len;
845 fdata->cum_bytes = cum_bytes;
848 /* increase cum_bytes with this packets length */
849 cum_bytes += fdata->pkt_len;
851 epan_dissect_fill_in_columns(edt);
853 /* If we haven't yet seen the first frame, this is it.
855 XXX - we must do this before we add the row to the display,
856 as, if the display's GtkCList's selection mode is
857 GTK_SELECTION_BROWSE, when the first entry is added to it,
858 "select_packet()" will be called, and it will fetch the row
859 data for the 0th row, and will get a null pointer rather than
860 "fdata", as "gtk_clist_append()" won't yet have returned and
861 thus "gtk_clist_set_row_data()" won't yet have been called.
863 We thus need to leave behind bread crumbs so that
864 "select_packet()" can find this frame. See the comment
865 in "select_packet()". */
866 if (cf->first_displayed == NULL)
867 cf->first_displayed = fdata;
869 /* This is the last frame we've seen so far. */
870 cf->last_displayed = fdata;
872 row = packet_list_append(cf->cinfo.col_data, fdata);
874 /* If the packet matches a color filter,
875 * store matching color_filter_t object in frame data. */
876 if (filter_list != NULL && (args.colorf != NULL)) {
877 /* add the matching colorfilter to the frame data */
878 fdata->color_filter = args.colorf;
879 /* If packet is marked, use colors from preferences */
880 if (fdata->flags.marked) {
881 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
882 } else /* if (filter_list != NULL && (args.colorf != NULL)) */ {
883 packet_list_set_colors(row, &(args.colorf->fg_color),
884 &(args.colorf->bg_color));
887 /* No color filter match */
888 fdata->color_filter = NULL;
889 if (fdata->flags.marked) {
890 packet_list_set_colors(row, &prefs.gui_marked_fg, &prefs.gui_marked_bg);
894 /* Set the time of the previous displayed frame to the time of this
896 prevsec = fdata->abs_secs;
897 prevusec = fdata->abs_usecs;
899 cf->displayed_count++;
901 /* This frame didn't pass the display filter, so it's not being added
902 to the clist, and thus has no row. */
905 epan_dissect_free(edt);
910 read_packet(capture_file *cf, long offset)
912 const struct wtap_pkthdr *phdr = wtap_phdr(cf->wth);
913 union wtap_pseudo_header *pseudo_header = wtap_pseudoheader(cf->wth);
914 const guchar *buf = wtap_buf_ptr(cf->wth);
917 frame_data *plist_end;
920 /* Allocate the next list entry, and add it to the list. */
921 fdata = g_mem_chunk_alloc(cf->plist_chunk);
926 fdata->pkt_len = phdr->len;
927 fdata->cap_len = phdr->caplen;
928 fdata->file_off = offset;
929 fdata->lnk_t = phdr->pkt_encap;
930 fdata->abs_secs = phdr->ts.tv_sec;
931 fdata->abs_usecs = phdr->ts.tv_usec;
932 fdata->flags.encoding = CHAR_ASCII;
933 fdata->flags.visited = 0;
934 fdata->flags.marked = 0;
935 fdata->flags.ref_time = 0;
939 edt = epan_dissect_new(TRUE, FALSE);
940 epan_dissect_prime_dfilter(edt, cf->rfcode);
941 epan_dissect_run(edt, pseudo_header, buf, fdata, NULL);
942 passed = dfilter_apply_edt(cf->rfcode, edt);
943 epan_dissect_free(edt);
946 plist_end = cf->plist_end;
947 fdata->prev = plist_end;
948 if (plist_end != NULL)
949 plist_end->next = fdata;
952 cf->plist_end = fdata;
955 fdata->num = cf->count;
956 add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE);
958 /* XXX - if we didn't have read filters, or if we could avoid
959 allocating the "frame_data" structure until we knew whether
960 the frame passed the read filter, we could use a G_ALLOC_ONLY
963 ...but, at least in one test I did, where I just made the chunk
964 a G_ALLOC_ONLY chunk and read in a huge capture file, it didn't
965 seem to save a noticeable amount of time or space. */
966 g_mem_chunk_free(cf->plist_chunk, fdata);
971 filter_packets(capture_file *cf, gchar *dftext, gboolean force)
974 char *filter_new = dftext ? dftext : "";
975 char *filter_old = cf->dfilter ? cf->dfilter : "";
977 /* if new filter equals old one, do nothing unless told to do so */
978 if (!force && strcmp(filter_new, filter_old) == 0) {
982 if (dftext == NULL) {
983 /* The new filter is an empty filter (i.e., display all packets). */
987 * We have a filter; make a copy of it (as we'll be saving it),
988 * and try to compile it.
990 dftext = g_strdup(dftext);
991 if (!dfilter_compile(dftext, &dfcode)) {
992 /* The attempt failed; report an error. */
993 gchar *safe_dftext = simple_dialog_format_message(dftext);
994 gchar *safe_dfilter_error_msg = simple_dialog_format_message(
996 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
999 "The following display filter is not a valid display filter:\n%s\n"
1000 "See the help for a description of the display filter syntax.",
1001 simple_dialog_primary_start(), safe_dfilter_error_msg,
1002 simple_dialog_primary_end(), safe_dftext);
1003 g_free(safe_dfilter_error_msg);
1004 g_free(safe_dftext);
1010 if (dfcode == NULL) {
1011 /* Yes - free the filter text, and set it to null. */
1017 /* We have a valid filter. Replace the current filter. */
1018 if (cf->dfilter != NULL)
1019 g_free(cf->dfilter);
1020 cf->dfilter = dftext;
1021 if (cf->dfcode != NULL)
1022 dfilter_free(cf->dfcode);
1023 cf->dfcode = dfcode;
1025 /* Now rescan the packet list, applying the new filter, but not
1026 throwing away information constructed on a previous pass. */
1027 if (dftext == NULL) {
1028 rescan_packets(cf, "Resetting", "Filter", TRUE, FALSE);
1030 rescan_packets(cf, "Filtering", dftext, TRUE, FALSE);
1036 colorize_packets(capture_file *cf)
1038 rescan_packets(cf, "Colorizing", "all packets", FALSE, FALSE);
1042 reftime_packets(capture_file *cf)
1044 rescan_packets(cf, "Updating Reftime", "all packets", FALSE, FALSE);
1048 redissect_packets(capture_file *cf)
1050 rescan_packets(cf, "Reprocessing", "all packets", TRUE, TRUE);
1053 /* Rescan the list of packets, reconstructing the CList.
1055 "action" describes why we're doing this; it's used in the progress
1058 "action_item" describes what we're doing; it's used in the progress
1061 "refilter" is TRUE if we need to re-evaluate the filter expression.
1063 "redissect" is TRUE if we need to make the dissectors reconstruct
1064 any state information they have (because a preference that affects
1065 some dissector has changed, meaning some dissector might construct
1066 its state differently from the way it was constructed the last time). */
1068 rescan_packets(capture_file *cf, const char *action, const char *action_item,
1069 gboolean refilter, gboolean redissect)
1072 progdlg_t *progbar = NULL;
1077 frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame;
1078 int selected_row, prev_row, preceding_row, following_row;
1079 gboolean selected_frame_seen;
1082 GTimeVal start_time;
1083 gchar status_str[100];
1084 int progbar_nextstep;
1085 int progbar_quantum;
1088 reset_tap_listeners();
1089 /* Which frame, if any, is the currently selected frame?
1090 XXX - should the selected frame or the focus frame be the "current"
1091 frame, that frame being the one from which "Find Frame" searches
1093 selected_frame = cf->current_frame;
1095 /* We don't yet know what row that frame will be on, if any, after we
1096 rebuild the clist, however. */
1100 /* We need to re-initialize all the state information that protocols
1101 keep, because some preference that controls a dissector has changed,
1102 which might cause the state information to be constructed differently
1103 by that dissector. */
1105 /* Initialize all data structures used for dissection. */
1109 /* Freeze the packet list while we redo it, so we don't get any
1110 screen updates while it happens. */
1111 packet_list_freeze();
1114 packet_list_clear();
1116 /* We don't yet know which will be the first and last frames displayed. */
1117 cf->first_displayed = NULL;
1118 cf->last_displayed = NULL;
1120 /* We currently don't display any packets */
1121 cf->displayed_count = 0;
1123 /* Iterate through the list of frames. Call a routine for each frame
1124 to check whether it should be displayed and, if so, add it to
1125 the display list. */
1131 /* Update the progress bar when it gets to this value. */
1132 progbar_nextstep = 0;
1133 /* When we reach the value that triggers a progress bar update,
1134 bump that value by this amount. */
1135 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1136 /* Count of packets at which we've looked. */
1140 g_get_current_time(&start_time);
1142 row = -1; /* no previous row yet */
1147 preceding_frame = NULL;
1149 following_frame = NULL;
1151 selected_frame_seen = FALSE;
1153 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1154 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1155 when we update it, we have to run the GTK+ main loop to get it
1156 to repaint what's pending, and doing so may involve an "ioctl()"
1157 to see if there's any pending input from an X server, and doing
1158 that for every packet can be costly, especially on a big file. */
1159 if (count >= progbar_nextstep) {
1160 /* let's not divide by zero. I should never be started
1161 * with count == 0, so let's assert that
1163 g_assert(cf->count > 0);
1164 prog_val = (gfloat) count / cf->count;
1166 if (progbar == NULL)
1167 /* Create the progress bar if necessary */
1168 progbar = delayed_create_progress_dlg(action, action_item, &stop_flag,
1169 &start_time, prog_val);
1171 if (progbar != NULL) {
1172 g_snprintf(status_str, sizeof(status_str),
1173 "%4u of %u frames", count, cf->count);
1174 update_progress_dlg(progbar, prog_val, status_str);
1177 progbar_nextstep += progbar_quantum;
1181 /* Well, the user decided to abort the filtering. Just stop.
1183 XXX - go back to the previous filter? Users probably just
1184 want not to wait for a filtering operation to finish;
1185 unless we cancel by having no filter, reverting to the
1186 previous filter will probably be even more expensive than
1187 continuing the filtering, as it involves going back to the
1188 beginning and filtering, and even with no filter we currently
1189 have to re-generate the entire clist, which is also expensive.
1191 I'm not sure what Network Monitor does, but it doesn't appear
1192 to give you an unfiltered display if you cancel. */
1199 /* Since all state for the frame was destroyed, mark the frame
1200 * as not visited, free the GSList referring to the state
1201 * data (the per-frame data itself was freed by
1202 * "init_dissection()"), and null out the GSList pointer. */
1203 fdata->flags.visited = 0;
1205 g_slist_free(fdata->pfd);
1210 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
1211 cf->pd, fdata->cap_len, &err, &err_info)) {
1212 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1213 cf_read_error_message(err, err_info), cf->filename);
1217 /* If the previous frame is displayed, and we haven't yet seen the
1218 selected frame, remember that frame - it's the closest one we've
1219 yet seen before the selected frame. */
1220 if (prev_row != -1 && !selected_frame_seen) {
1221 preceding_row = prev_row;
1222 preceding_frame = prev_frame;
1224 row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd,
1227 /* If this frame is displayed, and this is the first frame we've
1228 seen displayed after the selected frame, remember this frame -
1229 it's the closest one we've yet seen at or after the selected
1231 if (row != -1 && selected_frame_seen && following_row == -1) {
1232 following_row = row;
1233 following_frame = fdata;
1235 if (fdata == selected_frame) {
1237 selected_frame_seen = TRUE;
1240 /* Remember this row/frame - it'll be the previous row/frame
1241 on the next pass through the loop. */
1247 /* Clear out what remains of the visited flags and per-frame data
1250 XXX - that may cause various forms of bogosity when dissecting
1251 these frames, as they won't have been seen by this sequential
1252 pass, but the only alternative I see is to keep scanning them
1253 even though the user requested that the scan stop, and that
1254 would leave the user stuck with an Ethereal grinding on
1255 until it finishes. Should we just stick them with that? */
1256 for (; fdata != NULL; fdata = fdata->next) {
1257 fdata->flags.visited = 0;
1259 g_slist_free(fdata->pfd);
1265 /* We're done filtering the packets; destroy the progress bar if it
1267 if (progbar != NULL)
1268 destroy_progress_dlg(progbar);
1270 /* Unfreeze the packet list. */
1273 if (selected_row == -1) {
1274 /* The selected frame didn't pass the filter. */
1275 if (selected_frame == NULL) {
1276 /* That's because there *was* no selected frame. Make the first
1277 displayed frame the current frame. */
1280 /* Find the nearest displayed frame to the selected frame (whether
1281 it's before or after that frame) and make that the current frame.
1282 If the next and previous displayed frames are equidistant from the
1283 selected frame, choose the next one. */
1284 g_assert(following_frame == NULL ||
1285 following_frame->num >= selected_frame->num);
1286 g_assert(preceding_frame == NULL ||
1287 preceding_frame->num <= selected_frame->num);
1288 if (following_frame == NULL) {
1289 /* No frame after the selected frame passed the filter, so we
1290 have to select the last displayed frame before the selected
1292 selected_row = preceding_row;
1293 } else if (preceding_frame == NULL) {
1294 /* No frame before the selected frame passed the filter, so we
1295 have to select the first displayed frame after the selected
1297 selected_row = following_row;
1299 /* Choose the closer of the last displayed frame before the
1300 selected frame and the first displayed frame after the
1301 selected frame; in case of a tie, choose the first displayed
1302 frame after the selected frame. */
1303 if (following_frame->num - selected_frame->num <=
1304 selected_frame->num - preceding_frame->num) {
1305 selected_row = following_row;
1307 /* The previous frame is closer to the selected frame than the
1309 selected_row = preceding_row;
1315 if (selected_row == -1) {
1316 /* There are no frames displayed at all. */
1317 unselect_packet(cf);
1319 /* Either the frame that was selected passed the filter, or we've
1320 found the nearest displayed frame to that frame. Select it, make
1321 it the focus row, and make it visible. */
1322 packet_list_set_selected_row(selected_row);
1333 process_specified_packets(capture_file *cf, packet_range_t *range,
1334 const char *string1, const char *string2,
1335 gboolean (*callback)(capture_file *, frame_data *,
1336 union wtap_pseudo_header *, const guint8 *, void *),
1337 void *callback_args)
1342 union wtap_pseudo_header pseudo_header;
1343 guint8 pd[WTAP_MAX_PACKET_SIZE+1];
1344 psp_return_t ret = PSP_FINISHED;
1346 progdlg_t *progbar = NULL;
1349 gboolean progbar_stop_flag;
1350 GTimeVal progbar_start_time;
1351 gchar progbar_status_str[100];
1352 int progbar_nextstep;
1353 int progbar_quantum;
1354 range_process_e process_this;
1356 /* Update the progress bar when it gets to this value. */
1357 progbar_nextstep = 0;
1358 /* When we reach the value that triggers a progress bar update,
1359 bump that value by this amount. */
1360 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1361 /* Count of packets at which we've looked. */
1364 progbar_stop_flag = FALSE;
1365 g_get_current_time(&progbar_start_time);
1367 packet_range_process_init(range);
1369 /* Iterate through the list of packets, printing the packets that
1370 were selected by the current display filter. */
1371 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
1372 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1373 when we update it, we have to run the GTK+ main loop to get it
1374 to repaint what's pending, and doing so may involve an "ioctl()"
1375 to see if there's any pending input from an X server, and doing
1376 that for every packet can be costly, especially on a big file. */
1377 if (progbar_count >= progbar_nextstep) {
1378 /* let's not divide by zero. I should never be started
1379 * with count == 0, so let's assert that
1381 g_assert(cf->count > 0);
1382 progbar_val = (gfloat) progbar_count / cf->count;
1384 if (progbar == NULL)
1385 /* Create the progress bar if necessary */
1386 progbar = delayed_create_progress_dlg(string1, string2,
1388 &progbar_start_time,
1391 if (progbar != NULL) {
1392 g_snprintf(progbar_status_str, sizeof(progbar_status_str),
1393 "%4u of %u packets", progbar_count, cf->count);
1394 update_progress_dlg(progbar, progbar_val, progbar_status_str);
1397 progbar_nextstep += progbar_quantum;
1400 if (progbar_stop_flag) {
1401 /* Well, the user decided to abort the operation. Just stop,
1402 and arrange to return TRUE to our caller, so they know it
1403 was stopped explicitly. */
1410 /* do we have to process this packet? */
1411 process_this = packet_range_process_packet(range, fdata);
1412 if (process_this == range_process_next) {
1413 /* this packet uninteresting, continue with next one */
1415 } else if (process_this == range_processing_finished) {
1416 /* all interesting packets processed, stop the loop */
1420 /* Get the packet */
1421 if (!wtap_seek_read(cf->wth, fdata->file_off, &pseudo_header,
1422 pd, fdata->cap_len, &err, &err_info)) {
1423 /* Attempt to get the packet failed. */
1424 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1425 cf_read_error_message(err, err_info), cf->filename);
1429 /* Process the packet */
1430 if (!callback(cf, fdata, &pseudo_header, pd, callback_args)) {
1431 /* Callback failed. We assume it reported the error appropriately. */
1437 /* We're done printing the packets; destroy the progress bar if
1439 if (progbar != NULL)
1440 destroy_progress_dlg(progbar);
1446 retap_packet(capture_file *cf _U_, frame_data *fdata,
1447 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1450 epan_dissect_t *edt;
1452 /* If we have tap listeners, allocate a protocol tree root node, so that
1453 we'll construct a protocol tree against which a filter expression can
1455 edt = epan_dissect_new(num_tap_filters != 0, FALSE);
1456 tap_queue_init(edt);
1457 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1458 tap_push_tapped_queue(edt);
1459 epan_dissect_free(edt);
1465 retap_packets(capture_file *cf)
1467 packet_range_t range;
1469 /* Reset the tap listeners. */
1470 reset_tap_listeners();
1472 /* Iterate through the list of packets, dissecting all packets and
1473 re-running the taps. */
1474 packet_range_init(&range);
1475 packet_range_process_init(&range);
1476 switch (process_specified_packets(cf, &range, "Refiltering statistics on",
1477 "all packets", retap_packet,
1480 /* Completed successfully. */
1484 /* Well, the user decided to abort the refiltering.
1485 Return FALSE so our caller knows they did that. */
1489 /* Error while retapping. */
1497 print_args_t *print_args;
1498 gboolean print_header_line;
1499 char *header_line_buf;
1500 int header_line_buf_len;
1501 gboolean print_formfeed;
1502 gboolean print_separator;
1506 } print_callback_args_t;
1509 print_packet(capture_file *cf, frame_data *fdata,
1510 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1513 print_callback_args_t *args = argsp;
1514 epan_dissect_t *edt;
1520 gboolean proto_tree_needed;
1521 char bookmark_name[9+10+1]; /* "__frameNNNNNNNNNN__\0" */
1522 char bookmark_title[6+10+1]; /* "Frame NNNNNNNNNN__\0" */
1524 /* Create the protocol tree, and make it visible, if we're printing
1525 the dissection or the hex data.
1526 XXX - do we need it if we're just printing the hex data? */
1528 args->print_args->print_dissections != print_dissections_none || args->print_args->print_hex;
1529 edt = epan_dissect_new(proto_tree_needed, proto_tree_needed);
1531 /* Fill in the column information if we're printing the summary
1533 if (args->print_args->print_summary) {
1534 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1535 epan_dissect_fill_in_columns(edt);
1537 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1539 if (args->print_formfeed) {
1540 if (!new_page(args->print_args->stream))
1543 if (args->print_separator) {
1544 if (!print_line(args->print_args->stream, 0, ""))
1550 * We generate bookmarks, if the output format supports them.
1551 * The name is "__frameN__".
1553 sprintf(bookmark_name, "__frame%u__", fdata->num);
1555 if (args->print_args->print_summary) {
1556 if (args->print_header_line) {
1557 if (!print_line(args->print_args->stream, 0, args->header_line_buf))
1559 args->print_header_line = FALSE; /* we might not need to print any more */
1561 cp = &args->line_buf[0];
1563 for (i = 0; i < cf->cinfo.num_cols; i++) {
1564 /* Find the length of the string for this column. */
1565 column_len = strlen(cf->cinfo.col_data[i]);
1566 if (args->col_widths[i] > column_len)
1567 column_len = args->col_widths[i];
1569 /* Make sure there's room in the line buffer for the column; if not,
1570 double its length. */
1571 line_len += column_len + 1; /* "+1" for space */
1572 if (line_len > args->line_buf_len) {
1573 cp_off = cp - args->line_buf;
1574 args->line_buf_len = 2 * line_len;
1575 args->line_buf = g_realloc(args->line_buf, args->line_buf_len + 1);
1576 cp = args->line_buf + cp_off;
1579 /* Right-justify the packet number column. */
1580 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1581 sprintf(cp, "%*s", args->col_widths[i], cf->cinfo.col_data[i]);
1583 sprintf(cp, "%-*s", args->col_widths[i], cf->cinfo.col_data[i]);
1585 if (i != cf->cinfo.num_cols - 1)
1591 * Generate a bookmark, using the summary line as the title.
1593 if (!print_bookmark(args->print_args->stream, bookmark_name,
1597 if (!print_line(args->print_args->stream, 0, args->line_buf))
1601 * Generate a bookmark, using "Frame N" as the title, as we're not
1602 * printing the summary line.
1604 sprintf(bookmark_title, "Frame %u", fdata->num);
1605 if (!print_bookmark(args->print_args->stream, bookmark_name,
1608 } /* if (print_summary) */
1610 if (args->print_args->print_dissections != print_dissections_none) {
1611 if (args->print_args->print_summary) {
1612 /* Separate the summary line from the tree with a blank line. */
1613 if (!print_line(args->print_args->stream, 0, ""))
1617 /* Print the information in that tree. */
1618 if (!proto_tree_print(args->print_args, edt, args->print_args->stream))
1621 /* Print a blank line if we print anything after this (aka more than one packet). */
1622 args->print_separator = TRUE;
1624 /* Print a header line if we print any more packet summaries */
1625 args->print_header_line = TRUE;
1628 if (args->print_args->print_hex) {
1629 /* Print the full packet data as hex. */
1630 if (!print_hex_data(args->print_args->stream, edt))
1633 /* Print a blank line if we print anything after this (aka more than one packet). */
1634 args->print_separator = TRUE;
1636 /* Print a header line if we print any more packet summaries */
1637 args->print_header_line = TRUE;
1638 } /* if (args->print_args->print_dissections != print_dissections_none) */
1640 epan_dissect_free(edt);
1642 /* do we want to have a formfeed between each packet from now on? */
1643 if(args->print_args->print_formfeed) {
1644 args->print_formfeed = TRUE;
1650 epan_dissect_free(edt);
1655 print_packets(capture_file *cf, print_args_t *print_args)
1658 print_callback_args_t callback_args;
1666 callback_args.print_args = print_args;
1667 callback_args.print_header_line = TRUE;
1668 callback_args.header_line_buf = NULL;
1669 callback_args.header_line_buf_len = 256;
1670 callback_args.print_formfeed = FALSE;
1671 callback_args.print_separator = FALSE;
1672 callback_args.line_buf = NULL;
1673 callback_args.line_buf_len = 256;
1674 callback_args.col_widths = NULL;
1676 if (!print_preamble(print_args->stream, cf->filename)) {
1677 destroy_print_stream(print_args->stream);
1678 return PP_WRITE_ERROR;
1681 if (print_args->print_summary) {
1682 /* We're printing packet summaries. Allocate the header line buffer
1683 and get the column widths. */
1684 callback_args.header_line_buf = g_malloc(callback_args.header_line_buf_len + 1);
1686 /* Find the widths for each of the columns - maximum of the
1687 width of the title and the width of the data - and construct
1688 a buffer with a line containing the column titles. */
1689 callback_args.col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1690 cp = &callback_args.header_line_buf[0];
1692 for (i = 0; i < cf->cinfo.num_cols; i++) {
1693 /* Don't pad the last column. */
1694 if (i == cf->cinfo.num_cols - 1)
1695 callback_args.col_widths[i] = 0;
1697 callback_args.col_widths[i] = strlen(cf->cinfo.col_title[i]);
1698 data_width = get_column_char_width(get_column_format(i));
1699 if (data_width > callback_args.col_widths[i])
1700 callback_args.col_widths[i] = data_width;
1703 /* Find the length of the string for this column. */
1704 column_len = strlen(cf->cinfo.col_title[i]);
1705 if (callback_args.col_widths[i] > column_len)
1706 column_len = callback_args.col_widths[i];
1708 /* Make sure there's room in the line buffer for the column; if not,
1709 double its length. */
1710 line_len += column_len + 1; /* "+1" for space */
1711 if (line_len > callback_args.header_line_buf_len) {
1712 cp_off = cp - callback_args.header_line_buf;
1713 callback_args.header_line_buf_len = 2 * line_len;
1714 callback_args.header_line_buf = g_realloc(callback_args.header_line_buf,
1715 callback_args.header_line_buf_len + 1);
1716 cp = callback_args.header_line_buf + cp_off;
1719 /* Right-justify the packet number column. */
1720 /* if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1721 sprintf(cp, "%*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1723 sprintf(cp, "%-*s", callback_args.col_widths[i], cf->cinfo.col_title[i]);
1725 if (i != cf->cinfo.num_cols - 1)
1730 /* Now start out the main line buffer with the same length as the
1731 header line buffer. */
1732 callback_args.line_buf_len = callback_args.header_line_buf_len;
1733 callback_args.line_buf = g_malloc(callback_args.line_buf_len + 1);
1734 } /* if (print_summary) */
1736 /* Iterate through the list of packets, printing the packets we were
1738 ret = process_specified_packets(cf, &print_args->range, "Printing",
1739 "selected packets", print_packet,
1742 if (callback_args.header_line_buf != NULL)
1743 g_free(callback_args.header_line_buf);
1744 if (callback_args.line_buf != NULL)
1745 g_free(callback_args.line_buf);
1746 if (callback_args.col_widths != NULL)
1747 g_free(callback_args.col_widths);
1752 /* Completed successfully. */
1756 /* Well, the user decided to abort the printing.
1758 XXX - note that what got generated before they did that
1759 will get printed if we're piping to a print program; we'd
1760 have to write to a file and then hand that to the print
1761 program to make it actually not print anything. */
1765 /* Error while printing.
1767 XXX - note that what got generated before they did that
1768 will get printed if we're piping to a print program; we'd
1769 have to write to a file and then hand that to the print
1770 program to make it actually not print anything. */
1771 destroy_print_stream(print_args->stream);
1772 return PP_WRITE_ERROR;
1775 if (!print_finale(print_args->stream)) {
1776 destroy_print_stream(print_args->stream);
1777 return PP_WRITE_ERROR;
1780 if (!destroy_print_stream(print_args->stream))
1781 return PP_WRITE_ERROR;
1787 write_pdml_packet(capture_file *cf _U_, frame_data *fdata,
1788 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1792 epan_dissect_t *edt;
1794 /* Create the protocol tree, but don't fill in the column information. */
1795 edt = epan_dissect_new(TRUE, TRUE);
1796 epan_dissect_run(edt, pseudo_header, pd, fdata, NULL);
1798 /* Write out the information in that tree. */
1799 proto_tree_write_pdml(edt, fh);
1801 epan_dissect_free(edt);
1807 write_pdml_packets(capture_file *cf, print_args_t *print_args)
1812 fh = fopen(print_args->file, "w");
1814 return PP_OPEN_ERROR; /* attempt to open destination failed */
1816 write_pdml_preamble(fh);
1819 return PP_WRITE_ERROR;
1822 /* Iterate through the list of packets, printing the packets we were
1824 ret = process_specified_packets(cf, &print_args->range, "Writing PDML",
1825 "selected packets", write_pdml_packet,
1831 /* Completed successfully. */
1835 /* Well, the user decided to abort the printing. */
1839 /* Error while printing. */
1841 return PP_WRITE_ERROR;
1844 write_pdml_finale(fh);
1847 return PP_WRITE_ERROR;
1850 /* XXX - check for an error */
1857 write_psml_packet(capture_file *cf, frame_data *fdata,
1858 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
1862 epan_dissect_t *edt;
1864 /* Fill in the column information, but don't create the protocol tree. */
1865 edt = epan_dissect_new(FALSE, FALSE);
1866 epan_dissect_run(edt, pseudo_header, pd, fdata, &cf->cinfo);
1868 /* Write out the information in that tree. */
1869 proto_tree_write_psml(edt, fh);
1871 epan_dissect_free(edt);
1877 write_psml_packets(capture_file *cf, print_args_t *print_args)
1882 fh = fopen(print_args->file, "w");
1884 return PP_OPEN_ERROR; /* attempt to open destination failed */
1886 write_psml_preamble(fh);
1889 return PP_WRITE_ERROR;
1892 /* Iterate through the list of packets, printing the packets we were
1894 ret = process_specified_packets(cf, &print_args->range, "Writing PSML",
1895 "selected packets", write_psml_packet,
1901 /* Completed successfully. */
1905 /* Well, the user decided to abort the printing. */
1909 /* Error while printing. */
1911 return PP_WRITE_ERROR;
1914 write_psml_finale(fh);
1917 return PP_WRITE_ERROR;
1920 /* XXX - check for an error */
1926 /* Scan through the packet list and change all columns that use the
1927 "command-line-specified" time stamp format to use the current
1928 value of that format. */
1930 change_time_formats(capture_file *cf)
1933 progdlg_t *progbar = NULL;
1939 GTimeVal start_time;
1940 gchar status_str[100];
1941 int progbar_nextstep;
1942 int progbar_quantum;
1944 gboolean sorted_by_frame_column;
1946 /* Are there any columns with time stamps in the "command-line-specified"
1949 XXX - we have to force the "column is writable" flag on, as it
1950 might be off from the last frame that was dissected. */
1951 col_set_writable(&cf->cinfo, TRUE);
1952 if (!check_col(&cf->cinfo, COL_CLS_TIME)) {
1953 /* No, there aren't any columns in that format, so we have no work
1957 first = cf->cinfo.col_first[COL_CLS_TIME];
1958 g_assert(first >= 0);
1959 last = cf->cinfo.col_last[COL_CLS_TIME];
1961 /* Freeze the packet list while we redo it, so we don't get any
1962 screen updates while it happens. */
1963 packet_list_freeze();
1965 /* Update the progress bar when it gets to this value. */
1966 progbar_nextstep = 0;
1967 /* When we reach the value that triggers a progress bar update,
1968 bump that value by this amount. */
1969 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1970 /* Count of packets at which we've looked. */
1973 /* If the rows are currently sorted by the frame column then we know
1974 * the row number of each packet: it's the row number of the previously
1975 * displayed packet + 1.
1977 * Otherwise, if the display is sorted by a different column then we have
1978 * to use the O(N) packet_list_find_row_from_data() (thus making the job
1979 * of changing the time display format O(N**2)).
1981 * (XXX - In fact it's still O(N**2) because gtk_clist_set_text() takes
1982 * the row number and walks that many elements down the clist to find
1983 * the appropriate element.)
1985 sorted_by_frame_column = FALSE;
1986 for (i = 0; i < cf->cinfo.num_cols; i++) {
1987 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1989 sorted_by_frame_column = (i == packet_list_get_sort_column());
1995 g_get_current_time(&start_time);
1997 /* Iterate through the list of packets, checking whether the packet
1998 is in a row of the summary list and, if so, whether there are
1999 any columns that show the time in the "command-line-specified"
2000 format and, if so, update that row. */
2001 for (fdata = cf->plist, row = -1; fdata != NULL; fdata = fdata->next) {
2002 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2003 when we update it, we have to run the GTK+ main loop to get it
2004 to repaint what's pending, and doing so may involve an "ioctl()"
2005 to see if there's any pending input from an X server, and doing
2006 that for every packet can be costly, especially on a big file. */
2007 if (count >= progbar_nextstep) {
2008 /* let's not divide by zero. I should never be started
2009 * with count == 0, so let's assert that
2011 g_assert(cf->count > 0);
2013 prog_val = (gfloat) count / cf->count;
2015 if (progbar == NULL)
2016 /* Create the progress bar if necessary */
2017 progbar = delayed_create_progress_dlg("Changing", "time display",
2018 &stop_flag, &start_time, prog_val);
2020 if (progbar != NULL) {
2021 g_snprintf(status_str, sizeof(status_str),
2022 "%4u of %u packets", count, cf->count);
2023 update_progress_dlg(progbar, prog_val, status_str);
2026 progbar_nextstep += progbar_quantum;
2030 /* Well, the user decided to abort the redisplay. Just stop.
2032 XXX - this leaves the time field in the old format in
2033 frames we haven't yet processed. So it goes; should we
2034 simply not offer them the option of stopping? */
2040 /* Find what row this packet is in. */
2041 if (!sorted_by_frame_column) {
2042 /* This function is O(N), so we try to avoid using it... */
2043 row = packet_list_find_row_from_data(fdata);
2045 /* ...which we do by maintaining a count of packets that are
2046 being displayed (i.e., that have passed the display filter),
2047 and using the current value of that count as the row number
2048 (which is why we can only do it when the display is sorted
2049 by the frame number). */
2050 if (fdata->flags.passed_dfilter)
2057 /* This packet is in the summary list, on row "row". */
2059 for (i = first; i <= last; i++) {
2060 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2061 /* This is one of the columns that shows the time in
2062 "command-line-specified" format; update it. */
2063 cf->cinfo.col_buf[i][0] = '\0';
2064 col_set_cls_time(fdata, &cf->cinfo, i);
2065 packet_list_set_text(row, i, cf->cinfo.col_data[i]);
2071 /* We're done redisplaying the packets; destroy the progress bar if it
2073 if (progbar != NULL)
2074 destroy_progress_dlg(progbar);
2076 /* Set the column widths of those columns that show the time in
2077 "command-line-specified" format. */
2078 for (i = first; i <= last; i++) {
2079 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
2080 packet_list_set_cls_time_width(i);
2084 /* Unfreeze the packet list. */
2092 gboolean frame_matched;
2096 find_packet_protocol_tree(capture_file *cf, const char *string)
2100 mdata.string = string;
2101 mdata.string_len = strlen(string);
2102 return find_packet(cf, match_protocol_tree, &mdata);
2106 match_protocol_tree(capture_file *cf, frame_data *fdata, void *criterion)
2108 match_data *mdata = criterion;
2109 epan_dissect_t *edt;
2111 /* Construct the protocol tree, including the displayed text */
2112 edt = epan_dissect_new(TRUE, TRUE);
2113 /* We don't need the column information */
2114 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2116 /* Iterate through all the nodes, seeing if they have text that matches. */
2118 mdata->frame_matched = FALSE;
2119 proto_tree_children_foreach(edt->tree, match_subtree_text, mdata);
2120 epan_dissect_free(edt);
2121 return mdata->frame_matched;
2125 match_subtree_text(proto_node *node, gpointer data)
2127 match_data *mdata = (match_data*) data;
2128 const gchar *string = mdata->string;
2129 size_t string_len = mdata->string_len;
2130 capture_file *cf = mdata->cf;
2131 field_info *fi = PITEM_FINFO(node);
2132 gchar label_str[ITEM_LABEL_LENGTH];
2139 if (mdata->frame_matched) {
2140 /* We already had a match; don't bother doing any more work. */
2144 /* Don't match invisible entries. */
2145 if (PROTO_ITEM_IS_HIDDEN(node))
2148 /* was a free format label produced? */
2150 label_ptr = fi->rep->representation;
2152 /* no, make a generic label */
2153 label_ptr = label_str;
2154 proto_item_fill_label(fi, label_str);
2157 /* Does that label match? */
2158 label_len = strlen(label_ptr);
2159 for (i = 0; i < label_len; i++) {
2160 c_char = label_ptr[i];
2162 c_char = toupper(c_char);
2163 if (c_char == string[c_match]) {
2165 if (c_match == string_len) {
2166 /* No need to look further; we have a match */
2167 mdata->frame_matched = TRUE;
2174 /* Recurse into the subtree, if it exists */
2175 if (node->first_child != NULL)
2176 proto_tree_children_foreach(node, match_subtree_text, mdata);
2180 find_packet_summary_line(capture_file *cf, const char *string)
2184 mdata.string = string;
2185 mdata.string_len = strlen(string);
2186 return find_packet(cf, match_summary_line, &mdata);
2190 match_summary_line(capture_file *cf, frame_data *fdata, void *criterion)
2192 match_data *mdata = criterion;
2193 const gchar *string = mdata->string;
2194 size_t string_len = mdata->string_len;
2195 epan_dissect_t *edt;
2196 const char *info_column;
2197 size_t info_column_len;
2198 gboolean frame_matched = FALSE;
2204 /* Don't bother constructing the protocol tree */
2205 edt = epan_dissect_new(FALSE, FALSE);
2206 /* Get the column information */
2207 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
2209 /* Find the Info column */
2210 for (colx = 0; colx < cf->cinfo.num_cols; colx++) {
2211 if (cf->cinfo.fmt_matx[colx][COL_INFO]) {
2212 /* Found it. See if we match. */
2213 info_column = edt->pi.cinfo->col_data[colx];
2214 info_column_len = strlen(info_column);
2215 for (i = 0; i < info_column_len; i++) {
2216 c_char = info_column[i];
2218 c_char = toupper(c_char);
2219 if (c_char == string[c_match]) {
2221 if (c_match == string_len) {
2222 frame_matched = TRUE;
2231 epan_dissect_free(edt);
2232 return frame_matched;
2238 } cbs_t; /* "Counted byte string" */
2241 find_packet_data(capture_file *cf, const guint8 *string, size_t string_size)
2246 info.data_len = string_size;
2248 /* String or hex search? */
2250 /* String search - what type of string? */
2251 switch (cf->scs_type) {
2253 case SCS_ASCII_AND_UNICODE:
2254 return find_packet(cf, match_ascii_and_unicode, &info);
2257 return find_packet(cf, match_ascii, &info);
2260 return find_packet(cf, match_unicode, &info);
2263 g_assert_not_reached();
2267 return find_packet(cf, match_binary, &info);
2271 match_ascii_and_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2273 cbs_t *info = criterion;
2274 const char *ascii_text = info->data;
2275 size_t textlen = info->data_len;
2276 gboolean frame_matched;
2282 frame_matched = FALSE;
2283 buf_len = fdata->pkt_len;
2284 for (i = 0; i < buf_len; i++) {
2287 c_char = toupper(c_char);
2289 if (c_char == ascii_text[c_match]) {
2291 if (c_match == textlen) {
2292 frame_matched = TRUE;
2299 return frame_matched;
2303 match_ascii(capture_file *cf, frame_data *fdata, void *criterion)
2305 cbs_t *info = criterion;
2306 const char *ascii_text = info->data;
2307 size_t textlen = info->data_len;
2308 gboolean frame_matched;
2314 frame_matched = FALSE;
2315 buf_len = fdata->pkt_len;
2316 for (i = 0; i < buf_len; i++) {
2319 c_char = toupper(c_char);
2320 if (c_char == ascii_text[c_match]) {
2322 if (c_match == textlen) {
2323 frame_matched = TRUE;
2329 return frame_matched;
2333 match_unicode(capture_file *cf, frame_data *fdata, void *criterion)
2335 cbs_t *info = criterion;
2336 const char *ascii_text = info->data;
2337 size_t textlen = info->data_len;
2338 gboolean frame_matched;
2344 frame_matched = FALSE;
2345 buf_len = fdata->pkt_len;
2346 for (i = 0; i < buf_len; i++) {
2349 c_char = toupper(c_char);
2350 if (c_char == ascii_text[c_match]) {
2353 if (c_match == textlen) {
2354 frame_matched = TRUE;
2360 return frame_matched;
2364 match_binary(capture_file *cf, frame_data *fdata, void *criterion)
2366 cbs_t *info = criterion;
2367 const guint8 *binary_data = info->data;
2368 size_t datalen = info->data_len;
2369 gboolean frame_matched;
2374 frame_matched = FALSE;
2375 buf_len = fdata->pkt_len;
2376 for (i = 0; i < buf_len; i++) {
2377 if (cf->pd[i] == binary_data[c_match]) {
2379 if (c_match == datalen) {
2380 frame_matched = TRUE;
2386 return frame_matched;
2390 find_packet_dfilter(capture_file *cf, dfilter_t *sfcode)
2392 return find_packet(cf, match_dfilter, sfcode);
2396 match_dfilter(capture_file *cf, frame_data *fdata, void *criterion)
2398 dfilter_t *sfcode = criterion;
2399 epan_dissect_t *edt;
2400 gboolean frame_matched;
2402 edt = epan_dissect_new(TRUE, FALSE);
2403 epan_dissect_prime_dfilter(edt, sfcode);
2404 epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, NULL);
2405 frame_matched = dfilter_apply_edt(sfcode, edt);
2406 epan_dissect_free(edt);
2407 return frame_matched;
2411 find_packet(capture_file *cf,
2412 gboolean (*match_function)(capture_file *, frame_data *, void *),
2415 frame_data *start_fd;
2417 frame_data *new_fd = NULL;
2418 progdlg_t *progbar = NULL;
2425 GTimeVal start_time;
2426 gchar status_str[100];
2427 int progbar_nextstep;
2428 int progbar_quantum;
2430 start_fd = cf->current_frame;
2431 if (start_fd != NULL) {
2432 /* Iterate through the list of packets, starting at the packet we've
2433 picked, calling a routine to run the filter on the packet, see if
2434 it matches, and stop if so. */
2438 progbar_nextstep = 0;
2439 /* When we reach the value that triggers a progress bar update,
2440 bump that value by this amount. */
2441 progbar_quantum = cf->count/N_PROGBAR_UPDATES;
2444 g_get_current_time(&start_time);
2448 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
2449 when we update it, we have to run the GTK+ main loop to get it
2450 to repaint what's pending, and doing so may involve an "ioctl()"
2451 to see if there's any pending input from an X server, and doing
2452 that for every packet can be costly, especially on a big file. */
2453 if (count >= progbar_nextstep) {
2454 /* let's not divide by zero. I should never be started
2455 * with count == 0, so let's assert that
2457 g_assert(cf->count > 0);
2459 prog_val = (gfloat) count / cf->count;
2461 /* Create the progress bar if necessary */
2462 if (progbar == NULL)
2463 progbar = delayed_create_progress_dlg("Searching", cf->sfilter,
2464 &stop_flag, &start_time, prog_val);
2466 if (progbar != NULL) {
2467 g_snprintf(status_str, sizeof(status_str),
2468 "%4u of %u packets", count, cf->count);
2469 update_progress_dlg(progbar, prog_val, status_str);
2472 progbar_nextstep += progbar_quantum;
2476 /* Well, the user decided to abort the search. Go back to the
2477 frame where we started. */
2482 /* Go past the current frame. */
2483 if (cf->sbackward) {
2484 /* Go on to the previous frame. */
2485 fdata = fdata->prev;
2486 if (fdata == NULL) {
2488 * XXX - other apps have a bit more of a detailed message
2489 * for this, and instead of offering "OK" and "Cancel",
2490 * they offer things such as "Continue" and "Cancel";
2491 * we need an API for popping up alert boxes with
2492 * {Verb} and "Cancel".
2495 if (prefs.gui_find_wrap)
2497 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2498 "%sBeginning of capture exceeded!%s\n\n"
2499 "Search is continued from the end of the capture.",
2500 simple_dialog_primary_start(), simple_dialog_primary_end());
2501 fdata = cf->plist_end; /* wrap around */
2505 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2506 "%sBeginning of capture exceeded!%s\n\n"
2507 "Try searching forwards.",
2508 simple_dialog_primary_start(), simple_dialog_primary_end());
2509 fdata = start_fd; /* stay on previous packet */
2513 /* Go on to the next frame. */
2514 fdata = fdata->next;
2515 if (fdata == NULL) {
2516 if (prefs.gui_find_wrap)
2518 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2519 "%sEnd of capture exceeded!%s\n\n"
2520 "Search is continued from the start of the capture.",
2521 simple_dialog_primary_start(), simple_dialog_primary_end());
2522 fdata = cf->plist; /* wrap around */
2526 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
2527 "%sEnd of capture exceeded!%s\n\n"
2528 "Try searching backwards.",
2529 simple_dialog_primary_start(), simple_dialog_primary_end());
2530 fdata = start_fd; /* stay on previous packet */
2537 /* Is this packet in the display? */
2538 if (fdata->flags.passed_dfilter) {
2539 /* Yes. Load its data. */
2540 if (!wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header,
2541 cf->pd, fdata->cap_len, &err, &err_info)) {
2542 /* Read error. Report the error, and go back to the frame
2543 where we started. */
2544 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2545 cf_read_error_message(err, err_info), cf->filename);
2550 /* Does it match the search criterion? */
2551 if ((*match_function)(cf, fdata, criterion)) {
2553 break; /* found it! */
2557 if (fdata == start_fd) {
2558 /* We're back to the frame we were on originally, and that frame
2559 doesn't match the search filter. The search failed. */
2564 /* We're done scanning the packets; destroy the progress bar if it
2566 if (progbar != NULL)
2567 destroy_progress_dlg(progbar);
2570 if (new_fd != NULL) {
2571 /* We found a frame. Find what row it's in. */
2572 row = packet_list_find_row_from_data(new_fd);
2573 g_assert(row != -1);
2575 /* Select that row, make it the focus row, and make it visible. */
2576 packet_list_set_selected_row(row);
2577 return TRUE; /* success */
2579 return FALSE; /* failure */
2583 goto_frame(capture_file *cf, guint fnumber)
2588 for (fdata = cf->plist; fdata != NULL && fdata->num < fnumber; fdata = fdata->next)
2591 if (fdata == NULL) {
2592 /* we didn't find a packet with that packet number */
2593 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2594 "There is no packet with that packet number.");
2595 return FALSE; /* we failed to go to that packet */
2597 if (!fdata->flags.passed_dfilter) {
2598 /* that packet currently isn't displayed */
2599 /* XXX - add it to the set of displayed packets? */
2600 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2601 "That packet is not currently being displayed.");
2602 return FALSE; /* we failed to go to that packet */
2605 /* We found that packet, and it's currently being displayed.
2606 Find what row it's in. */
2607 row = packet_list_find_row_from_data(fdata);
2608 g_assert(row != -1);
2610 /* Select that row, make it the focus row, and make it visible. */
2611 packet_list_set_selected_row(row);
2612 return TRUE; /* we got to that packet */
2616 goto_top_frame(capture_file *cf)
2620 frame_data *lowest_fdata = NULL;
2622 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2623 if (fdata->flags.passed_dfilter) {
2624 lowest_fdata = fdata;
2629 if (lowest_fdata == NULL) {
2633 /* We found that packet, and it's currently being displayed.
2634 Find what row it's in. */
2635 row = packet_list_find_row_from_data(lowest_fdata);
2636 g_assert(row != -1);
2638 /* Select that row, make it the focus row, and make it visible. */
2639 packet_list_set_selected_row(row);
2640 return TRUE; /* we got to that packet */
2644 goto_bottom_frame(capture_file *cf)
2648 frame_data *highest_fdata = NULL;
2650 for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) {
2651 if (fdata->flags.passed_dfilter) {
2652 highest_fdata = fdata;
2656 if (highest_fdata == NULL) {
2660 /* We found that packet, and it's currently being displayed.
2661 Find what row it's in. */
2662 row = packet_list_find_row_from_data(highest_fdata);
2663 g_assert(row != -1);
2665 /* Select that row, make it the focus row, and make it visible. */
2666 packet_list_set_selected_row(row);
2667 return TRUE; /* we got to that packet */
2671 * Go to frame specified by currently selected protocol tree item.
2674 goto_framenum(capture_file *cf)
2676 header_field_info *hfinfo;
2679 if (cf->finfo_selected) {
2680 hfinfo = cf->finfo_selected->hfinfo;
2682 if (hfinfo->type == FT_FRAMENUM) {
2683 framenum = fvalue_get_integer(&cf->finfo_selected->value);
2685 goto_frame(cf, framenum);
2690 /* Select the packet on a given row. */
2692 select_packet(capture_file *cf, int row)
2698 /* Get the frame data struct pointer for this frame */
2699 fdata = (frame_data *)packet_list_get_row_data(row);
2701 if (fdata == NULL) {
2702 /* XXX - if a GtkCList's selection mode is GTK_SELECTION_BROWSE, when
2703 the first entry is added to it by "real_insert_row()", that row
2704 is selected (see "real_insert_row()", in "gtk/gtkclist.c", in both
2705 our version and the vanilla GTK+ version).
2707 This means that a "select-row" signal is emitted; this causes
2708 "packet_list_select_cb()" to be called, which causes "select_packet()"
2711 "select_packet()" fetches, above, the data associated with the
2712 row that was selected; however, as "gtk_clist_append()", which
2713 called "real_insert_row()", hasn't yet returned, we haven't yet
2714 associated any data with that row, so we get back a null pointer.
2716 We can't assume that there's only one frame in the frame list,
2717 either, as we may be filtering the display.
2719 We therefore assume that, if "row" is 0, i.e. the first row
2720 is being selected, and "cf->first_displayed" equals
2721 "cf->last_displayed", i.e. there's only one frame being
2722 displayed, that frame is the frame we want.
2724 This means we have to set "cf->first_displayed" and
2725 "cf->last_displayed" before adding the row to the
2726 GtkCList; see the comment in "add_packet_to_packet_list()". */
2728 if (row == 0 && cf->first_displayed == cf->last_displayed)
2729 fdata = cf->first_displayed;
2732 /* Get the data in that frame. */
2733 if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
2734 cf->pd, fdata->cap_len, &err, &err_info)) {
2735 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2736 cf_read_error_message(err, err_info), cf->filename);
2740 /* Record that this frame is the current frame. */
2741 cf->current_frame = fdata;
2743 /* Create the logical protocol tree. */
2744 if (cf->edt != NULL) {
2745 epan_dissect_free(cf->edt);
2748 /* We don't need the columns here. */
2749 cf->edt = epan_dissect_new(TRUE, TRUE);
2750 epan_dissect_run(cf->edt, &cf->pseudo_header, cf->pd, cf->current_frame,
2753 /* Display the GUI protocol tree and hex dump.
2754 XXX - why do we dump core if we call "proto_tree_draw()"
2755 before calling "add_byte_views()"? */
2756 add_main_byte_views(cf->edt);
2757 main_proto_tree_draw(cf->edt->tree);
2759 /* A packet is selected. */
2760 set_menus_for_selected_packet(cf);
2763 /* Unselect the selected packet, if any. */
2765 unselect_packet(capture_file *cf)
2767 /* Destroy the epan_dissect_t for the unselected packet. */
2768 if (cf->edt != NULL) {
2769 epan_dissect_free(cf->edt);
2773 /* Clear out the display of that packet. */
2774 clear_tree_and_hex_views();
2776 /* No packet is selected. */
2777 cf->current_frame = NULL;
2778 set_menus_for_selected_packet(cf);
2780 /* No protocol tree means no selected field. */
2784 /* Unset the selected protocol tree field, if any. */
2786 unselect_field(capture_file *cf)
2788 statusbar_pop_field_msg();
2789 cf->finfo_selected = NULL;
2790 set_menus_for_selected_tree_row(cf);
2794 * Mark a particular frame.
2797 mark_frame(capture_file *cf, frame_data *frame)
2799 if (! frame->flags.marked) {
2800 frame->flags.marked = TRUE;
2801 if (cf->count > cf->marked_count)
2807 * Unmark a particular frame.
2810 unmark_frame(capture_file *cf, frame_data *frame)
2812 if (frame->flags.marked) {
2813 frame->flags.marked = FALSE;
2814 if (cf->marked_count > 0)
2822 } save_callback_args_t;
2825 * Save a capture to a file, in a particular format, saving either
2826 * all packets, all currently-displayed packets, or all marked packets.
2828 * Returns TRUE if it succeeds, FALSE otherwise; if it fails, it pops
2829 * up a message box for the failure.
2832 save_packet(capture_file *cf _U_, frame_data *fdata,
2833 union wtap_pseudo_header *pseudo_header, const guint8 *pd,
2836 save_callback_args_t *args = argsp;
2837 struct wtap_pkthdr hdr;
2840 /* init the wtap header for saving */
2841 hdr.ts.tv_sec = fdata->abs_secs;
2842 hdr.ts.tv_usec = fdata->abs_usecs;
2843 hdr.caplen = fdata->cap_len;
2844 hdr.len = fdata->pkt_len;
2845 hdr.pkt_encap = fdata->lnk_t;
2847 /* and save the packet */
2848 if (!wtap_dump(args->pdh, &hdr, pseudo_header, pd, &err)) {
2849 cf_write_failure_alert_box(args->fname, err);
2856 cf_save(char *fname, capture_file *cf, packet_range_t *range, guint save_format)
2858 gchar *from_filename;
2859 gchar *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
2864 struct stat infile, outfile;
2865 save_callback_args_t callback_args;
2867 name_ptr = get_basename(fname);
2868 msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
2869 save_msg = g_malloc(msg_len);
2870 snprintf(save_msg, msg_len, save_fmt, name_ptr);
2871 statusbar_push_file_msg(save_msg);
2875 * Check that the from file is not the same as to file
2876 * We do it here so we catch all cases ...
2877 * Unfortunately, the file requester gives us an absolute file
2878 * name and the read file name may be relative (if supplied on
2879 * the command line). From Joerg Mayer.
2881 * This is a bit tricky on win32. The st_ino field is documented as:
2882 * "The inode, and therefore st_ino, has no meaning in the FAT, ..."
2883 * but it *is* set to zero if stat() returns without an error,
2884 * so this is working, but maybe not quite the way expected. ULFL
2886 infile.st_ino = 1; /* These prevent us from getting equality */
2887 outfile.st_ino = 2; /* If one or other of the files is not accessible */
2888 stat(cf->filename, &infile);
2889 stat(fname, &outfile);
2890 if (infile.st_ino == outfile.st_ino) {
2891 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2892 "%sCapture file: \"%s\" already exists!%s\n\n"
2893 "Please choose a different filename.",
2894 simple_dialog_primary_start(), fname, simple_dialog_primary_end());
2898 packet_range_process_init(range);
2901 * if (!save_filtered && !save_marked && !save_manual_range &&
2902 * !save_marked_range && !save_curr && save_format == cf->cd_t) {
2905 if (packet_range_process_all(range) && save_format == cf->cd_t) {
2906 /* We're not filtering packets, and we're saving it in the format
2907 it's already in, so we can just move or copy the raw data. */
2909 if (cf->is_tempfile) {
2910 /* The file being saved is a temporary file from a live
2911 capture, so it doesn't need to stay around under that name;
2912 first, try renaming the capture buffer file to the new name. */
2914 if (rename(cf->filename, fname) == 0) {
2915 /* That succeeded - there's no need to copy the source file. */
2916 from_filename = NULL;
2919 if (errno == EXDEV) {
2920 /* They're on different file systems, so we have to copy the
2923 from_filename = cf->filename;
2925 /* The rename failed, but not because they're on different
2926 file systems - put up an error message. (Or should we
2927 just punt and try to copy? The only reason why I'd
2928 expect the rename to fail and the copy to succeed would
2929 be if we didn't have permission to remove the file from
2930 the temporary directory, and that might be fixable - but
2931 is it worth requiring the user to go off and fix it?) */
2932 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
2933 file_rename_error_message(errno), fname);
2939 from_filename = cf->filename;
2942 /* It's a permanent file, so we should copy it, and not remove the
2945 from_filename = cf->filename;
2949 /* Copy the file, if we haven't moved it. */
2950 if (!copy_binary_file(from_filename, fname))
2954 /* Either we're filtering packets, or we're saving in a different
2955 format; we can't do that by copying or moving the capture file,
2956 we have to do it by writing the packets out in Wiretap. */
2957 pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
2959 cf_open_failure_alert_box(fname, err, NULL, TRUE, save_format);
2963 /* XXX - we let the user save a subset of the packets.
2965 If we do that, should we make that file the current file? If so,
2966 it means we can no longer get at the other packets. What does
2969 /* Iterate through the list of packets, processing the packets we were
2972 XXX - we've already called "packet_range_process_init(range)", but
2973 "process_specified_packets()" will do it again. Fortunately,
2974 that's harmless in this case, as we haven't done anything to
2975 "range" since we initialized it. */
2976 callback_args.pdh = pdh;
2977 callback_args.fname = fname;
2978 switch (process_specified_packets(cf, range, "Saving",
2979 "selected packets", save_packet,
2983 /* Completed successfully. */
2987 /* The user decided to abort the saving.
2988 XXX - remove the output file? */
2992 /* Error while saving. */
2993 wtap_dump_close(pdh, &err);
2997 if (!wtap_dump_close(pdh, &err)) {
2998 cf_close_failure_alert_box(fname, err);
3003 /* Pop the "Saving:" message off the status bar. */
3004 statusbar_pop_file_msg();
3006 if (packet_range_process_all(range)) {
3007 /* We saved the entire capture, not just some packets from it.
3008 Open and read the file we saved it to.
3010 XXX - this is somewhat of a waste; we already have the
3011 packets, all this gets us is updated file type information
3012 (which we could just stuff into "cf"), and having the new
3013 file be the one we have opened and from which we're reading
3014 the data, and it means we have to spend time opening and
3015 reading the file, which could be a significant amount of
3016 time if the file is large. */
3017 cf->user_saved = TRUE;
3019 if ((err = cf_open(fname, FALSE, cf)) == 0) {
3020 /* XXX - report errors if this fails?
3021 What should we return if it fails or is aborted? */
3022 switch (cf_read(cf)) {
3026 /* Just because we got an error, that doesn't mean we were unable
3027 to read any of the file; we handle what we could get from the
3032 /* The user bailed out of re-reading the capture file; the
3033 capture file has been closed - just return (without
3034 changing any menu settings; "cf_close()" set them
3035 correctly for the "no capture file open" state). */
3038 set_menus_for_unsaved_capture_file(FALSE);
3044 /* Pop the "Saving:" message off the status bar. */
3045 statusbar_pop_file_msg();
3050 cf_open_failure_alert_box(const char *filename, int err, gchar *err_info,
3051 gboolean for_writing, int file_type)
3054 /* Wiretap error. */
3057 case WTAP_ERR_NOT_REGULAR_FILE:
3058 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3059 "The file \"%s\" is a \"special file\" or socket or other non-regular file.",
3063 case WTAP_ERR_RANDOM_OPEN_PIPE:
3064 /* Seen only when opening a capture file for reading. */
3065 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3066 "The file \"%s\" is a pipe or FIFO; Ethereal cannot read pipe or FIFO files.",
3070 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
3071 /* Seen only when opening a capture file for reading. */
3072 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3073 "The file \"%s\" is not a capture file in a format Ethereal understands.",
3077 case WTAP_ERR_UNSUPPORTED:
3078 /* Seen only when opening a capture file for reading. */
3079 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3080 "The file \"%s\" is not a capture file in a format Ethereal understands.\n"
3082 filename, err_info);
3086 case WTAP_ERR_CANT_WRITE_TO_PIPE:
3087 /* Seen only when opening a capture file for writing. */
3088 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3089 "The file \"%s\" is a pipe, and %s capture files cannot be "
3090 "written to a pipe.",
3091 filename, wtap_file_type_string(file_type));
3094 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
3095 /* Seen only when opening a capture file for writing. */
3096 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3097 "Ethereal does not support writing capture files in that format.");
3100 case WTAP_ERR_UNSUPPORTED_ENCAP:
3102 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3103 "Ethereal cannot save this capture in that format.");
3105 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3106 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.\n"
3108 filename, err_info);
3113 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
3115 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3116 "Ethereal cannot save this capture in that format.");
3118 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3119 "The file \"%s\" is a capture for a network type that Ethereal doesn't support.",
3124 case WTAP_ERR_BAD_RECORD:
3125 /* Seen only when opening a capture file for reading. */
3126 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3127 "The file \"%s\" appears to be damaged or corrupt.\n"
3129 filename, err_info);
3133 case WTAP_ERR_CANT_OPEN:
3135 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3136 "The file \"%s\" could not be created for some unknown reason.",
3139 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3140 "The file \"%s\" could not be opened for some unknown reason.",
3145 case WTAP_ERR_SHORT_READ:
3146 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3147 "The file \"%s\" appears to have been cut short"
3148 " in the middle of a packet or other data.",
3152 case WTAP_ERR_SHORT_WRITE:
3153 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3154 "A full header couldn't be written to the file \"%s\".",
3159 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3160 "The file \"%s\" could not be %s: %s.",
3162 for_writing ? "created" : "opened",
3163 wtap_strerror(err));
3168 open_failure_alert_box(filename, err, for_writing);
3173 file_rename_error_message(int err)
3176 static char errmsg_errno[1024+1];
3181 errmsg = "The path to the file \"%s\" does not exist.";
3185 errmsg = "You do not have permission to move the capture file to \"%s\".";
3189 snprintf(errmsg_errno, sizeof(errmsg_errno),
3190 "The file \"%%s\" could not be moved: %s.",
3191 wtap_strerror(err));
3192 errmsg = errmsg_errno;
3199 cf_read_error_message(int err, gchar *err_info)
3201 static char errmsg_errno[1024+1];
3205 case WTAP_ERR_UNSUPPORTED_ENCAP:
3206 snprintf(errmsg_errno, sizeof(errmsg_errno),
3207 "The file \"%%s\" has a packet with a network type that Ethereal doesn't support.\n(%s)",
3211 case WTAP_ERR_BAD_RECORD:
3212 snprintf(errmsg_errno, sizeof(errmsg_errno),
3213 "An error occurred while reading from the file \"%%s\": %s.\n(%s)",
3214 wtap_strerror(err), err_info);
3218 snprintf(errmsg_errno, sizeof(errmsg_errno),
3219 "An error occurred while reading from the file \"%%s\": %s.",
3220 wtap_strerror(err));
3223 return errmsg_errno;
3227 cf_write_failure_alert_box(const char *filename, int err)
3230 /* Wiretap error. */
3231 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3232 "An error occurred while writing to the file \"%s\": %s.",
3233 filename, wtap_strerror(err));
3236 write_failure_alert_box(filename, err);
3240 /* Check for write errors - if the file is being written to an NFS server,
3241 a write error may not show up until the file is closed, as NFS clients
3242 might not send writes to the server until the "write()" call finishes,
3243 so that the write may fail on the server but the "write()" may succeed. */
3245 cf_close_failure_alert_box(const char *filename, int err)
3248 /* Wiretap error. */
3251 case WTAP_ERR_CANT_CLOSE:
3252 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3253 "The file \"%s\" couldn't be closed for some unknown reason.",
3257 case WTAP_ERR_SHORT_WRITE:
3258 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3259 "Not all the packets could be written to the file \"%s\".",
3264 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3265 "An error occurred while closing the file \"%s\": %s.",
3266 filename, wtap_strerror(err));
3271 We assume that a close error from the OS is really a write error. */
3272 write_failure_alert_box(filename, err);
3276 /* Reload the current capture file. */
3280 gboolean is_tempfile;
3282 /* If the file could be opened, "cf_open()" calls "cf_close()"
3283 to get rid of state for the old capture file before filling in state
3284 for the new capture file. "cf_close()" will remove the file if
3285 it's a temporary file; we don't want that to happen (for one thing,
3286 it'd prevent subsequent reopens from working). Remember whether it's
3287 a temporary file, mark it as not being a temporary file, and then
3288 reopen it as the type of file it was.
3290 Also, "cf_close()" will free "cfile.filename", so we must make
3291 a copy of it first. */
3292 filename = g_strdup(cfile.filename);
3293 is_tempfile = cfile.is_tempfile;
3294 cfile.is_tempfile = FALSE;
3295 if (cf_open(filename, is_tempfile, &cfile) == 0) {
3296 switch (cf_read(&cfile)) {
3300 /* Just because we got an error, that doesn't mean we were unable
3301 to read any of the file; we handle what we could get from the
3306 /* The user bailed out of re-reading the capture file; the
3307 capture file has been closed - just free the capture file name
3308 string and return (without changing the last containing
3314 /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
3315 Instead, the file was left open, so we should restore "cfile.is_tempfile"
3318 XXX - change the menu? Presumably "cf_open()" will do that;
3319 make sure it does! */
3320 cfile.is_tempfile = is_tempfile;
3322 /* "cf_open()" made a copy of the file name we handed it, so
3323 we should free up our copy. */
3327 /* Copies a file in binary mode, for those operating systems that care about
3329 * Returns TRUE on success, FALSE on failure. If a failure, it also
3330 * displays a simple dialog window with the error message.
3333 copy_binary_file(char *from_filename, char *to_filename)
3335 int from_fd, to_fd, nread, nwritten, err;
3338 /* Copy the raw bytes of the file. */
3339 from_fd = open(from_filename, O_RDONLY | O_BINARY);
3341 open_failure_alert_box(from_filename, errno, FALSE);
3345 /* Use open() instead of creat() so that we can pass the O_BINARY
3346 flag, which is relevant on Win32; it appears that "creat()"
3347 may open the file in text mode, not binary mode, but we want
3348 to copy the raw bytes of the file, so we need the output file
3349 to be open in binary mode. */
3350 to_fd = open(to_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
3352 open_failure_alert_box(to_filename, errno, TRUE);
3357 while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
3358 nwritten = write(to_fd, pd, nread);
3359 if (nwritten < nread) {
3363 err = WTAP_ERR_SHORT_WRITE;
3364 write_failure_alert_box(to_filename, err);
3372 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3373 "An error occurred while reading from the file \"%s\": %s.",
3374 from_filename, strerror(err));
3380 if (close(to_fd) < 0) {
3381 write_failure_alert_box(to_filename, errno);