3 * $Id: tethereal.c,v 1.34 2000/07/05 09:40:43 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
7 * Copyright 1998 Gerald Combs
9 * Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
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.
41 #include <sys/types.h>
46 #ifdef NEED_SNPRINTF_H
52 # include "snprintf.h"
55 #if defined(HAVE_UCD_SNMP_SNMP_H)
56 #ifdef HAVE_UCD_SNMP_VERSION_H
57 #include <ucd-snmp/version.h>
58 #endif /* HAVE_UCD_SNMP_VERSION_H */
59 #elif defined(HAVE_SNMP_SNMP_H)
60 #ifdef HAVE_SNMP_VERSION_H
61 #include <snmp/version.h>
62 #endif /* HAVE_SNMP_VERSION_H */
65 #ifdef NEED_STRERROR_H
74 #include "timestamp.h"
84 #include "conversation.h"
87 static guint32 firstsec, firstusec;
88 static guint32 prevsec, prevusec;
89 static gchar comp_info_str[256];
90 static gboolean verbose;
91 static gboolean print_hex;
94 typedef struct _loop_data {
102 static int capture(int, int);
103 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
105 static void capture_cleanup(int);
113 static int load_cap_file(capture_file *, int);
114 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
115 union wtap_pseudo_header *, const u_char *);
116 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
117 union wtap_pseudo_header *, const u_char *);
118 static gchar *col_info(frame_data *, gint);
122 FILE *data_out_file = NULL;
123 guint main_ctx, file_ctx;
124 ts_type timestamp_type = RELATIVE;
131 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
132 VERSION, comp_info_str);
134 fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <capture filter> ]\n", PACKAGE);
135 fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
136 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
137 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
139 fprintf(stderr, "t%s [ -vVh ] [ -D ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
140 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
141 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
143 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
144 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
145 if (wtap_dump_can_open(i))
146 fprintf(stderr, "\t%s - %s\n",
147 wtap_file_type_short_string(i), wtap_file_type_string(i));
149 fprintf(stderr, "\tdefault is libpcap\n");
153 main(int argc, char *argv[])
157 gboolean arg_error = FALSE;
160 char pcap_version[] = "0.4a6";
162 extern char pcap_version[];
165 char *gpf_path, *pf_path;
166 int gpf_open_errno, pf_open_errno;
169 gboolean capture_filter_specified = FALSE;
170 int packet_count = 0;
172 gchar err_str[PCAP_ERRBUF_SIZE];
174 gboolean capture_option_specified = FALSE;
176 int out_file_type = WTAP_FILE_PCAP;
177 gchar *cf_name = NULL, *rfilter = NULL;
178 dfilter *rfcode = NULL;
181 /* Register all dissectors; we must do this before checking for the
182 "-G" flag, as the "-G" flag dumps a list of fields registered
183 by the dissectors, and we must do it before we read the preferences,
184 in case any dissectors register preferences. */
187 /* Now register the preferences for any non-dissector modules.
188 We must do that before we read the preferences as well. */
189 prefs_register_modules();
191 /* If invoked with the "-G" flag, we dump out a glossary of
192 display filter symbols.
194 We do this here to mirror what happens in the GTK+ version, although
195 it's not necessary here. */
196 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
197 proto_registrar_dump();
201 /* Set the C-language locale to the native environment. */
202 setlocale(LC_ALL, "");
204 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
205 if (gpf_path != NULL) {
206 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
207 strerror(gpf_open_errno));
209 if (pf_path != NULL) {
210 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
211 strerror(pf_open_errno));
214 /* Initialize the capture file struct */
216 cfile.plist_end = NULL;
218 cfile.filename = NULL;
219 cfile.user_saved = FALSE;
220 cfile.is_tempfile = FALSE;
222 cfile.dfilter = NULL;
225 cfile.cfilter = g_strdup("");
228 cfile.save_file = NULL;
229 cfile.save_file_fd = -1;
230 cfile.snap = WTAP_MAX_PACKET_SIZE;
232 cfile.cinfo.num_cols = prefs->num_cols;
233 cfile.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cfile.cinfo.num_cols);
234 cfile.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cfile.cinfo.num_cols);
235 cfile.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cfile.cinfo.num_cols);
236 cfile.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cfile.cinfo.num_cols);
237 cfile.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cfile.cinfo.num_cols);
239 /* Assemble the compile-time options */
240 snprintf(comp_info_str, 256,
241 #ifdef GTK_MAJOR_VERSION
242 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
245 "GTK+ (version unknown), %s%s, %s%s, %s%s",
249 "with libpcap ", pcap_version,
251 "without libpcap", "",
256 "with libz ", ZLIB_VERSION,
257 #else /* ZLIB_VERSION */
258 "with libz ", "(version unknown)",
259 #endif /* ZLIB_VERSION */
260 #else /* HAVE_LIBZ */
262 #endif /* HAVE_LIBZ */
264 /* Oh, this is pretty */
265 #if defined(HAVE_UCD_SNMP_SNMP_H)
266 #ifdef HAVE_UCD_SNMP_VERSION_H
267 "with UCD SNMP ", VersionInfo
268 #else /* HAVE_UCD_SNMP_VERSION_H */
269 "with UCD SNMP ", "(version unknown)"
270 #endif /* HAVE_UCD_SNMP_VERSION_H */
271 #elif defined(HAVE_SNMP_SNMP_H)
272 #ifdef HAVE_SNMP_VERSION_H
273 "with CMU SNMP ", snmp_Version()
274 #else /* HAVE_SNMP_VERSION_H */
275 "with CMU SNMP ", "(version unknown)"
276 #endif /* HAVE_SNMP_VERSION_H */
282 /* Now get our args */
283 while ((opt = getopt(argc, argv, "c:Df:F:hi:no:r:R:s:t:vw:Vx")) != EOF) {
285 case 'c': /* Capture xxx packets */
287 packet_count = atoi(optarg);
289 capture_option_specified = TRUE;
293 case 'D': /* Turn off DSCP printing */
294 g_ip_dscp_actif = FALSE;
298 capture_filter_specified = TRUE;
299 cfile.cfilter = g_strdup(optarg);
301 capture_option_specified = TRUE;
306 out_file_type = wtap_short_string_to_file_type(optarg);
307 if (out_file_type < 0) {
308 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
313 case 'h': /* Print help and exit */
317 case 'i': /* Use interface xxx */
319 cfile.iface = g_strdup(optarg);
321 capture_option_specified = TRUE;
325 case 'n': /* No name resolution */
326 g_resolving_actif = 0;
328 case 'o': /* Override preference from command line */
329 switch (prefs_set_pref(optarg)) {
331 case PREFS_SET_SYNTAX_ERR:
332 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
336 case PREFS_SET_NO_SUCH_PREF:
337 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
343 case 'r': /* Read capture file xxx */
344 cf_name = g_strdup(optarg);
346 case 'R': /* Read file filter */
349 case 's': /* Set the snapshot (capture) length */
351 cfile.snap = atoi(optarg);
353 capture_option_specified = TRUE;
357 case 't': /* Time stamp type */
358 if (strcmp(optarg, "r") == 0)
359 timestamp_type = RELATIVE;
360 else if (strcmp(optarg, "a") == 0)
361 timestamp_type = ABSOLUTE;
362 else if (strcmp(optarg, "d") == 0)
363 timestamp_type = DELTA;
365 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
367 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
368 fprintf(stderr, "or \"d\" for delta.\n");
372 case 'v': /* Show version and exit */
373 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
376 case 'w': /* Write to capture file xxx */
377 cfile.save_file = g_strdup(optarg);
379 case 'V': /* Verbose */
382 case 'x': /* Print packet data in hex (and ASCII) */
388 /* If no capture filter or read filter has been specified, and there are
389 still command-line arguments, treat them as the tokens of a capture
390 filter (if no "-r" flag was specified) or a read filter (if a "-r"
391 flag was specified. */
393 if (cf_name != NULL) {
394 if (rfilter != NULL) {
396 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
399 rfilter = get_args_as_string(argc, argv, optind);
402 if (capture_filter_specified) {
404 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
407 cfile.cfilter = get_args_as_string(argc, argv, optind);
409 capture_option_specified = TRUE;
415 if (capture_option_specified)
416 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
421 /* Build the column format array */
422 for (i = 0; i < cfile.cinfo.num_cols; i++) {
423 cfile.cinfo.col_fmt[i] = get_column_format(i);
424 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
425 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
427 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
428 if (cfile.cinfo.col_fmt[i] == COL_INFO)
429 cfile.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
431 cfile.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
435 cfile.snap = WTAP_MAX_PACKET_SIZE;
436 else if (cfile.snap < MIN_PACKET_SIZE)
437 cfile.snap = MIN_PACKET_SIZE;
439 if (rfilter != NULL) {
440 if (dfilter_compile(rfilter, &rfcode) != 0) {
441 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
446 cfile.rfcode = rfcode;
448 err = open_cap_file(cf_name, FALSE, &cfile);
453 err = load_cap_file(&cfile, out_file_type);
460 /* No capture file specified, so we're supposed to do a live capture;
461 do we have support for live captures? */
463 /* Yes; did the user specify an interface to use? */
464 if (cfile.iface == NULL) {
465 /* No - pick the first one from the list of interfaces. */
466 if_list = get_interface_list(&err, err_str);
467 if (if_list == NULL) {
470 case CANT_GET_INTERFACE_LIST:
471 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
475 case NO_INTERFACES_FOUND:
476 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
481 cfile.iface = g_strdup(if_list->data); /* first interface */
482 free_interface_list(if_list);
484 capture(packet_count, out_file_type);
487 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
498 /* Do the low-level work of a capture.
499 Returns TRUE if it succeeds, FALSE otherwise. */
501 capture(int packet_count, int out_file_type)
503 gchar err_str[PCAP_ERRBUF_SIZE];
504 bpf_u_int32 netnum, netmask;
505 void (*oldhandler)(int);
509 /* Initialize the table of conversations. */
512 /* Initialize protocol-specific variables */
513 init_all_protocols();
515 ld.linktype = WTAP_ENCAP_UNKNOWN;
518 /* Open the network interface to capture from it. */
519 ld.pch = pcap_open_live(cfile.iface, cfile.snap, 1, 1000, err_str);
521 if (ld.pch == NULL) {
522 /* Well, we couldn't start the capture.
523 If this is a child process that does the capturing in sync
524 mode or fork mode, it shouldn't do any UI stuff until we pop up the
525 capture-progress window, and, since we couldn't start the
526 capture, we haven't popped it up. */
527 snprintf(errmsg, sizeof errmsg,
528 "The capture session could not be initiated (%s).\n"
529 "Please check to make sure you have sufficient permissions, and that\n"
530 "you have the proper interface specified.", err_str);
535 /* A capture filter was specified; set it up. */
536 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
537 snprintf(errmsg, sizeof errmsg,
538 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
541 if (pcap_compile(ld.pch, &cfile.fcode, cfile.cfilter, 1, netmask) < 0) {
542 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
543 pcap_geterr(ld.pch));
546 if (pcap_setfilter(ld.pch, &cfile.fcode) < 0) {
547 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
548 pcap_geterr(ld.pch));
553 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
554 if (cfile.save_file != NULL) {
555 /* Set up to write to the capture file. */
556 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
557 strcpy(errmsg, "The network you're capturing from is of a type"
558 " that Tethereal doesn't support.");
561 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
562 ld.linktype, pcap_snapshot(ld.pch), &err);
564 if (ld.pdh == NULL) {
565 /* We couldn't set up to write to the capture file. */
568 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
569 strcpy(errmsg, "Tethereal does not support writing capture files in that format.");
572 case WTAP_ERR_UNSUPPORTED_ENCAP:
573 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
574 strcpy(errmsg, "Tethereal cannot save this capture in that format.");
577 case WTAP_ERR_CANT_OPEN:
578 strcpy(errmsg, "The file to which the capture would be written"
579 " couldn't be created for some unknown reason.");
582 case WTAP_ERR_SHORT_WRITE:
583 strcpy(errmsg, "A full header couldn't be written to the file"
584 " to which the capture would be written.");
589 sprintf(errmsg, "The file to which the capture would be"
590 " written (\"%s\") could not be opened: Error %d.",
591 cfile.save_file, err);
593 sprintf(errmsg, "The file to which the capture would be"
594 " written (\"%s\") could not be opened: %s.",
595 cfile.save_file, strerror(err));
603 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
605 XXX - deal with signal semantics on various platforms. Or just
606 use "sigaction()" and be done with it? */
607 signal(SIGTERM, capture_cleanup);
608 signal(SIGINT, capture_cleanup);
610 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
611 signal(SIGHUP, oldhandler);
614 /* Let the user know what interface was chosen. */
615 printf("Capturing on %s\n", cfile.iface);
617 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
623 g_free(cfile.save_file);
624 cfile.save_file = NULL;
625 fprintf(stderr, "tethereal: %s\n", errmsg);
633 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
636 struct wtap_pkthdr whdr;
637 loop_data *ld = (loop_data *) user;
640 whdr.ts.tv_sec = phdr->ts.tv_sec;
641 whdr.ts.tv_usec = phdr->ts.tv_usec;
642 whdr.caplen = phdr->caplen;
643 whdr.len = phdr->len;
644 whdr.pkt_encap = ld->linktype;
649 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
651 printf("\r%u ", cfile.count);
654 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
659 capture_cleanup(int signum)
666 wtap_dump_close(ld.pdh, &err);
667 /* XXX - complain if this fails */
670 #endif /* HAVE_LIBPCAP */
673 load_cap_file(capture_file *cf, int out_file_type)
681 linktype = wtap_file_encap(cf->wth);
682 if (cf->save_file != NULL) {
683 /* Set up to write to the capture file. */
684 pdh = wtap_dump_open(cf->save_file, out_file_type,
685 linktype, wtap_snapshot_length(cf->wth), &err);
688 /* We couldn't set up to write to the capture file. */
691 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
693 "tethereal: Capture files can't be written in that format.\n");
696 case WTAP_ERR_UNSUPPORTED_ENCAP:
697 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
699 "tethereal: The capture file being read cannot be written in that format.\n");
702 case WTAP_ERR_CANT_OPEN:
704 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
708 case WTAP_ERR_SHORT_WRITE:
710 "tethereal: A full header couldn't be written to the file \"%s\".\n",
717 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
721 "tethereal: The file \"%s\" could not be opened: %s\n.",
722 cf->save_file, strerror(err));
730 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
735 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
739 /* Print up a message box noting that the read failed somewhere along
743 case WTAP_ERR_UNSUPPORTED_ENCAP:
745 "tethereal: The capture file is for a network type that Tethereal doesn't support.\n");
748 case WTAP_ERR_CANT_READ:
750 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
753 case WTAP_ERR_SHORT_READ:
755 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
758 case WTAP_ERR_BAD_RECORD:
760 "tethereal: The capture file appears to be damaged or corrupt.\n");
765 "tethereal: An error occurred while reading the capture file: %s.\n",
779 fill_in_fdata(frame_data *fdata, capture_file *cf,
780 const struct wtap_pkthdr *phdr,
781 const union wtap_pseudo_header *pseudo_header, int offset)
787 fdata->pkt_len = phdr->len;
788 fdata->cap_len = phdr->caplen;
789 fdata->file_off = offset;
790 fdata->lnk_t = phdr->pkt_encap;
791 fdata->abs_secs = phdr->ts.tv_sec;
792 fdata->abs_usecs = phdr->ts.tv_usec;
793 fdata->flags.encoding = CHAR_ASCII;
794 fdata->flags.visited = 0;
797 fdata->num = cf->count;
799 /* If we don't have the time stamp of the first packet in the
800 capture, it's because this is the first packet. Save the time
801 stamp of this packet as the time stamp of the first packet. */
802 if (!firstsec && !firstusec) {
803 firstsec = fdata->abs_secs;
804 firstusec = fdata->abs_usecs;
807 /* Get the time elapsed between the first packet and this packet. */
808 cf->esec = fdata->abs_secs - firstsec;
809 if (firstusec <= fdata->abs_usecs) {
810 cf->eusec = fdata->abs_usecs - firstusec;
812 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
816 /* If we don't have the time stamp of the previous displayed packet,
817 it's because this is the first displayed packet. Save the time
818 stamp of this packet as the time stamp of the previous displayed
820 if (!prevsec && !prevusec) {
821 prevsec = fdata->abs_secs;
822 prevusec = fdata->abs_usecs;
825 /* Get the time elapsed between the first packet and this packet. */
826 fdata->rel_secs = cf->esec;
827 fdata->rel_usecs = cf->eusec;
829 /* Get the time elapsed between the previous displayed packet and
831 fdata->del_secs = fdata->abs_secs - prevsec;
832 if (prevusec <= fdata->abs_usecs) {
833 fdata->del_usecs = fdata->abs_usecs - prevusec;
835 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
838 prevsec = fdata->abs_secs;
839 prevusec = fdata->abs_usecs;
841 fdata->cinfo = &cf->cinfo;
842 for (i = 0; i < fdata->cinfo->num_cols; i++) {
843 fdata->cinfo->col_data[i][0] = '\0';
848 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
849 union wtap_pseudo_header *pseudo_header, const u_char *buf)
851 cb_args_t *args = (cb_args_t *) user;
852 capture_file *cf = args->cf;
853 wtap_dumper *pdh = args->pdh;
855 proto_tree *protocol_tree;
861 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
862 protocol_tree = proto_tree_create_root();
863 dissect_packet(pseudo_header, buf, &fdata, protocol_tree);
864 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len);
866 protocol_tree = NULL;
870 /* XXX - do something if this fails */
871 wtap_dump(pdh, phdr, pseudo_header, buf, &err);
873 if (protocol_tree != NULL)
874 proto_tree_free(protocol_tree);
878 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
879 union wtap_pseudo_header *pseudo_header, const u_char *buf)
881 cb_args_t *args = (cb_args_t *) user;
882 capture_file *cf = args->cf;
884 proto_tree *protocol_tree;
886 print_args_t print_args;
890 /* The protocol tree will be "visible", i.e., printed, only if we're
891 not printing a summary. */
892 proto_tree_is_visible = verbose;
894 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
897 if (cf->rfcode || verbose)
898 protocol_tree = proto_tree_create_root();
900 protocol_tree = NULL;
901 dissect_packet(pseudo_header, buf, &fdata, protocol_tree);
903 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len);
905 /* The packet passed the read filter. */
907 /* Print the information in the protocol tree. */
908 print_args.to_file = TRUE;
909 print_args.format = PR_FMT_TEXT;
910 print_args.print_summary = FALSE;
911 print_args.print_hex = print_hex;
912 print_args.expand_all = TRUE;
913 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
914 buf, &fdata, stdout);
916 /* "print_hex_data()" will put out a leading blank line, as well
917 as a trailing one; print one here, to separate the packets,
918 only if "print_hex_data()" won't be called. */
922 /* Just fill in the columns. */
923 fill_in_columns(&fdata);
924 if (cf->iface == NULL) {
925 printf("%3s %10s %12s -> %-12s %s %s\n",
926 col_info(&fdata, COL_NUMBER),
927 col_info(&fdata, COL_CLS_TIME),
928 col_info(&fdata, COL_DEF_SRC),
929 col_info(&fdata, COL_DEF_DST),
930 col_info(&fdata, COL_PROTOCOL),
931 col_info(&fdata, COL_INFO));
933 printf("%12s -> %-12s %s %s\n",
934 col_info(&fdata, COL_DEF_SRC),
935 col_info(&fdata, COL_DEF_DST),
936 col_info(&fdata, COL_PROTOCOL),
937 col_info(&fdata, COL_INFO));
941 print_hex_data(stdout, print_args.format, buf,
942 fdata.cap_len, fdata.flags.encoding);
947 if (protocol_tree != NULL)
948 proto_tree_free(protocol_tree);
950 proto_tree_is_visible = FALSE;
954 file_open_error_message(int err, int for_writing)
957 static char errmsg_errno[1024+1];
961 case WTAP_ERR_NOT_REGULAR_FILE:
962 errmsg = "The file \"%s\" is invalid.";
965 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
966 case WTAP_ERR_UNSUPPORTED:
967 /* Seen only when opening a capture file for reading. */
968 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
971 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
972 /* Seen only when opening a capture file for writing. */
973 errmsg = "Tethereal does not support writing capture files in that format.";
976 case WTAP_ERR_UNSUPPORTED_ENCAP:
977 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
979 errmsg = "Tethereal cannot save this capture in that format.";
981 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
984 case WTAP_ERR_BAD_RECORD:
985 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
988 case WTAP_ERR_CANT_OPEN:
990 errmsg = "The file \"%s\" could not be created for some unknown reason.";
992 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
995 case WTAP_ERR_SHORT_READ:
996 errmsg = "The file \"%s\" appears to have been cut short"
997 " in the middle of a packet.";
1000 case WTAP_ERR_SHORT_WRITE:
1001 errmsg = "A full header couldn't be written to the file \"%s\".";
1006 errmsg = "The path to the file \"%s\" does not exist.";
1008 errmsg = "The file \"%s\" does not exist.";
1013 errmsg = "You do not have permission to create or write to the file \"%s\".";
1015 errmsg = "You do not have permission to read the file \"%s\".";
1019 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1020 wtap_strerror(err));
1021 errmsg = errmsg_errno;
1028 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1034 struct stat cf_stat;
1035 char err_msg[2048+1];
1037 wth = wtap_open_offline(fname, &err, FALSE);
1041 /* Find the size of the file. */
1042 fh = wtap_file(wth);
1044 if (fstat(fd, &cf_stat) < 0) {
1050 /* The open succeeded. Fill in the information for this file. */
1052 /* Initialize the table of conversations. */
1053 conversation_init();
1055 /* Initialize protocol-specific variables */
1056 init_all_protocols();
1060 cf->f_len = cf_stat.st_size;
1062 /* Set the file name because we need it to set the follow stream filter.
1063 XXX - is that still true? We need it for other reasons, though,
1065 cf->filename = g_strdup(fname);
1067 /* Indicate whether it's a permanent or temporary file. */
1068 cf->is_tempfile = is_tempfile;
1070 /* If it's a temporary capture buffer file, mark it as not saved. */
1071 cf->user_saved = !is_tempfile;
1073 cf->cd_t = wtap_file_type(cf->wth);
1078 cf->snap = wtap_snapshot_length(cf->wth);
1079 cf->progbar_quantum = 0;
1080 cf->progbar_nextstep = 0;
1081 firstsec = 0, firstusec = 0;
1082 prevsec = 0, prevusec = 0;
1087 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1088 fprintf(stderr, "tethereal: %s\n", err_msg);
1092 /* Get the text in a given column */
1094 col_info(frame_data *fd, gint el) {
1098 for (i = 0; i < fd->cinfo->num_cols; i++) {
1099 if (fd->cinfo->fmt_matx[i][el])
1100 return fd->cinfo->col_data[i];