3 * $Id: tethereal.c,v 1.64 2001/02/01 20:21:13 gram 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.
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
46 #ifdef HAVE_SYS_STAT_H
60 #ifdef NEED_SNPRINTF_H
61 # include "snprintf.h"
64 #if defined(HAVE_UCD_SNMP_SNMP_H)
65 #ifdef HAVE_UCD_SNMP_VERSION_H
66 #include <ucd-snmp/version.h>
67 #endif /* HAVE_UCD_SNMP_VERSION_H */
68 #elif defined(HAVE_SNMP_SNMP_H)
69 #ifdef HAVE_SNMP_VERSION_H
70 #include <snmp/version.h>
71 #endif /* HAVE_SNMP_VERSION_H */
74 #ifdef NEED_STRERROR_H
86 #include "timestamp.h"
94 #include "conversation.h"
97 static guint32 firstsec, firstusec;
98 static guint32 prevsec, prevusec;
99 static gchar comp_info_str[256];
100 static gboolean verbose;
101 static gboolean print_hex;
104 typedef struct _loop_data {
112 static int capture(int, int);
113 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
115 static void capture_cleanup(int);
123 static int load_cap_file(capture_file *, int);
124 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
125 union wtap_pseudo_header *, const u_char *);
126 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
127 union wtap_pseudo_header *, const u_char *);
131 FILE *data_out_file = NULL;
132 guint main_ctx, file_ctx;
133 ts_type timestamp_type = RELATIVE;
135 static int promisc_mode = TRUE;
143 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
144 VERSION, comp_info_str);
146 fprintf(stderr, "t%s [ -vVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
147 fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
148 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
149 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
151 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
152 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
153 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
155 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
156 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
157 if (wtap_dump_can_open(i))
158 fprintf(stderr, "\t%s - %s\n",
159 wtap_file_type_short_string(i), wtap_file_type_string(i));
161 fprintf(stderr, "\tdefault is libpcap\n");
165 main(int argc, char *argv[])
169 gboolean arg_error = FALSE;
172 char pcap_version[] = "0.4a6";
174 extern char pcap_version[];
182 char *gpf_path, *pf_path;
183 int gpf_open_errno, pf_open_errno;
186 gboolean capture_filter_specified = FALSE;
187 int packet_count = 0;
189 gchar err_str[PCAP_ERRBUF_SIZE];
191 gboolean capture_option_specified = FALSE;
193 int out_file_type = WTAP_FILE_PCAP;
194 gchar *cf_name = NULL, *rfilter = NULL;
195 dfilter_t *rfcode = NULL;
198 /* Register all dissectors; we must do this before checking for the
199 "-G" flag, as the "-G" flag dumps a list of fields registered
200 by the dissectors, and we must do it before we read the preferences,
201 in case any dissectors register preferences. */
202 epan_init(PLUGIN_DIR);
204 /* Now register the preferences for any non-dissector modules.
205 We must do that before we read the preferences as well. */
206 prefs_register_modules();
208 /* If invoked with the "-G" flag, we dump out a glossary of
209 display filter symbols.
211 We do this here to mirror what happens in the GTK+ version, although
212 it's not necessary here. */
213 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
214 proto_registrar_dump();
218 /* Set the C-language locale to the native environment. */
219 setlocale(LC_ALL, "");
221 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
222 if (gpf_path != NULL) {
223 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
224 strerror(gpf_open_errno));
226 if (pf_path != NULL) {
227 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
228 strerror(pf_open_errno));
231 /* Initialize the capture file struct */
233 cfile.plist_end = NULL;
235 cfile.filename = NULL;
236 cfile.user_saved = FALSE;
237 cfile.is_tempfile = FALSE;
239 cfile.dfilter = NULL;
242 cfile.cfilter = g_strdup("");
245 cfile.save_file = NULL;
246 cfile.save_file_fd = -1;
247 cfile.snap = WTAP_MAX_PACKET_SIZE;
249 col_init(&cfile.cinfo, prefs->num_cols);
251 /* Assemble the compile-time options */
252 snprintf(comp_info_str, 256,
253 #ifdef GTK_MAJOR_VERSION
254 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
257 "GTK+ (version unknown), %s%s, %s%s, %s%s",
261 "with libpcap ", pcap_version,
263 "without libpcap", "",
268 "with libz ", ZLIB_VERSION,
269 #else /* ZLIB_VERSION */
270 "with libz ", "(version unknown)",
271 #endif /* ZLIB_VERSION */
272 #else /* HAVE_LIBZ */
274 #endif /* HAVE_LIBZ */
276 /* Oh, this is pretty */
277 #if defined(HAVE_UCD_SNMP_SNMP_H)
278 #ifdef HAVE_UCD_SNMP_VERSION_H
279 "with UCD SNMP ", VersionInfo
280 #else /* HAVE_UCD_SNMP_VERSION_H */
281 "with UCD SNMP ", "(version unknown)"
282 #endif /* HAVE_UCD_SNMP_VERSION_H */
283 #elif defined(HAVE_SNMP_SNMP_H)
284 #ifdef HAVE_SNMP_VERSION_H
285 "with CMU SNMP ", snmp_Version()
286 #else /* HAVE_SNMP_VERSION_H */
287 "with CMU SNMP ", "(version unknown)"
288 #endif /* HAVE_SNMP_VERSION_H */
294 /* Now get our args */
295 while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
297 case 'c': /* Capture xxx packets */
299 packet_count = atoi(optarg);
301 capture_option_specified = TRUE;
307 capture_filter_specified = TRUE;
308 cfile.cfilter = g_strdup(optarg);
310 capture_option_specified = TRUE;
315 out_file_type = wtap_short_string_to_file_type(optarg);
316 if (out_file_type < 0) {
317 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
322 case 'h': /* Print help and exit */
326 case 'i': /* Use interface xxx */
328 cfile.iface = g_strdup(optarg);
330 capture_option_specified = TRUE;
334 case 'l': /* Line-buffer standard output */
335 setvbuf(stdout, NULL, _IOLBF, 0);
337 case 'n': /* No name resolution */
338 g_resolving_actif = 0;
340 case 'o': /* Override preference from command line */
341 switch (prefs_set_pref(optarg)) {
343 case PREFS_SET_SYNTAX_ERR:
344 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
348 case PREFS_SET_NO_SUCH_PREF:
349 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
355 case 'p': /* Don't capture in promiscuous mode */
359 capture_option_specified = TRUE;
363 case 'r': /* Read capture file xxx */
364 cf_name = g_strdup(optarg);
366 case 'R': /* Read file filter */
369 case 's': /* Set the snapshot (capture) length */
371 cfile.snap = atoi(optarg);
373 capture_option_specified = TRUE;
377 case 't': /* Time stamp type */
378 if (strcmp(optarg, "r") == 0)
379 timestamp_type = RELATIVE;
380 else if (strcmp(optarg, "a") == 0)
381 timestamp_type = ABSOLUTE;
382 else if (strcmp(optarg, "ad") == 0)
383 timestamp_type = ABSOLUTE_WITH_DATE;
384 else if (strcmp(optarg, "d") == 0)
385 timestamp_type = DELTA;
387 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
389 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
390 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
394 case 'v': /* Show version and exit */
395 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
398 case 'w': /* Write to capture file xxx */
399 cfile.save_file = g_strdup(optarg);
401 case 'V': /* Verbose */
404 case 'x': /* Print packet data in hex (and ASCII) */
410 /* If no capture filter or read filter has been specified, and there are
411 still command-line arguments, treat them as the tokens of a capture
412 filter (if no "-r" flag was specified) or a read filter (if a "-r"
413 flag was specified. */
415 if (cf_name != NULL) {
416 if (rfilter != NULL) {
418 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
421 rfilter = get_args_as_string(argc, argv, optind);
424 if (capture_filter_specified) {
426 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
429 cfile.cfilter = get_args_as_string(argc, argv, optind);
431 capture_option_specified = TRUE;
437 /* Start windows sockets */
438 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
441 /* Notify all registered modules that have had any of their preferences
442 changed either from one of the preferences file or from the command
443 line that its preferences have changed. */
447 if (capture_option_specified)
448 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
453 /* Build the column format array */
454 for (i = 0; i < cfile.cinfo.num_cols; i++) {
455 cfile.cinfo.col_fmt[i] = get_column_format(i);
456 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
457 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
459 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
460 cfile.cinfo.col_data[i] = NULL;
461 if (cfile.cinfo.col_fmt[i] == COL_INFO)
462 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
464 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
468 cfile.snap = WTAP_MAX_PACKET_SIZE;
469 else if (cfile.snap < MIN_PACKET_SIZE)
470 cfile.snap = MIN_PACKET_SIZE;
472 if (rfilter != NULL) {
473 if (!dfilter_compile(rfilter, &rfcode)) {
474 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
479 cfile.rfcode = rfcode;
481 err = open_cap_file(cf_name, FALSE, &cfile);
486 err = load_cap_file(&cfile, out_file_type);
493 /* No capture file specified, so we're supposed to do a live capture;
494 do we have support for live captures? */
496 /* Yes; did the user specify an interface to use? */
497 if (cfile.iface == NULL) {
498 /* No - pick the first one from the list of interfaces. */
499 if_list = get_interface_list(&err, err_str);
500 if (if_list == NULL) {
503 case CANT_GET_INTERFACE_LIST:
504 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
508 case NO_INTERFACES_FOUND:
509 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
514 cfile.iface = g_strdup(if_list->data); /* first interface */
515 free_interface_list(if_list);
517 capture(packet_count, out_file_type);
520 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
531 /* Do the low-level work of a capture.
532 Returns TRUE if it succeeds, FALSE otherwise. */
534 capture(int packet_count, int out_file_type)
536 gchar err_str[PCAP_ERRBUF_SIZE];
537 bpf_u_int32 netnum, netmask;
538 struct bpf_program fcode;
539 void (*oldhandler)(int);
543 static const char ppamsg[] = "can't find PPA for ";
547 /* Initialize the table of conversations. */
548 epan_conversation_init();
550 /* Initialize protocol-specific variables */
551 init_all_protocols();
553 ld.linktype = WTAP_ENCAP_UNKNOWN;
556 /* Open the network interface to capture from it. */
557 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
559 if (ld.pch == NULL) {
560 /* Well, we couldn't start the capture. */
562 /* On Win32 OSes, the capture devices are probably available to all
563 users; don't warn about permissions problems.
565 Do, however, warn that Token Ring and PPP devices aren't supported. */
566 snprintf(errmsg, sizeof errmsg,
567 "The capture session could not be initiated (%s).\n"
568 "Please check that you have the proper interface specified.\n"
570 "Note that the driver Tethereal uses for packet capture on Windows\n"
571 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
572 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
575 /* If we got a "can't find PPA for XXX" message, warn the user (who
576 is running Ethereal on HP-UX) that they don't have a version
577 of libpcap patched to properly handle HP-UX (the patched version
578 says "can't find /dev/dlpi PPA for XXX" rather than "can't find
580 if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
583 "You are running Tethereal with a version of the libpcap library\n"
584 "that doesn't handle HP-UX network devices well; this means that\n"
585 "Tethereal may not be able to capture packets.\n"
587 "To fix this, you will need to download the source to Tethereal\n"
588 "from www.ethereal.com if you have not already done so, read\n"
589 "the instructions in the \"README.hpux\" file in the source\n"
590 "distribution, download the source to libpcap if you have not\n"
591 "already done so, patch libpcap as per the instructions, rebuild\n"
592 "and install libpcap, and then build Tethereal (if you have already\n"
593 "built Tethereal from source, do a \"make distclean\" and re-run\n"
594 "configure before building).";
597 snprintf(errmsg, sizeof errmsg,
598 "The capture session could not be initiated (%s).\n"
599 "Please check to make sure you have sufficient permissions, and that\n"
600 "you have the proper interface specified.%s", err_str, libpcap_warn);
606 /* A capture filter was specified; set it up. */
607 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
609 * Well, we can't get the netmask for this interface; it's used
610 * only for filters that check for broadcast IP addresses, so
611 * we just warn the user, and punt and use 0.
614 "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
617 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
618 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
619 pcap_geterr(ld.pch));
622 if (pcap_setfilter(ld.pch, &fcode) < 0) {
623 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
624 pcap_geterr(ld.pch));
629 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
630 if (cfile.save_file != NULL) {
631 /* Set up to write to the capture file. */
632 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
633 strcpy(errmsg, "The network you're capturing from is of a type"
634 " that Tethereal doesn't support.");
637 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
638 ld.linktype, pcap_snapshot(ld.pch), &err);
640 if (ld.pdh == NULL) {
641 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
647 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
649 XXX - deal with signal semantics on various platforms. Or just
650 use "sigaction()" and be done with it? */
651 signal(SIGTERM, capture_cleanup);
652 signal(SIGINT, capture_cleanup);
654 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
655 signal(SIGHUP, oldhandler);
658 /* Let the user know what interface was chosen. */
659 printf("Capturing on %s\n", cfile.iface);
661 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
664 /* Send a newline if we were printing packet counts to stdout */
665 if (cfile.save_file != NULL) {
672 g_free(cfile.save_file);
673 cfile.save_file = NULL;
674 fprintf(stderr, "tethereal: %s\n", errmsg);
682 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
685 struct wtap_pkthdr whdr;
686 loop_data *ld = (loop_data *) user;
689 whdr.ts.tv_sec = phdr->ts.tv_sec;
690 whdr.ts.tv_usec = phdr->ts.tv_usec;
691 whdr.caplen = phdr->caplen;
692 whdr.len = phdr->len;
693 whdr.pkt_encap = ld->linktype;
698 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
699 printf("\r%u ", cfile.count);
702 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
707 capture_cleanup(int signum)
714 wtap_dump_close(ld.pdh, &err);
715 /* XXX - complain if this fails */
718 #endif /* HAVE_LIBPCAP */
721 load_cap_file(capture_file *cf, int out_file_type)
729 linktype = wtap_file_encap(cf->wth);
730 if (cf->save_file != NULL) {
731 /* Set up to write to the capture file. */
732 pdh = wtap_dump_open(cf->save_file, out_file_type,
733 linktype, wtap_snapshot_length(cf->wth), &err);
736 /* We couldn't set up to write to the capture file. */
739 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
741 "tethereal: Capture files can't be written in that format.\n");
744 case WTAP_ERR_UNSUPPORTED_ENCAP:
745 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
747 "tethereal: The capture file being read cannot be written in that format.\n");
750 case WTAP_ERR_CANT_OPEN:
752 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
756 case WTAP_ERR_SHORT_WRITE:
758 "tethereal: A full header couldn't be written to the file \"%s\".\n",
765 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
769 "tethereal: The file \"%s\" could not be opened: %s\n.",
770 cf->save_file, strerror(err));
778 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
783 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
787 /* Print up a message box noting that the read failed somewhere along
791 case WTAP_ERR_UNSUPPORTED_ENCAP:
793 "tethereal: The capture file is for a network type that Tethereal doesn't support.\n");
796 case WTAP_ERR_CANT_READ:
798 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
801 case WTAP_ERR_SHORT_READ:
803 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
806 case WTAP_ERR_BAD_RECORD:
808 "tethereal: The capture file appears to be damaged or corrupt.\n");
813 "tethereal: An error occurred while reading the capture file: %s.\n",
827 fill_in_fdata(frame_data *fdata, capture_file *cf,
828 const struct wtap_pkthdr *phdr,
829 const union wtap_pseudo_header *pseudo_header, int offset)
836 fdata->num = cf->count;
837 fdata->pkt_len = phdr->len;
838 fdata->cap_len = phdr->caplen;
839 fdata->file_off = offset;
841 fdata->lnk_t = phdr->pkt_encap;
842 fdata->abs_secs = phdr->ts.tv_sec;
843 fdata->abs_usecs = phdr->ts.tv_usec;
844 fdata->flags.passed_dfilter = 0;
845 fdata->flags.encoding = CHAR_ASCII;
846 fdata->flags.visited = 0;
847 fdata->flags.marked = 0;
849 /* If we don't have the time stamp of the first packet in the
850 capture, it's because this is the first packet. Save the time
851 stamp of this packet as the time stamp of the first packet. */
852 if (!firstsec && !firstusec) {
853 firstsec = fdata->abs_secs;
854 firstusec = fdata->abs_usecs;
857 /* If we don't have the time stamp of the previous displayed packet,
858 it's because this is the first displayed packet. Save the time
859 stamp of this packet as the time stamp of the previous displayed
861 if (!prevsec && !prevusec) {
862 prevsec = fdata->abs_secs;
863 prevusec = fdata->abs_usecs;
866 /* Get the time elapsed between the first packet and this packet. */
867 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
868 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
870 /* If it's greater than the current elapsed time, set the elapsed time
871 to it (we check for "greater than" so as not to be confused by
872 time moving backwards). */
873 if (cf->esec < fdata->rel_secs
874 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
875 cf->esec = fdata->rel_secs;
876 cf->eusec = fdata->rel_usecs;
879 /* Get the time elapsed between the previous displayed packet and
881 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
882 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
883 prevsec = fdata->abs_secs;
884 prevusec = fdata->abs_usecs;
886 fdata->cinfo = &cf->cinfo;
887 for (i = 0; i < fdata->cinfo->num_cols; i++) {
888 fdata->cinfo->col_buf[i][0] = '\0';
889 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
894 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
895 union wtap_pseudo_header *pseudo_header, const u_char *buf)
897 cb_args_t *args = (cb_args_t *) user;
898 capture_file *cf = args->cf;
899 wtap_dumper *pdh = args->pdh;
901 proto_tree *protocol_tree;
908 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
909 protocol_tree = proto_tree_create_root();
910 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
911 passed = dfilter_apply_edt(cf->rfcode, edt);
913 protocol_tree = NULL;
918 /* XXX - do something if this fails */
919 wtap_dump(pdh, phdr, pseudo_header, buf, &err);
921 if (protocol_tree != NULL)
922 proto_tree_free(protocol_tree);
924 epan_dissect_free(edt);
928 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
929 union wtap_pseudo_header *pseudo_header, const u_char *buf)
931 cb_args_t *args = (cb_args_t *) user;
932 capture_file *cf = args->cf;
934 proto_tree *protocol_tree;
936 print_args_t print_args;
942 /* The protocol tree will be "visible", i.e., printed, only if we're
943 not printing a summary. */
944 proto_tree_is_visible = verbose;
946 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
949 if (cf->rfcode || verbose)
950 protocol_tree = proto_tree_create_root();
952 protocol_tree = NULL;
953 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
955 passed = dfilter_apply_edt(cf->rfcode, edt);
957 /* The packet passed the read filter. */
959 /* Print the information in the protocol tree. */
960 print_args.to_file = TRUE;
961 print_args.format = PR_FMT_TEXT;
962 print_args.print_summary = FALSE;
963 print_args.print_hex = print_hex;
964 print_args.expand_all = TRUE;
965 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
966 buf, &fdata, stdout);
968 /* "print_hex_data()" will put out a leading blank line, as well
969 as a trailing one; print one here, to separate the packets,
970 only if "print_hex_data()" won't be called. */
974 /* Just fill in the columns. */
975 fill_in_columns(&fdata);
977 /* Now print them. */
978 for (i = 0; i < cf->cinfo.num_cols; i++) {
979 switch (cf->cinfo.col_fmt[i]) {
982 * Don't print this if we're doing a live capture from a network
983 * interface - if we're doing a live capture, you won't be
984 * able to look at the capture in the future (it's not being
985 * saved anywhere), so the frame numbers are unlikely to be
988 * (XXX - it might be nice to be able to save and print at
989 * the same time, sort of like an "Update list of packets
990 * in real time" capture in Ethereal.)
992 if (cf->iface != NULL)
994 printf("%3s", cf->cinfo.col_data[i]);
1000 case COL_ABS_DATE_TIME: /* XXX - wider */
1001 printf("%10s", cf->cinfo.col_data[i]);
1007 case COL_DEF_DL_SRC:
1008 case COL_RES_DL_SRC:
1009 case COL_UNRES_DL_SRC:
1010 case COL_DEF_NET_SRC:
1011 case COL_RES_NET_SRC:
1012 case COL_UNRES_NET_SRC:
1013 printf("%12s", cf->cinfo.col_data[i]);
1019 case COL_DEF_DL_DST:
1020 case COL_RES_DL_DST:
1021 case COL_UNRES_DL_DST:
1022 case COL_DEF_NET_DST:
1023 case COL_RES_NET_DST:
1024 case COL_UNRES_NET_DST:
1025 printf("%-12s", cf->cinfo.col_data[i]);
1029 printf("%s", cf->cinfo.col_data[i]);
1032 if (i != cf->cinfo.num_cols - 1) {
1034 * This isn't the last column, so we need to print a
1035 * separator between this column and the next.
1037 * If we printed a network source and are printing a
1038 * network destination of the same type next, separate
1039 * them with "->"; if we printed a network destination
1040 * and are printing a network source of the same type
1041 * next, separate them with "<-"; otherwise separate them
1044 switch (cf->cinfo.col_fmt[i]) {
1049 switch (cf->cinfo.col_fmt[i + 1]) {
1063 case COL_DEF_DL_SRC:
1064 case COL_RES_DL_SRC:
1065 case COL_UNRES_DL_SRC:
1066 switch (cf->cinfo.col_fmt[i + 1]) {
1068 case COL_DEF_DL_DST:
1069 case COL_RES_DL_DST:
1070 case COL_UNRES_DL_DST:
1080 case COL_DEF_NET_SRC:
1081 case COL_RES_NET_SRC:
1082 case COL_UNRES_NET_SRC:
1083 switch (cf->cinfo.col_fmt[i + 1]) {
1085 case COL_DEF_NET_DST:
1086 case COL_RES_NET_DST:
1087 case COL_UNRES_NET_DST:
1100 switch (cf->cinfo.col_fmt[i + 1]) {
1114 case COL_DEF_DL_DST:
1115 case COL_RES_DL_DST:
1116 case COL_UNRES_DL_DST:
1117 switch (cf->cinfo.col_fmt[i + 1]) {
1119 case COL_DEF_DL_SRC:
1120 case COL_RES_DL_SRC:
1121 case COL_UNRES_DL_SRC:
1131 case COL_DEF_NET_DST:
1132 case COL_RES_NET_DST:
1133 case COL_UNRES_NET_DST:
1134 switch (cf->cinfo.col_fmt[i + 1]) {
1136 case COL_DEF_NET_SRC:
1137 case COL_RES_NET_SRC:
1138 case COL_UNRES_NET_SRC:
1157 print_hex_data(stdout, print_args.format, buf,
1158 fdata.cap_len, fdata.flags.encoding);
1163 if (protocol_tree != NULL)
1164 proto_tree_free(protocol_tree);
1166 epan_dissect_free(edt);
1168 proto_tree_is_visible = FALSE;
1172 file_open_error_message(int err, gboolean for_writing)
1175 static char errmsg_errno[1024+1];
1179 case WTAP_ERR_NOT_REGULAR_FILE:
1180 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1183 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1184 case WTAP_ERR_UNSUPPORTED:
1185 /* Seen only when opening a capture file for reading. */
1186 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1189 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1190 /* Seen only when opening a capture file for writing. */
1191 errmsg = "Tethereal does not support writing capture files in that format.";
1194 case WTAP_ERR_UNSUPPORTED_ENCAP:
1195 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1197 errmsg = "Tethereal cannot save this capture in that format.";
1199 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1202 case WTAP_ERR_BAD_RECORD:
1203 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1206 case WTAP_ERR_CANT_OPEN:
1208 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1210 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1213 case WTAP_ERR_SHORT_READ:
1214 errmsg = "The file \"%s\" appears to have been cut short"
1215 " in the middle of a packet.";
1218 case WTAP_ERR_SHORT_WRITE:
1219 errmsg = "A full header couldn't be written to the file \"%s\".";
1224 errmsg = "The path to the file \"%s\" does not exist.";
1226 errmsg = "The file \"%s\" does not exist.";
1231 errmsg = "You do not have permission to create or write to the file \"%s\".";
1233 errmsg = "You do not have permission to read the file \"%s\".";
1237 errmsg = "\"%s\" is a directory (folder), not a file.";
1241 snprintf(errmsg_errno, sizeof(errmsg_errno),
1242 "The file \"%%s\" could not be opened: %s.",
1243 wtap_strerror(err));
1244 errmsg = errmsg_errno;
1251 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1257 struct stat cf_stat;
1258 char err_msg[2048+1];
1260 wth = wtap_open_offline(fname, &err, FALSE);
1264 /* Find the size of the file. */
1265 fh = wtap_file(wth);
1267 if (fstat(fd, &cf_stat) < 0) {
1273 /* The open succeeded. Fill in the information for this file. */
1275 /* Initialize the table of conversations. */
1276 epan_conversation_init();
1278 /* Initialize protocol-specific variables */
1279 init_all_protocols();
1283 cf->f_len = cf_stat.st_size;
1285 /* Set the file name because we need it to set the follow stream filter.
1286 XXX - is that still true? We need it for other reasons, though,
1288 cf->filename = g_strdup(fname);
1290 /* Indicate whether it's a permanent or temporary file. */
1291 cf->is_tempfile = is_tempfile;
1293 /* If it's a temporary capture buffer file, mark it as not saved. */
1294 cf->user_saved = !is_tempfile;
1296 cf->cd_t = wtap_file_type(cf->wth);
1301 cf->snap = wtap_snapshot_length(cf->wth);
1302 cf->progbar_quantum = 0;
1303 cf->progbar_nextstep = 0;
1304 firstsec = 0, firstusec = 0;
1305 prevsec = 0, prevusec = 0;
1310 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1311 fprintf(stderr, "tethereal: %s\n", err_msg);