3 * $Id: tethereal.c,v 1.61 2001/01/04 00:16: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.
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
46 #ifdef HAVE_SYS_STAT_H
56 #ifdef NEED_SNPRINTF_H
57 # include "snprintf.h"
60 #if defined(HAVE_UCD_SNMP_SNMP_H)
61 #ifdef HAVE_UCD_SNMP_VERSION_H
62 #include <ucd-snmp/version.h>
63 #endif /* HAVE_UCD_SNMP_VERSION_H */
64 #elif defined(HAVE_SNMP_SNMP_H)
65 #ifdef HAVE_SNMP_VERSION_H
66 #include <snmp/version.h>
67 #endif /* HAVE_SNMP_VERSION_H */
70 #ifdef NEED_STRERROR_H
82 #include "timestamp.h"
90 #include "conversation.h"
93 static guint32 firstsec, firstusec;
94 static guint32 prevsec, prevusec;
95 static gchar comp_info_str[256];
96 static gboolean verbose;
97 static gboolean print_hex;
100 typedef struct _loop_data {
108 static int capture(int, int);
109 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
111 static void capture_cleanup(int);
119 static int load_cap_file(capture_file *, int);
120 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
121 union wtap_pseudo_header *, const u_char *);
122 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
123 union wtap_pseudo_header *, const u_char *);
127 FILE *data_out_file = NULL;
128 guint main_ctx, file_ctx;
129 ts_type timestamp_type = RELATIVE;
131 static int promisc_mode = TRUE;
139 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
140 VERSION, comp_info_str);
142 fprintf(stderr, "t%s [ -vVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
143 fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
144 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
145 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
147 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
148 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
149 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
151 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
152 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
153 if (wtap_dump_can_open(i))
154 fprintf(stderr, "\t%s - %s\n",
155 wtap_file_type_short_string(i), wtap_file_type_string(i));
157 fprintf(stderr, "\tdefault is libpcap\n");
161 main(int argc, char *argv[])
165 gboolean arg_error = FALSE;
168 char pcap_version[] = "0.4a6";
170 extern char pcap_version[];
178 char *gpf_path, *pf_path;
179 int gpf_open_errno, pf_open_errno;
182 gboolean capture_filter_specified = FALSE;
183 int packet_count = 0;
185 gchar err_str[PCAP_ERRBUF_SIZE];
187 gboolean capture_option_specified = FALSE;
189 int out_file_type = WTAP_FILE_PCAP;
190 gchar *cf_name = NULL, *rfilter = NULL;
191 dfilter *rfcode = NULL;
194 /* Register all dissectors; we must do this before checking for the
195 "-G" flag, as the "-G" flag dumps a list of fields registered
196 by the dissectors, and we must do it before we read the preferences,
197 in case any dissectors register preferences. */
198 epan_init(PLUGIN_DIR);
200 /* Now register the preferences for any non-dissector modules.
201 We must do that before we read the preferences as well. */
202 prefs_register_modules();
204 /* If invoked with the "-G" flag, we dump out a glossary of
205 display filter symbols.
207 We do this here to mirror what happens in the GTK+ version, although
208 it's not necessary here. */
209 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
210 proto_registrar_dump();
214 /* Set the C-language locale to the native environment. */
215 setlocale(LC_ALL, "");
217 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
218 if (gpf_path != NULL) {
219 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
220 strerror(gpf_open_errno));
222 if (pf_path != NULL) {
223 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
224 strerror(pf_open_errno));
227 /* Initialize the capture file struct */
229 cfile.plist_end = NULL;
231 cfile.filename = NULL;
232 cfile.user_saved = FALSE;
233 cfile.is_tempfile = FALSE;
235 cfile.dfilter = NULL;
238 cfile.cfilter = g_strdup("");
241 cfile.save_file = NULL;
242 cfile.save_file_fd = -1;
243 cfile.snap = WTAP_MAX_PACKET_SIZE;
245 col_init(&cfile.cinfo, prefs->num_cols);
247 /* Assemble the compile-time options */
248 snprintf(comp_info_str, 256,
249 #ifdef GTK_MAJOR_VERSION
250 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
253 "GTK+ (version unknown), %s%s, %s%s, %s%s",
257 "with libpcap ", pcap_version,
259 "without libpcap", "",
264 "with libz ", ZLIB_VERSION,
265 #else /* ZLIB_VERSION */
266 "with libz ", "(version unknown)",
267 #endif /* ZLIB_VERSION */
268 #else /* HAVE_LIBZ */
270 #endif /* HAVE_LIBZ */
272 /* Oh, this is pretty */
273 #if defined(HAVE_UCD_SNMP_SNMP_H)
274 #ifdef HAVE_UCD_SNMP_VERSION_H
275 "with UCD SNMP ", VersionInfo
276 #else /* HAVE_UCD_SNMP_VERSION_H */
277 "with UCD SNMP ", "(version unknown)"
278 #endif /* HAVE_UCD_SNMP_VERSION_H */
279 #elif defined(HAVE_SNMP_SNMP_H)
280 #ifdef HAVE_SNMP_VERSION_H
281 "with CMU SNMP ", snmp_Version()
282 #else /* HAVE_SNMP_VERSION_H */
283 "with CMU SNMP ", "(version unknown)"
284 #endif /* HAVE_SNMP_VERSION_H */
290 /* Now get our args */
291 while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
293 case 'c': /* Capture xxx packets */
295 packet_count = atoi(optarg);
297 capture_option_specified = TRUE;
303 capture_filter_specified = TRUE;
304 cfile.cfilter = g_strdup(optarg);
306 capture_option_specified = TRUE;
311 out_file_type = wtap_short_string_to_file_type(optarg);
312 if (out_file_type < 0) {
313 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
318 case 'h': /* Print help and exit */
322 case 'i': /* Use interface xxx */
324 cfile.iface = g_strdup(optarg);
326 capture_option_specified = TRUE;
330 case 'l': /* Line-buffer standard output */
331 setvbuf(stdout, NULL, _IOLBF, 0);
333 case 'n': /* No name resolution */
334 g_resolving_actif = 0;
336 case 'o': /* Override preference from command line */
337 switch (prefs_set_pref(optarg)) {
339 case PREFS_SET_SYNTAX_ERR:
340 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
344 case PREFS_SET_NO_SUCH_PREF:
345 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
351 case 'p': /* Don't capture in promiscuous mode */
355 capture_option_specified = TRUE;
359 case 'r': /* Read capture file xxx */
360 cf_name = g_strdup(optarg);
362 case 'R': /* Read file filter */
365 case 's': /* Set the snapshot (capture) length */
367 cfile.snap = atoi(optarg);
369 capture_option_specified = TRUE;
373 case 't': /* Time stamp type */
374 if (strcmp(optarg, "r") == 0)
375 timestamp_type = RELATIVE;
376 else if (strcmp(optarg, "a") == 0)
377 timestamp_type = ABSOLUTE;
378 else if (strcmp(optarg, "ad") == 0)
379 timestamp_type = ABSOLUTE_WITH_DATE;
380 else if (strcmp(optarg, "d") == 0)
381 timestamp_type = DELTA;
383 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
385 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
386 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
390 case 'v': /* Show version and exit */
391 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
394 case 'w': /* Write to capture file xxx */
395 cfile.save_file = g_strdup(optarg);
397 case 'V': /* Verbose */
400 case 'x': /* Print packet data in hex (and ASCII) */
406 /* If no capture filter or read filter has been specified, and there are
407 still command-line arguments, treat them as the tokens of a capture
408 filter (if no "-r" flag was specified) or a read filter (if a "-r"
409 flag was specified. */
411 if (cf_name != NULL) {
412 if (rfilter != NULL) {
414 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
417 rfilter = get_args_as_string(argc, argv, optind);
420 if (capture_filter_specified) {
422 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
425 cfile.cfilter = get_args_as_string(argc, argv, optind);
427 capture_option_specified = TRUE;
433 /* Start windows sockets */
434 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
437 /* Notify all registered modules that have had any of their preferences
438 changed either from one of the preferences file or from the command
439 line that its preferences have changed. */
443 if (capture_option_specified)
444 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
449 /* Build the column format array */
450 for (i = 0; i < cfile.cinfo.num_cols; i++) {
451 cfile.cinfo.col_fmt[i] = get_column_format(i);
452 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
453 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
455 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
456 cfile.cinfo.col_data[i] = NULL;
457 if (cfile.cinfo.col_fmt[i] == COL_INFO)
458 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
460 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
464 cfile.snap = WTAP_MAX_PACKET_SIZE;
465 else if (cfile.snap < MIN_PACKET_SIZE)
466 cfile.snap = MIN_PACKET_SIZE;
468 if (rfilter != NULL) {
469 if (dfilter_compile(rfilter, &rfcode) != 0) {
470 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
475 cfile.rfcode = rfcode;
477 err = open_cap_file(cf_name, FALSE, &cfile);
482 err = load_cap_file(&cfile, out_file_type);
489 /* No capture file specified, so we're supposed to do a live capture;
490 do we have support for live captures? */
492 /* Yes; did the user specify an interface to use? */
493 if (cfile.iface == NULL) {
494 /* No - pick the first one from the list of interfaces. */
495 if_list = get_interface_list(&err, err_str);
496 if (if_list == NULL) {
499 case CANT_GET_INTERFACE_LIST:
500 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
504 case NO_INTERFACES_FOUND:
505 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
510 cfile.iface = g_strdup(if_list->data); /* first interface */
511 free_interface_list(if_list);
513 capture(packet_count, out_file_type);
516 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
527 /* Do the low-level work of a capture.
528 Returns TRUE if it succeeds, FALSE otherwise. */
530 capture(int packet_count, int out_file_type)
532 gchar err_str[PCAP_ERRBUF_SIZE];
533 bpf_u_int32 netnum, netmask;
534 void (*oldhandler)(int);
538 static const char ppamsg[] = "can't find PPA for ";
542 /* Initialize the table of conversations. */
543 epan_conversation_init();
545 /* Initialize protocol-specific variables */
546 init_all_protocols();
548 ld.linktype = WTAP_ENCAP_UNKNOWN;
551 /* Open the network interface to capture from it. */
552 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
554 if (ld.pch == NULL) {
555 /* Well, we couldn't start the capture. */
557 /* On Win32 OSes, the capture devices are probably available to all
558 users; don't warn about permissions problems.
560 Do, however, warn that Token Ring and PPP devices aren't supported. */
561 snprintf(errmsg, sizeof errmsg,
562 "The capture session could not be initiated (%s).\n"
563 "Please check that you have the proper interface specified.\n"
565 "Note that the driver Tethereal uses for packet capture on Windows\n"
566 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
567 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
570 /* If we got a "can't find PPA for XXX" message, warn the user (who
571 is running Ethereal on HP-UX) that they don't have a version
572 of libpcap patched to properly handle HP-UX (the patched version
573 says "can't find /dev/dlpi PPA for XXX" rather than "can't find
575 if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
578 "You are running Tethereal with a version of the libpcap library\n"
579 "that doesn't handle HP-UX network devices well; this means that\n"
580 "Tethereal may not be able to capture packets.\n"
582 "To fix this, you will need to download the source to Tethereal\n"
583 "from www.ethereal.com if you have not already done so, read\n"
584 "the instructions in the \"README.hpux\" file in the source\n"
585 "distribution, download the source to libpcap if you have not\n"
586 "already done so, patch libpcap as per the instructions, rebuild\n"
587 "and install libpcap, and then build Tethereal (if you have already\n"
588 "built Tethereal from source, do a \"make distclean\" and re-run\n"
589 "configure before building).";
592 snprintf(errmsg, sizeof errmsg,
593 "The capture session could not be initiated (%s).\n"
594 "Please check to make sure you have sufficient permissions, and that\n"
595 "you have the proper interface specified.%s", err_str, libpcap_warn);
601 /* A capture filter was specified; set it up. */
602 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
604 * Well, we can't get the netmask for this interface; it's used
605 * only for filters that check for broadcast IP addresses, so
606 * we just warn the user, and punt and use 0.
609 "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
612 if (pcap_compile(ld.pch, &cfile.fcode, cfile.cfilter, 1, netmask) < 0) {
613 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
614 pcap_geterr(ld.pch));
617 if (pcap_setfilter(ld.pch, &cfile.fcode) < 0) {
618 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
619 pcap_geterr(ld.pch));
624 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
625 if (cfile.save_file != NULL) {
626 /* Set up to write to the capture file. */
627 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
628 strcpy(errmsg, "The network you're capturing from is of a type"
629 " that Tethereal doesn't support.");
632 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
633 ld.linktype, pcap_snapshot(ld.pch), &err);
635 if (ld.pdh == NULL) {
636 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
642 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
644 XXX - deal with signal semantics on various platforms. Or just
645 use "sigaction()" and be done with it? */
646 signal(SIGTERM, capture_cleanup);
647 signal(SIGINT, capture_cleanup);
649 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
650 signal(SIGHUP, oldhandler);
653 /* Let the user know what interface was chosen. */
654 printf("Capturing on %s\n", cfile.iface);
656 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
659 /* Send a newline if we were printing packet counts to stdout */
660 if (cfile.save_file != NULL) {
667 g_free(cfile.save_file);
668 cfile.save_file = NULL;
669 fprintf(stderr, "tethereal: %s\n", errmsg);
677 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
680 struct wtap_pkthdr whdr;
681 loop_data *ld = (loop_data *) user;
684 whdr.ts.tv_sec = phdr->ts.tv_sec;
685 whdr.ts.tv_usec = phdr->ts.tv_usec;
686 whdr.caplen = phdr->caplen;
687 whdr.len = phdr->len;
688 whdr.pkt_encap = ld->linktype;
693 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
694 printf("\r%u ", cfile.count);
697 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
702 capture_cleanup(int signum)
709 wtap_dump_close(ld.pdh, &err);
710 /* XXX - complain if this fails */
713 #endif /* HAVE_LIBPCAP */
716 load_cap_file(capture_file *cf, int out_file_type)
724 linktype = wtap_file_encap(cf->wth);
725 if (cf->save_file != NULL) {
726 /* Set up to write to the capture file. */
727 pdh = wtap_dump_open(cf->save_file, out_file_type,
728 linktype, wtap_snapshot_length(cf->wth), &err);
731 /* We couldn't set up to write to the capture file. */
734 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
736 "tethereal: Capture files can't be written in that format.\n");
739 case WTAP_ERR_UNSUPPORTED_ENCAP:
740 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
742 "tethereal: The capture file being read cannot be written in that format.\n");
745 case WTAP_ERR_CANT_OPEN:
747 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
751 case WTAP_ERR_SHORT_WRITE:
753 "tethereal: A full header couldn't be written to the file \"%s\".\n",
760 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
764 "tethereal: The file \"%s\" could not be opened: %s\n.",
765 cf->save_file, strerror(err));
773 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
778 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
782 /* Print up a message box noting that the read failed somewhere along
786 case WTAP_ERR_UNSUPPORTED_ENCAP:
788 "tethereal: The capture file is for a network type that Tethereal doesn't support.\n");
791 case WTAP_ERR_CANT_READ:
793 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
796 case WTAP_ERR_SHORT_READ:
798 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
801 case WTAP_ERR_BAD_RECORD:
803 "tethereal: The capture file appears to be damaged or corrupt.\n");
808 "tethereal: An error occurred while reading the capture file: %s.\n",
822 fill_in_fdata(frame_data *fdata, capture_file *cf,
823 const struct wtap_pkthdr *phdr,
824 const union wtap_pseudo_header *pseudo_header, int offset)
831 fdata->num = cf->count;
832 fdata->pkt_len = phdr->len;
833 fdata->cap_len = phdr->caplen;
834 fdata->file_off = offset;
836 fdata->lnk_t = phdr->pkt_encap;
837 fdata->abs_secs = phdr->ts.tv_sec;
838 fdata->abs_usecs = phdr->ts.tv_usec;
839 fdata->flags.passed_dfilter = 0;
840 fdata->flags.encoding = CHAR_ASCII;
841 fdata->flags.visited = 0;
842 fdata->flags.marked = 0;
844 /* If we don't have the time stamp of the first packet in the
845 capture, it's because this is the first packet. Save the time
846 stamp of this packet as the time stamp of the first packet. */
847 if (!firstsec && !firstusec) {
848 firstsec = fdata->abs_secs;
849 firstusec = fdata->abs_usecs;
852 /* If we don't have the time stamp of the previous displayed packet,
853 it's because this is the first displayed packet. Save the time
854 stamp of this packet as the time stamp of the previous displayed
856 if (!prevsec && !prevusec) {
857 prevsec = fdata->abs_secs;
858 prevusec = fdata->abs_usecs;
861 /* Get the time elapsed between the first packet and this packet. */
862 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
863 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
865 /* If it's greater than the current elapsed time, set the elapsed time
866 to it (we check for "greater than" so as not to be confused by
867 time moving backwards). */
868 if (cf->esec < fdata->rel_secs
869 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
870 cf->esec = fdata->rel_secs;
871 cf->eusec = fdata->rel_usecs;
874 /* Get the time elapsed between the previous displayed packet and
876 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
877 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
878 prevsec = fdata->abs_secs;
879 prevusec = fdata->abs_usecs;
881 fdata->cinfo = &cf->cinfo;
882 for (i = 0; i < fdata->cinfo->num_cols; i++) {
883 fdata->cinfo->col_buf[i][0] = '\0';
884 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
889 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
890 union wtap_pseudo_header *pseudo_header, const u_char *buf)
892 cb_args_t *args = (cb_args_t *) user;
893 capture_file *cf = args->cf;
894 wtap_dumper *pdh = args->pdh;
896 proto_tree *protocol_tree;
903 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
904 protocol_tree = proto_tree_create_root();
905 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
906 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len);
908 protocol_tree = NULL;
913 /* XXX - do something if this fails */
914 wtap_dump(pdh, phdr, pseudo_header, buf, &err);
916 if (protocol_tree != NULL)
917 proto_tree_free(protocol_tree);
919 epan_dissect_free(edt);
923 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
924 union wtap_pseudo_header *pseudo_header, const u_char *buf)
926 cb_args_t *args = (cb_args_t *) user;
927 capture_file *cf = args->cf;
929 proto_tree *protocol_tree;
931 print_args_t print_args;
937 /* The protocol tree will be "visible", i.e., printed, only if we're
938 not printing a summary. */
939 proto_tree_is_visible = verbose;
941 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
944 if (cf->rfcode || verbose)
945 protocol_tree = proto_tree_create_root();
947 protocol_tree = NULL;
948 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
950 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len);
952 /* The packet passed the read filter. */
954 /* Print the information in the protocol tree. */
955 print_args.to_file = TRUE;
956 print_args.format = PR_FMT_TEXT;
957 print_args.print_summary = FALSE;
958 print_args.print_hex = print_hex;
959 print_args.expand_all = TRUE;
960 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
961 buf, &fdata, stdout);
963 /* "print_hex_data()" will put out a leading blank line, as well
964 as a trailing one; print one here, to separate the packets,
965 only if "print_hex_data()" won't be called. */
969 /* Just fill in the columns. */
970 fill_in_columns(&fdata);
972 /* Now print them. */
973 for (i = 0; i < cf->cinfo.num_cols; i++) {
974 switch (cf->cinfo.col_fmt[i]) {
977 * Don't print this if we're doing a live capture from a network
978 * interface - if we're doing a live capture, you won't be
979 * able to look at the capture in the future (it's not being
980 * saved anywhere), so the frame numbers are unlikely to be
983 * (XXX - it might be nice to be able to save and print at
984 * the same time, sort of like an "Update list of packets
985 * in real time" capture in Ethereal.)
987 if (cf->iface != NULL)
989 printf("%3s", cf->cinfo.col_data[i]);
995 case COL_ABS_DATE_TIME: /* XXX - wider */
996 printf("%10s", cf->cinfo.col_data[i]);
1002 case COL_DEF_DL_SRC:
1003 case COL_RES_DL_SRC:
1004 case COL_UNRES_DL_SRC:
1005 case COL_DEF_NET_SRC:
1006 case COL_RES_NET_SRC:
1007 case COL_UNRES_NET_SRC:
1008 printf("%12s", cf->cinfo.col_data[i]);
1014 case COL_DEF_DL_DST:
1015 case COL_RES_DL_DST:
1016 case COL_UNRES_DL_DST:
1017 case COL_DEF_NET_DST:
1018 case COL_RES_NET_DST:
1019 case COL_UNRES_NET_DST:
1020 printf("%-12s", cf->cinfo.col_data[i]);
1024 printf("%s", cf->cinfo.col_data[i]);
1027 if (i != cf->cinfo.num_cols - 1) {
1029 * This isn't the last column, so we need to print a
1030 * separator between this column and the next.
1032 * If we printed a network source and are printing a
1033 * network destination of the same type next, separate
1034 * them with "->"; if we printed a network destination
1035 * and are printing a network source of the same type
1036 * next, separate them with "<-"; otherwise separate them
1039 switch (cf->cinfo.col_fmt[i]) {
1044 switch (cf->cinfo.col_fmt[i + 1]) {
1058 case COL_DEF_DL_SRC:
1059 case COL_RES_DL_SRC:
1060 case COL_UNRES_DL_SRC:
1061 switch (cf->cinfo.col_fmt[i + 1]) {
1063 case COL_DEF_DL_DST:
1064 case COL_RES_DL_DST:
1065 case COL_UNRES_DL_DST:
1075 case COL_DEF_NET_SRC:
1076 case COL_RES_NET_SRC:
1077 case COL_UNRES_NET_SRC:
1078 switch (cf->cinfo.col_fmt[i + 1]) {
1080 case COL_DEF_NET_DST:
1081 case COL_RES_NET_DST:
1082 case COL_UNRES_NET_DST:
1095 switch (cf->cinfo.col_fmt[i + 1]) {
1109 case COL_DEF_DL_DST:
1110 case COL_RES_DL_DST:
1111 case COL_UNRES_DL_DST:
1112 switch (cf->cinfo.col_fmt[i + 1]) {
1114 case COL_DEF_DL_SRC:
1115 case COL_RES_DL_SRC:
1116 case COL_UNRES_DL_SRC:
1126 case COL_DEF_NET_DST:
1127 case COL_RES_NET_DST:
1128 case COL_UNRES_NET_DST:
1129 switch (cf->cinfo.col_fmt[i + 1]) {
1131 case COL_DEF_NET_SRC:
1132 case COL_RES_NET_SRC:
1133 case COL_UNRES_NET_SRC:
1152 print_hex_data(stdout, print_args.format, buf,
1153 fdata.cap_len, fdata.flags.encoding);
1158 if (protocol_tree != NULL)
1159 proto_tree_free(protocol_tree);
1161 epan_dissect_free(edt);
1163 proto_tree_is_visible = FALSE;
1167 file_open_error_message(int err, gboolean for_writing)
1170 static char errmsg_errno[1024+1];
1174 case WTAP_ERR_NOT_REGULAR_FILE:
1175 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1178 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1179 case WTAP_ERR_UNSUPPORTED:
1180 /* Seen only when opening a capture file for reading. */
1181 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1184 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1185 /* Seen only when opening a capture file for writing. */
1186 errmsg = "Tethereal does not support writing capture files in that format.";
1189 case WTAP_ERR_UNSUPPORTED_ENCAP:
1190 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1192 errmsg = "Tethereal cannot save this capture in that format.";
1194 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1197 case WTAP_ERR_BAD_RECORD:
1198 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1201 case WTAP_ERR_CANT_OPEN:
1203 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1205 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1208 case WTAP_ERR_SHORT_READ:
1209 errmsg = "The file \"%s\" appears to have been cut short"
1210 " in the middle of a packet.";
1213 case WTAP_ERR_SHORT_WRITE:
1214 errmsg = "A full header couldn't be written to the file \"%s\".";
1219 errmsg = "The path to the file \"%s\" does not exist.";
1221 errmsg = "The file \"%s\" does not exist.";
1226 errmsg = "You do not have permission to create or write to the file \"%s\".";
1228 errmsg = "You do not have permission to read the file \"%s\".";
1232 errmsg = "\"%s\" is a directory (folder), not a file.";
1236 snprintf(errmsg_errno, sizeof(errmsg_errno),
1237 "The file \"%%s\" could not be opened: %s.",
1238 wtap_strerror(err));
1239 errmsg = errmsg_errno;
1246 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1252 struct stat cf_stat;
1253 char err_msg[2048+1];
1255 wth = wtap_open_offline(fname, &err, FALSE);
1259 /* Find the size of the file. */
1260 fh = wtap_file(wth);
1262 if (fstat(fd, &cf_stat) < 0) {
1268 /* The open succeeded. Fill in the information for this file. */
1270 /* Initialize the table of conversations. */
1271 epan_conversation_init();
1273 /* Initialize protocol-specific variables */
1274 init_all_protocols();
1278 cf->f_len = cf_stat.st_size;
1280 /* Set the file name because we need it to set the follow stream filter.
1281 XXX - is that still true? We need it for other reasons, though,
1283 cf->filename = g_strdup(fname);
1285 /* Indicate whether it's a permanent or temporary file. */
1286 cf->is_tempfile = is_tempfile;
1288 /* If it's a temporary capture buffer file, mark it as not saved. */
1289 cf->user_saved = !is_tempfile;
1291 cf->cd_t = wtap_file_type(cf->wth);
1296 cf->snap = wtap_snapshot_length(cf->wth);
1297 cf->progbar_quantum = 0;
1298 cf->progbar_nextstep = 0;
1299 firstsec = 0, firstusec = 0;
1300 prevsec = 0, prevusec = 0;
1305 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1306 fprintf(stderr, "tethereal: %s\n", err_msg);