4 * $Id: file.c,v 1.112 1999/10/22 08:30:02 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@zing.org>
8 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
51 #ifdef NEED_SNPRINTF_H
57 # include "snprintf.h"
60 #ifdef NEED_STRERROR_H
64 #ifdef HAVE_SYS_TYPES_H
65 # include <sys/types.h>
68 #ifdef HAVE_NETINET_IN_H
69 # include <netinet/in.h>
72 #ifdef HAVE_SYS_WAIT_H
73 # include <sys/wait.h>
83 #include "gtk/proto_draw.h"
85 #include "timestamp.h"
86 #include "conversation.h"
92 #include "packet-atalk.h"
94 #include "packet-ipv6.h"
96 #include "packet-ncp.h"
98 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
99 extern guint file_ctx;
100 extern int sync_pipe[];
103 gboolean auto_scroll_live = FALSE;
105 static guint32 firstsec, firstusec;
106 static guint32 prevsec, prevusec;
108 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
111 static void freeze_clist(capture_file *cf);
112 static void thaw_clist(capture_file *cf);
114 /* Update the progress bar this many times when reading a file. */
115 #define N_PROGBAR_UPDATES 100
118 open_cap_file(char *fname, capture_file *cf) {
125 wth = wtap_open_offline(fname, &err);
129 /* Find the size of the file. */
132 if (fstat(fd, &cf_stat) < 0) {
138 /* The open succeeded. Close whatever capture file we had open,
139 and fill in the information for this file. */
140 close_cap_file(cf, info_bar, file_ctx);
142 /* Initialize the table of conversations. */
145 /* Initialize protocol-specific variables */
153 cf->f_len = cf_stat.st_size;
155 /* set the file name because we need it to set the follow stream filter */
156 cf->filename = g_strdup(fname);
158 cf->cd_t = wtap_file_type(cf->wth);
159 cf->cd_t_desc = wtap_file_type_string(cf->wth);
164 cf->snap = wtap_snapshot_length(cf->wth);
165 cf->update_progbar = FALSE;
166 cf->progbar_quantum = 0;
167 cf->progbar_nextstep = 0;
168 firstsec = 0, firstusec = 0;
169 prevsec = 0, prevusec = 0;
174 simple_dialog(ESD_TYPE_WARN, NULL,
175 file_open_error_message(err, FALSE), fname);
179 /* Reset everything to a pristine state */
181 close_cap_file(capture_file *cf, void *w, guint context) {
182 frame_data *fd, *fd_next;
192 for (fd = cf->plist; fd != NULL; fd = fd_next) {
196 if (cf->rfcode != NULL) {
197 dfilter_destroy(cf->rfcode);
201 cf->plist_end = NULL;
202 unselect_packet(cf); /* nothing to select */
204 gtk_clist_freeze(GTK_CLIST(packet_list));
205 gtk_clist_clear(GTK_CLIST(packet_list));
206 gtk_clist_thaw(GTK_CLIST(packet_list));
207 gtk_statusbar_pop(GTK_STATUSBAR(w), context);
209 /* Disable all menu items that make sense only if you have a capture. */
210 set_menu_sensitivity("/File/Save", FALSE);
211 set_menu_sensitivity("/File/Save As...", FALSE);
212 set_menu_sensitivity("/File/Close", FALSE);
213 set_menu_sensitivity("/File/Reload", FALSE);
214 set_menu_sensitivity("/File/Print...", FALSE);
215 set_menu_sensitivity("/Display/Options...", FALSE);
216 set_menu_sensitivity("/Tools/Summary", FALSE);
220 read_cap_file(capture_file *cf) {
221 gchar *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
222 gchar *done_fmt = " File: %s Drops: %d";
227 char errmsg_errno[1024+1];
228 gchar err_str[2048+1];
230 if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
231 name_ptr = cf->filename;
235 load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
236 sprintf(load_msg, load_fmt, name_ptr);
237 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
239 cf->update_progbar = TRUE;
240 /* Update the progress bar when it gets to this value. */
241 cf->progbar_nextstep = 0;
242 /* When we reach the value that triggers a progress bar update,
243 bump that value by this amount. */
244 cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
247 proto_tree_is_visible = FALSE;
248 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
251 cf->filed = open(cf->filename, O_RDONLY);
252 cf->fh = filed_open(cf->filed, "r");
253 cf->unfiltered_count = cf->count;
256 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
257 gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
259 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
261 msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
262 load_msg = g_realloc(load_msg, msg_len);
264 if (cf->user_saved || !cf->save_file)
265 snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
267 snprintf(load_msg, msg_len, done_fmt, "<none>", cf->drops);
269 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
272 /* Enable menu items that make sense if you have a capture. */
273 set_menu_sensitivity("/File/Close", TRUE);
274 set_menu_sensitivity("/File/Reload", TRUE);
275 set_menu_sensitivity("/File/Print...", TRUE);
276 set_menu_sensitivity("/Display/Options...", TRUE);
277 set_menu_sensitivity("/Tools/Summary", TRUE);
280 /* Put up a message box noting that the read failed somewhere along
281 the line. Don't throw out the stuff we managed to read, though,
285 case WTAP_ERR_CANT_READ:
286 errmsg = "An attempt to read from the file failed for"
287 " some unknown reason.";
290 case WTAP_ERR_SHORT_READ:
291 errmsg = "The capture file appears to have been cut short"
292 " in the middle of a packet.";
295 case WTAP_ERR_BAD_RECORD:
296 errmsg = "The capture file appears to be damaged or corrupt.";
300 sprintf(errmsg_errno, "An error occurred while reading the"
301 " capture file: %s.", wtap_strerror(err));
302 errmsg = errmsg_errno;
305 snprintf(err_str, sizeof err_str, errmsg);
306 simple_dialog(ESD_TYPE_WARN, NULL, err_str);
314 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
316 capture_file *cf = (capture_file *)data;
317 char buffer[256+1], *p = buffer, *q = buffer;
320 gboolean exit_loop = FALSE;
326 char sigmsg_buf[6+1+3+1];
329 /* avoid reentrancy problems and stack overflow */
330 gtk_input_remove(cap_input_id);
332 if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
334 /* The child has closed the sync pipe, meaning it's not going to be
335 capturing any more packets. Pick up its exit status, and
336 complain if it died of a signal. */
337 if (wait(&wstatus) != -1) {
338 /* XXX - are there any platforms on which we can run that *don't*
339 support POSIX.1's <sys/wait.h> and macros therein? */
340 wsignal = wstatus & 0177;
342 if (wstatus == 0177) {
343 /* It stopped, rather than exiting. "Should not happen." */
345 wsignal = (wstatus >> 8) & 0xFF;
349 coredumped = " - core dumped";
359 sigmsg = "Interrupted";
367 sigmsg = "Illegal instruction";
371 sigmsg = "Trace trap";
379 sigmsg = "Arithmetic exception";
387 sigmsg = "Bus error";
391 sigmsg = "Segmentation violation";
394 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
395 Linux is POSIX compliant. These are not POSIX-defined signals ---
396 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
398 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
399 were omitted from POSIX.1 because their behavior is
400 implementation dependent and could not be adequately catego-
401 rized. Conforming implementations may deliver these sig-
402 nals, but must document the circumstances under which they
403 are delivered and note any restrictions concerning their
409 sigmsg = "Bad system call";
414 sigmsg = "Broken pipe";
418 sigmsg = "Alarm clock";
422 sigmsg = "Terminated";
426 sprintf(sigmsg_buf, "Signal %d", wsignal);
430 simple_dialog(ESD_TYPE_WARN, NULL,
431 "Child capture process %s: %s%s", msg, sigmsg, coredumped);
435 /* Read what remains of the capture file, and stop capture (restore
437 gtk_clist_freeze(GTK_CLIST(packet_list));
439 /* XXX - do something if this fails? */
440 wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
443 if (auto_scroll_live)
444 gtk_clist_moveto(GTK_CLIST(packet_list),
445 cf->plist_end->row, -1, 1.0, 1.0);
449 set_menu_sensitivity("/File/Open...", TRUE);
450 set_menu_sensitivity("/File/Close", TRUE);
451 set_menu_sensitivity("/File/Save As...", TRUE);
452 set_menu_sensitivity("/File/Print...", TRUE);
453 set_menu_sensitivity("/File/Reload", TRUE);
454 set_menu_sensitivity("/Capture/Start...", TRUE);
455 set_menu_sensitivity("/Tools/Summary", TRUE);
456 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
460 buffer[nread] = '\0';
463 /* look for (possibly multiple) '*' */
471 /* XXX should handle the case of a pipe full (i.e. no star found) */
480 gtk_clist_freeze(GTK_CLIST(packet_list));
481 /* XXX - do something if this fails? */
482 wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
483 gtk_clist_thaw(GTK_CLIST(packet_list));
484 if (auto_scroll_live)
485 gtk_clist_moveto(GTK_CLIST(packet_list), cf->plist_end->row, -1, 1.0, 1.0);
487 /* restore pipe handler */
488 cap_input_id = gtk_input_add_full (sync_pipe[0],
497 tail_cap_file(char *fname, capture_file *cf) {
501 err = open_cap_file(fname, cf);
502 if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
504 set_menu_sensitivity("/File/Open...", FALSE);
505 set_menu_sensitivity("/Display/Options...", TRUE);
506 set_menu_sensitivity("/Capture/Start...", FALSE);
508 for (i = 0; i < cf->cinfo.num_cols; i++) {
509 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
510 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
512 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
513 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
514 cf->cinfo.col_width[i]);
515 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
519 cf->fh = file_open(fname, "r");
521 cap_input_id = gtk_input_add_full (sync_pipe[0],
527 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx,
528 " <live capture in progress>");
535 #endif /* HAVE_LIBPCAP */
537 /* To do: Add check_col checks to the col_add* routines */
540 col_set_abs_time(frame_data *fd, int col)
546 tmp = localtime(&then);
547 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
551 (long)fd->abs_usecs/100);
555 col_set_rel_time(frame_data *fd, int col)
557 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
562 col_set_delta_time(frame_data *fd, int col)
564 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
568 /* Add "command-line-specified" time. */
570 col_set_cls_time(frame_data *fd, int col)
572 switch (timestamp_type) {
574 col_set_abs_time(fd, col);
578 col_set_rel_time(fd, col);
582 col_set_delta_time(fd, col);
588 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
591 struct e_in6_addr ipv6_addr;
592 struct atalk_ddp_addr ddp_addr;
594 switch (addr->type) {
598 strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
600 strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
604 memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
606 strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
608 strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
612 memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
614 strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
616 strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
620 strncpy(fd->cinfo->col_data[col],
621 ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
628 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
632 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
633 pntohs(&addr->data[0]));
639 memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
640 strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
645 strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
652 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
656 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
663 strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
665 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
670 strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
672 snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
678 fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
682 fill_in_columns(frame_data *fd)
686 for (i = 0; i < fd->cinfo->num_cols; i++) {
687 switch (fd->cinfo->col_fmt[i]) {
690 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
694 col_set_cls_time(fd, i);
698 col_set_abs_time(fd, i);
702 col_set_rel_time(fd, i);
706 col_set_delta_time(fd, i);
710 case COL_RES_SRC: /* COL_DEF_SRC is currently just like COL_RES_SRC */
711 col_set_addr(fd, i, &pi.src, TRUE);
715 col_set_addr(fd, i, &pi.src, FALSE);
720 col_set_addr(fd, i, &pi.dl_src, TRUE);
723 case COL_UNRES_DL_SRC:
724 col_set_addr(fd, i, &pi.dl_src, FALSE);
727 case COL_DEF_NET_SRC:
728 case COL_RES_NET_SRC:
729 col_set_addr(fd, i, &pi.net_src, TRUE);
732 case COL_UNRES_NET_SRC:
733 col_set_addr(fd, i, &pi.net_src, FALSE);
737 case COL_RES_DST: /* COL_DEF_DST is currently just like COL_RES_DST */
738 col_set_addr(fd, i, &pi.dst, TRUE);
742 col_set_addr(fd, i, &pi.dst, FALSE);
747 col_set_addr(fd, i, &pi.dl_dst, TRUE);
750 case COL_UNRES_DL_DST:
751 col_set_addr(fd, i, &pi.dl_dst, FALSE);
754 case COL_DEF_NET_DST:
755 case COL_RES_NET_DST:
756 col_set_addr(fd, i, &pi.net_dst, TRUE);
759 case COL_UNRES_NET_DST:
760 col_set_addr(fd, i, &pi.net_dst, FALSE);
763 case COL_DEF_SRC_PORT:
764 case COL_RES_SRC_PORT: /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
765 col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
768 case COL_UNRES_SRC_PORT:
769 col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
772 case COL_DEF_DST_PORT:
773 case COL_RES_DST_PORT: /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
774 col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
777 case COL_UNRES_DST_PORT:
778 col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
781 case COL_PROTOCOL: /* currently done by dissectors */
782 case COL_INFO: /* currently done by dissectors */
785 case COL_PACKET_LENGTH:
786 snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
789 case NUM_COL_FMTS: /* keep compiler happy - shouldn't get here */
796 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
801 proto_tree *protocol_tree;
803 fdata->num = cf->count;
805 /* If we don't have the time stamp of the first packet in the
806 capture, it's because this is the first packet. Save the time
807 stamp of this packet as the time stamp of the first packet. */
808 if (!firstsec && !firstusec) {
809 firstsec = fdata->abs_secs;
810 firstusec = fdata->abs_usecs;
813 /* Get the time elapsed between the first packet and this packet. */
814 cf->esec = fdata->abs_secs - firstsec;
815 if (firstusec <= fdata->abs_usecs) {
816 cf->eusec = fdata->abs_usecs - firstusec;
818 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
822 fdata->cinfo = &cf->cinfo;
823 for (i = 0; i < fdata->cinfo->num_cols; i++) {
824 fdata->cinfo->col_data[i][0] = '\0';
827 /* Apply the filters */
828 if (cf->dfcode != NULL ||
829 CFILTERS_CONTAINS_FILTER(cf)) {
830 protocol_tree = proto_tree_create_root();
831 dissect_packet(buf, fdata, protocol_tree);
832 if (cf->dfcode != NULL)
833 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
835 fdata->passed_dfilter = TRUE;
836 /* Apply color filters. */
838 for(crow = 0; cf->colors->num_of_filters &&
839 crow < cf->colors->num_of_filters; crow++) {
841 if(color_filter(cf,crow)->c_colorfilter == NULL) {
844 if(dfilter_apply(color_filter(cf,crow)->c_colorfilter, protocol_tree,
851 proto_tree_free(protocol_tree);
854 dissect_packet(buf, fdata, NULL);
855 fdata->passed_dfilter = TRUE;
858 if (fdata->passed_dfilter) {
859 /* If we don't have the time stamp of the previous displayed packet,
860 it's because this is the first displayed packet. Save the time
861 stamp of this packet as the time stamp of the previous displayed
863 if (!prevsec && !prevusec) {
864 prevsec = fdata->abs_secs;
865 prevusec = fdata->abs_usecs;
868 /* Get the time elapsed between the first packet and this packet. */
869 fdata->rel_secs = cf->esec;
870 fdata->rel_usecs = cf->eusec;
872 /* Get the time elapsed between the previous displayed packet and
874 fdata->del_secs = fdata->abs_secs - prevsec;
875 if (prevusec <= fdata->abs_usecs) {
876 fdata->del_usecs = fdata->abs_usecs - prevusec;
878 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
881 prevsec = fdata->abs_secs;
882 prevusec = fdata->abs_usecs;
884 fill_in_columns(fdata);
886 row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
889 if (cf->colors->color_filters && (color != -1)){
890 gtk_clist_set_background(GTK_CLIST(packet_list), row,
891 &(color_filter(cf,color)->bg_color));
892 gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
893 &(color_filter(cf,color)->fg_color));
895 gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
896 gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
899 /* If this was the selected packet, remember the row it's in, so
900 we can re-select it. ("selected_packet" is 0-origin, as it's
901 a GList index; "num", however, is 1-origin.) */
902 if (cf->selected_packet == fdata->num - 1)
903 cf->selected_row = row;
905 fdata->row = -1; /* not in the display */
910 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
913 capture_file *cf = (capture_file *) user;
915 proto_tree *protocol_tree;
916 frame_data *plist_end;
920 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
921 when we update it, we have to run the GTK+ main loop to get it
922 to repaint what's pending, and doing so may involve an "ioctl()"
923 to see if there's any pending input from an X server, and doing
924 that for every packet can be costly, especially on a big file.
926 Do so only if we were told to do so; when reading a capture file
927 being updated by a live capture, we don't do so (as we're not
928 "done" until the capture stops, so we don't know how close to
931 if (cf->update_progbar && offset >= cf->progbar_nextstep) {
932 file_pos = lseek(cf->filed, 0, SEEK_CUR);
933 prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
934 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
935 cf->progbar_nextstep += cf->progbar_quantum;
936 while (gtk_events_pending())
937 gtk_main_iteration();
940 /* Allocate the next list entry, and add it to the list. */
941 fdata = (frame_data *) g_malloc(sizeof(frame_data));
944 fdata->pkt_len = phdr->len;
945 fdata->cap_len = phdr->caplen;
946 fdata->file_off = offset;
947 fdata->lnk_t = phdr->pkt_encap;
948 fdata->abs_secs = phdr->ts.tv_sec;
949 fdata->abs_usecs = phdr->ts.tv_usec;
950 fdata->pseudo_header = phdr->pseudo_header;
955 protocol_tree = proto_tree_create_root();
956 dissect_packet(buf, fdata, protocol_tree);
957 passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
958 proto_tree_free(protocol_tree);
961 plist_end = cf->plist_end;
962 if (plist_end != NULL)
963 plist_end->next = fdata;
966 cf->plist_end = fdata;
969 add_packet_to_packet_list(fdata, cf, buf);
975 filter_packets(capture_file *cf, gchar *dftext)
979 if (dftext == NULL) {
980 /* The new filter is an empty filter (i.e., display all packets). */
984 * We have a filter; try to compile it.
986 if (dfilter_compile(dftext, &dfcode) != 0) {
987 /* The attempt failed; report an error. */
988 simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
993 if (dfcode == NULL) {
994 /* Yes - free the filter text, and set it to null. */
1000 /* We have a valid filter. Replace the current filter. */
1001 if (cf->dfilter != NULL)
1002 g_free(cf->dfilter);
1003 cf->dfilter = dftext;
1004 if (cf->dfcode != NULL)
1005 dfilter_destroy(cf->dfcode);
1006 cf->dfcode = dfcode;
1008 /* Now go through the list of packets we've read from the capture file,
1009 applying the current display filter, and, if the packet passes the
1010 display filter, add it to the summary display, appropriately
1011 colored. (That's how we colorize the display - it's like filtering
1012 the display, only we don't install a new filter.) */
1013 colorize_packets(cf);
1017 colorize_packets(capture_file *cf)
1020 guint32 progbar_quantum;
1021 guint32 progbar_nextstep;
1023 gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1025 /* Freeze the packet list while we redo it, so we don't get any
1026 screen updates while it happens. */
1027 gtk_clist_freeze(GTK_CLIST(packet_list));
1030 gtk_clist_clear(GTK_CLIST(packet_list));
1032 /* If a packet was selected, we don't know yet what row, if any, it'll
1034 cf->selected_row = -1;
1036 /* Iterate through the list of packets, calling a routine
1037 to run the filter on the packet, see if it matches, and
1038 put it in the display list if so. */
1043 cf->unfiltered_count = cf->count;
1046 proto_tree_is_visible = FALSE;
1048 /* Update the progress bar when it gets to this value. */
1049 progbar_nextstep = 0;
1050 /* When we reach the value that triggers a progress bar update,
1051 bump that value by this amount. */
1052 progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1053 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1055 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1056 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1057 when we update it, we have to run the GTK+ main loop to get it
1058 to repaint what's pending, and doing so may involve an "ioctl()"
1059 to see if there's any pending input from an X server, and doing
1060 that for every packet can be costly, especially on a big file. */
1061 if (cf->count >= progbar_nextstep) {
1062 /* let's not divide by zero. I should never be started
1063 * with unfiltered_count == 0, so let's assert that
1065 g_assert(cf->unfiltered_count > 0);
1067 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1068 (gfloat) cf->count / cf->unfiltered_count);
1070 progbar_nextstep += progbar_quantum;
1071 while (gtk_events_pending())
1072 gtk_main_iteration();
1077 wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1079 add_packet_to_packet_list(fd, cf, cf->pd);
1082 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1084 if (cf->selected_row != -1) {
1085 /* We had a selected packet and it passed the filter. */
1086 gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
1088 /* If we had one, it didn't pass the filter. */
1089 unselect_packet(cf);
1092 /* Unfreeze the packet list. */
1093 gtk_clist_thaw(GTK_CLIST(packet_list));
1097 print_packets(capture_file *cf, print_args_t *print_args)
1101 guint32 progbar_quantum;
1102 guint32 progbar_nextstep;
1104 proto_tree *protocol_tree;
1105 gint *col_widths = NULL;
1107 gboolean print_separator;
1109 cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1110 if (cf->print_fh == NULL)
1111 return FALSE; /* attempt to open destination failed */
1113 /* XXX - printing multiple frames in PostScript looks as if it's
1114 tricky - you have to deal with page boundaries, I think -
1115 and I'll have to spend some time learning enough about
1116 PostScript to figure it out, so, for now, we only print
1117 multiple frames as text. */
1119 print_preamble(cf->print_fh);
1122 if (print_args->print_summary) {
1123 /* We're printing packet summaries.
1125 Find the widths for each of the columns - maximum of the
1126 width of the title and the width of the data - and print
1127 the column titles. */
1128 col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1129 for (i = 0; i < cf->cinfo.num_cols; i++) {
1130 /* Don't pad the last column. */
1131 if (i == cf->cinfo.num_cols - 1)
1134 col_widths[i] = strlen(cf->cinfo.col_title[i]);
1135 data_width = get_column_char_width(get_column_format(i));
1136 if (data_width > col_widths[i])
1137 col_widths[i] = data_width;
1140 /* Right-justify the packet number column. */
1141 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1142 fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1144 fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1145 if (i == cf->cinfo.num_cols - 1)
1146 fputc('\n', cf->print_fh);
1148 fputc(' ', cf->print_fh);
1152 print_separator = FALSE;
1153 proto_tree_is_visible = TRUE;
1155 /* Update the progress bar when it gets to this value. */
1156 progbar_nextstep = 0;
1157 /* When we reach the value that triggers a progress bar update,
1158 bump that value by this amount. */
1159 progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1160 /* Count of packets we've looked at. */
1163 /* Iterate through the list of packets, printing the packets that
1164 were selected by the current display filter. */
1165 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1166 /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1167 when we update it, we have to run the GTK+ main loop to get it
1168 to repaint what's pending, and doing so may involve an "ioctl()"
1169 to see if there's any pending input from an X server, and doing
1170 that for every packet can be costly, especially on a big file. */
1171 if (count >= progbar_nextstep) {
1172 /* let's not divide by zero. I should never be started
1173 * with unfiltered_count == 0, so let's assert that
1175 g_assert(cf->unfiltered_count > 0);
1177 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1178 (gfloat) count / cf->unfiltered_count);
1179 progbar_nextstep += progbar_quantum;
1180 while (gtk_events_pending())
1181 gtk_main_iteration();
1185 if (fd->passed_dfilter) {
1186 wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1187 if (print_args->print_summary) {
1188 /* Fill in the column information, but don't bother creating
1189 the logical protocol tree. */
1190 fd->cinfo = &cf->cinfo;
1191 for (i = 0; i < fd->cinfo->num_cols; i++) {
1192 fd->cinfo->col_data[i][0] = '\0';
1194 dissect_packet(cf->pd, fd, NULL);
1195 fill_in_columns(fd);
1196 for (i = 0; i < cf->cinfo.num_cols; i++) {
1197 /* Right-justify the packet number column. */
1198 if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1199 fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1201 fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1202 if (i == cf->cinfo.num_cols - 1)
1203 fputc('\n', cf->print_fh);
1205 fputc(' ', cf->print_fh);
1208 if (print_separator)
1209 fputc('\n', cf->print_fh);
1211 /* Create the logical protocol tree. */
1212 protocol_tree = proto_tree_create_root();
1213 dissect_packet(cf->pd, fd, protocol_tree);
1215 /* Print the information in that tree. */
1216 proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1217 cf->pd, fd, cf->print_fh);
1219 proto_tree_free(protocol_tree);
1221 if (print_args->print_hex) {
1222 /* Print the full packet data as hex. */
1223 print_hex_data(cf->print_fh, cf->pd, fd->cap_len);
1226 /* Print a blank line if we print anything after this. */
1227 print_separator = TRUE;
1232 if (col_widths != NULL)
1236 print_finale(cf->print_fh);
1239 close_print_dest(print_args->to_file, cf->print_fh);
1241 gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1243 cf->print_fh = NULL;
1247 /* Scan through the packet list and change all columns that use the
1248 "command-line-specified" time stamp format to use the current
1249 value of that format. */
1251 change_time_formats(capture_file *cf)
1257 /* Freeze the packet list while we redo it, so we don't get any
1258 screen updates while it happens. */
1261 /* Iterate through the list of packets, checking whether the packet
1262 is in a row of the summary list and, if so, whether there are
1263 any columns that show the time in the "command-line-specified"
1264 format and, if so, update that row. */
1265 for (fd = cf->plist; fd != NULL; fd = fd->next) {
1266 if (fd->row != -1) {
1267 /* This packet is in the summary list, on row "fd->row". */
1269 /* XXX - there really should be a way of checking "cf->cinfo" for this;
1270 the answer isn't going to change from packet to packet, so we should
1271 simply skip all the "change_time_formats()" work if we're not
1272 changing anything. */
1273 fd->cinfo = &cf->cinfo;
1274 if (check_col(fd, COL_CLS_TIME)) {
1275 /* There are columns that show the time in the "command-line-specified"
1276 format; update them. */
1277 for (i = 0; i < cf->cinfo.num_cols; i++) {
1278 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1279 /* This is one of the columns that shows the time in
1280 "command-line-specified" format; update it. */
1281 cf->cinfo.col_data[i][0] = '\0';
1282 col_set_cls_time(fd, i);
1283 gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
1284 cf->cinfo.col_data[i]);
1291 /* Set the column widths of those columns that show the time in
1292 "command-line-specified" format. */
1293 pl_style = gtk_widget_get_style(packet_list);
1294 for (i = 0; i < cf->cinfo.num_cols; i++) {
1295 if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1296 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1297 get_column_width(COL_CLS_TIME, pl_style->font));
1301 /* Unfreeze the packet list. */
1306 clear_tree_and_hex_views(void)
1309 GtkWidget *tmp_item;
1311 /* Clear the hex dump. */
1312 gtk_text_freeze(GTK_TEXT(byte_view));
1313 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1314 gtk_text_forward_delete(GTK_TEXT(byte_view),
1315 gtk_text_get_length(GTK_TEXT(byte_view)));
1316 gtk_text_thaw(GTK_TEXT(byte_view));
1318 /* Deselect any selected tree item. gtktree.c should
1319 * do this when we clear_items, but it doesn't. I copied
1320 * this while() loop from gtktree.c, gtk_real_tree_select_child()
1322 if (GTK_TREE(tree_view)->root_tree) {
1323 selection = GTK_TREE(tree_view)->root_tree->selection;
1325 tmp_item = selection->data;
1326 gtk_tree_item_deselect(GTK_TREE_ITEM(tmp_item));
1327 gtk_widget_unref(tmp_item);
1328 selection = selection->next;
1330 g_list_free(GTK_TREE(tree_view)->root_tree->selection);
1331 GTK_TREE(tree_view)->root_tree->selection = NULL;
1334 /* Clear the protocol tree view. The length arg of -1
1335 * means to clear all items up to the end. */
1336 gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
1340 /* Select the packet on a given row. */
1342 select_packet(capture_file *cf, int row)
1347 /* Clear out whatever's currently in the hex dump. */
1348 gtk_text_freeze(GTK_TEXT(byte_view));
1349 gtk_text_set_point(GTK_TEXT(byte_view), 0);
1350 gtk_text_forward_delete(GTK_TEXT(byte_view),
1351 gtk_text_get_length(GTK_TEXT(byte_view)));
1353 /* Search through the list of frames to see which one is in
1355 for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1360 g_assert(fd != NULL);
1364 /* Remember the ordinal number of that frame. */
1365 cf->selected_packet = i;
1367 /* Get the data in that frame. */
1368 wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1370 /* Create the logical protocol tree. */
1371 if (cf->protocol_tree)
1372 proto_tree_free(cf->protocol_tree);
1373 cf->protocol_tree = proto_tree_create_root();
1374 proto_tree_is_visible = TRUE;
1375 dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
1377 /* Display the GUI protocol tree and hex dump. */
1378 clear_tree_and_hex_views();
1379 proto_tree_draw(cf->protocol_tree, tree_view);
1380 packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
1381 gtk_text_thaw(GTK_TEXT(byte_view));
1383 /* A packet is selected, so "File/Print Packet" has something to print. */
1384 set_menu_sensitivity("/File/Print Packet", TRUE);
1385 set_menu_sensitivity("/Display/Collapse All", TRUE);
1386 set_menu_sensitivity("/Display/Expand All", TRUE);
1389 /* Unselect the selected packet, if any. */
1391 unselect_packet(capture_file *cf)
1393 cf->selected_packet = -1; /* nothing there to be selected */
1394 cf->selected_row = -1;
1396 /* Destroy the protocol tree for that packet. */
1397 if (cf->protocol_tree != NULL) {
1398 proto_tree_free(cf->protocol_tree);
1399 cf->protocol_tree = NULL;
1402 /* Clear out the display of that packet. */
1403 clear_tree_and_hex_views();
1405 /* No packet is selected, so "File/Print Packet" has nothing to print. */
1406 set_menu_sensitivity("/File/Print Packet", FALSE);
1407 set_menu_sensitivity("/Display/Collapse All", FALSE);
1408 set_menu_sensitivity("/Display/Expand All", FALSE);
1412 freeze_clist(capture_file *cf)
1416 /* Make the column sizes static, so they don't adjust while
1417 we're reading the capture file (freezing the clist doesn't
1418 seem to suffice). */
1419 for (i = 0; i < cf->cinfo.num_cols; i++)
1420 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1421 gtk_clist_freeze(GTK_CLIST(packet_list));
1425 thaw_clist(capture_file *cf)
1429 for (i = 0; i < cf->cinfo.num_cols; i++) {
1430 if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1431 /* Set this column's width to the appropriate value. */
1432 gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1433 cf->cinfo.col_width[i]);
1435 /* Make this column's size dynamic, so that it adjusts to the
1436 appropriate size. */
1437 gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1440 gtk_clist_thaw(GTK_CLIST(packet_list));
1442 /* Hopefully, the columns have now gotten their appropriate sizes;
1443 make them resizeable - a column that auto-resizes cannot be
1444 resized by the user, and *vice versa*. */
1445 for (i = 0; i < cf->cinfo.num_cols; i++)
1446 gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1449 /* Tries to mv a file. If unsuccessful, tries to cp the file.
1450 * Returns 0 on failure to do either, 1 on success of either
1453 file_mv(char *from, char *to)
1456 #define COPY_BUFFER_SIZE 8192
1461 /* try a hard link */
1462 retval = link(from, to);
1467 retval = file_cp(from, to);
1480 * Returns 0 on failure to do either, 1 on success of either
1483 file_cp(char *from, char *to)
1486 #define COPY_BUFFER_SIZE 8192
1488 int from_fd, to_fd, nread, nwritten;
1491 buffer = g_malloc(COPY_BUFFER_SIZE);
1493 from_fd = open(from, O_RDONLY);
1495 simple_dialog(ESD_TYPE_WARN, NULL,
1496 file_open_error_message(errno, TRUE), from);
1500 to_fd = creat(to, 0644);
1502 simple_dialog(ESD_TYPE_WARN, NULL,
1503 file_open_error_message(errno, TRUE), to);
1508 while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
1509 nwritten = write(to_fd, buffer, nread);
1510 if (nwritten < nread) {
1512 simple_dialog(ESD_TYPE_WARN, NULL,
1513 file_write_error_message(errno), to);
1515 simple_dialog(ESD_TYPE_WARN, NULL,
1516 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
1517 to, nread, nwritten);
1525 simple_dialog(ESD_TYPE_WARN, NULL,
1526 file_read_error_message(errno), from);
1538 file_open_error_message(int err, int for_writing)
1541 static char errmsg_errno[1024+1];
1545 case WTAP_ERR_NOT_REGULAR_FILE:
1546 errmsg = "The file \"%s\" is invalid.";
1549 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1550 case WTAP_ERR_UNSUPPORTED:
1551 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1554 case WTAP_ERR_BAD_RECORD:
1555 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1558 case WTAP_ERR_CANT_OPEN:
1560 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1562 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1565 case WTAP_ERR_SHORT_READ:
1566 errmsg = "The file \"%s\" appears to have been cut short"
1567 " in the middle of a packet.";
1572 errmsg = "The path to the file \"%s\" does not exist.";
1574 errmsg = "The file \"%s\" does not exist.";
1579 errmsg = "You do not have permission to create or write to the file \"%s\".";
1581 errmsg = "You do not have permission to read the file \"%s\".";
1585 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1586 wtap_strerror(err));
1587 errmsg = errmsg_errno;
1594 file_read_error_message(int err)
1596 static char errmsg_errno[1024+1];
1598 sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1599 wtap_strerror(err));
1600 return errmsg_errno;
1604 file_write_error_message(int err)
1607 static char errmsg_errno[1024+1];
1612 errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1617 errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1622 sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1623 wtap_strerror(err));
1624 errmsg = errmsg_errno;