3 * $Id: tethereal.c,v 1.60 2000/12/03 22:12:18 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;
130 static int promisc_mode = TRUE;
137 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
138 VERSION, comp_info_str);
140 fprintf(stderr, "t%s [ -vVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
141 fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
142 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
143 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
145 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
146 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
147 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
149 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
150 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
151 if (wtap_dump_can_open(i))
152 fprintf(stderr, "\t%s - %s\n",
153 wtap_file_type_short_string(i), wtap_file_type_string(i));
155 fprintf(stderr, "\tdefault is libpcap\n");
159 main(int argc, char *argv[])
163 gboolean arg_error = FALSE;
166 char pcap_version[] = "0.4a6";
168 extern char pcap_version[];
176 char *gpf_path, *pf_path;
177 int gpf_open_errno, pf_open_errno;
180 gboolean capture_filter_specified = FALSE;
181 int packet_count = 0;
183 gchar err_str[PCAP_ERRBUF_SIZE];
185 gboolean capture_option_specified = FALSE;
187 int out_file_type = WTAP_FILE_PCAP;
188 gchar *cf_name = NULL, *rfilter = NULL;
189 dfilter *rfcode = NULL;
192 /* Register all dissectors; we must do this before checking for the
193 "-G" flag, as the "-G" flag dumps a list of fields registered
194 by the dissectors, and we must do it before we read the preferences,
195 in case any dissectors register preferences. */
196 epan_init(PLUGIN_DIR);
198 /* Now register the preferences for any non-dissector modules.
199 We must do that before we read the preferences as well. */
200 prefs_register_modules();
202 /* If invoked with the "-G" flag, we dump out a glossary of
203 display filter symbols.
205 We do this here to mirror what happens in the GTK+ version, although
206 it's not necessary here. */
207 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
208 proto_registrar_dump();
212 /* Set the C-language locale to the native environment. */
213 setlocale(LC_ALL, "");
215 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
216 if (gpf_path != NULL) {
217 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
218 strerror(gpf_open_errno));
220 if (pf_path != NULL) {
221 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
222 strerror(pf_open_errno));
225 /* Initialize the capture file struct */
227 cfile.plist_end = NULL;
229 cfile.filename = NULL;
230 cfile.user_saved = FALSE;
231 cfile.is_tempfile = FALSE;
233 cfile.dfilter = NULL;
236 cfile.cfilter = g_strdup("");
239 cfile.save_file = NULL;
240 cfile.save_file_fd = -1;
241 cfile.snap = WTAP_MAX_PACKET_SIZE;
243 col_init(&cfile.cinfo, prefs->num_cols);
245 /* Assemble the compile-time options */
246 snprintf(comp_info_str, 256,
247 #ifdef GTK_MAJOR_VERSION
248 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
251 "GTK+ (version unknown), %s%s, %s%s, %s%s",
255 "with libpcap ", pcap_version,
257 "without libpcap", "",
262 "with libz ", ZLIB_VERSION,
263 #else /* ZLIB_VERSION */
264 "with libz ", "(version unknown)",
265 #endif /* ZLIB_VERSION */
266 #else /* HAVE_LIBZ */
268 #endif /* HAVE_LIBZ */
270 /* Oh, this is pretty */
271 #if defined(HAVE_UCD_SNMP_SNMP_H)
272 #ifdef HAVE_UCD_SNMP_VERSION_H
273 "with UCD SNMP ", VersionInfo
274 #else /* HAVE_UCD_SNMP_VERSION_H */
275 "with UCD SNMP ", "(version unknown)"
276 #endif /* HAVE_UCD_SNMP_VERSION_H */
277 #elif defined(HAVE_SNMP_SNMP_H)
278 #ifdef HAVE_SNMP_VERSION_H
279 "with CMU SNMP ", snmp_Version()
280 #else /* HAVE_SNMP_VERSION_H */
281 "with CMU SNMP ", "(version unknown)"
282 #endif /* HAVE_SNMP_VERSION_H */
288 /* Now get our args */
289 while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
291 case 'c': /* Capture xxx packets */
293 packet_count = atoi(optarg);
295 capture_option_specified = TRUE;
301 capture_filter_specified = TRUE;
302 cfile.cfilter = g_strdup(optarg);
304 capture_option_specified = TRUE;
309 out_file_type = wtap_short_string_to_file_type(optarg);
310 if (out_file_type < 0) {
311 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
316 case 'h': /* Print help and exit */
320 case 'i': /* Use interface xxx */
322 cfile.iface = g_strdup(optarg);
324 capture_option_specified = TRUE;
328 case 'l': /* Line-buffer standard output */
329 setvbuf(stdout, NULL, _IOLBF, 0);
331 case 'n': /* No name resolution */
332 g_resolving_actif = 0;
334 case 'o': /* Override preference from command line */
335 switch (prefs_set_pref(optarg)) {
337 case PREFS_SET_SYNTAX_ERR:
338 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
342 case PREFS_SET_NO_SUCH_PREF:
343 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
349 case 'p': /* Don't capture in promiscuous mode */
353 capture_option_specified = TRUE;
357 case 'r': /* Read capture file xxx */
358 cf_name = g_strdup(optarg);
360 case 'R': /* Read file filter */
363 case 's': /* Set the snapshot (capture) length */
365 cfile.snap = atoi(optarg);
367 capture_option_specified = TRUE;
371 case 't': /* Time stamp type */
372 if (strcmp(optarg, "r") == 0)
373 timestamp_type = RELATIVE;
374 else if (strcmp(optarg, "a") == 0)
375 timestamp_type = ABSOLUTE;
376 else if (strcmp(optarg, "ad") == 0)
377 timestamp_type = ABSOLUTE_WITH_DATE;
378 else if (strcmp(optarg, "d") == 0)
379 timestamp_type = DELTA;
381 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
383 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
384 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
388 case 'v': /* Show version and exit */
389 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
392 case 'w': /* Write to capture file xxx */
393 cfile.save_file = g_strdup(optarg);
395 case 'V': /* Verbose */
398 case 'x': /* Print packet data in hex (and ASCII) */
404 /* If no capture filter or read filter has been specified, and there are
405 still command-line arguments, treat them as the tokens of a capture
406 filter (if no "-r" flag was specified) or a read filter (if a "-r"
407 flag was specified. */
409 if (cf_name != NULL) {
410 if (rfilter != NULL) {
412 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
415 rfilter = get_args_as_string(argc, argv, optind);
418 if (capture_filter_specified) {
420 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
423 cfile.cfilter = get_args_as_string(argc, argv, optind);
425 capture_option_specified = TRUE;
431 /* Start windows sockets */
432 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
435 /* Notify all registered modules that have had any of their preferences
436 changed either from one of the preferences file or from the command
437 line that its preferences have changed. */
441 if (capture_option_specified)
442 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
447 /* Build the column format array */
448 for (i = 0; i < cfile.cinfo.num_cols; i++) {
449 cfile.cinfo.col_fmt[i] = get_column_format(i);
450 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
451 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
453 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
454 cfile.cinfo.col_data[i] = NULL;
455 if (cfile.cinfo.col_fmt[i] == COL_INFO)
456 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
458 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
462 cfile.snap = WTAP_MAX_PACKET_SIZE;
463 else if (cfile.snap < MIN_PACKET_SIZE)
464 cfile.snap = MIN_PACKET_SIZE;
466 if (rfilter != NULL) {
467 if (dfilter_compile(rfilter, &rfcode) != 0) {
468 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
473 cfile.rfcode = rfcode;
475 err = open_cap_file(cf_name, FALSE, &cfile);
480 err = load_cap_file(&cfile, out_file_type);
487 /* No capture file specified, so we're supposed to do a live capture;
488 do we have support for live captures? */
490 /* Yes; did the user specify an interface to use? */
491 if (cfile.iface == NULL) {
492 /* No - pick the first one from the list of interfaces. */
493 if_list = get_interface_list(&err, err_str);
494 if (if_list == NULL) {
497 case CANT_GET_INTERFACE_LIST:
498 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
502 case NO_INTERFACES_FOUND:
503 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
508 cfile.iface = g_strdup(if_list->data); /* first interface */
509 free_interface_list(if_list);
511 capture(packet_count, out_file_type);
514 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
525 /* Do the low-level work of a capture.
526 Returns TRUE if it succeeds, FALSE otherwise. */
528 capture(int packet_count, int out_file_type)
530 gchar err_str[PCAP_ERRBUF_SIZE];
531 bpf_u_int32 netnum, netmask;
532 void (*oldhandler)(int);
536 static const char ppamsg[] = "can't find PPA for ";
540 /* Initialize the table of conversations. */
541 epan_conversation_init();
543 /* Initialize protocol-specific variables */
544 init_all_protocols();
546 ld.linktype = WTAP_ENCAP_UNKNOWN;
549 /* Open the network interface to capture from it. */
550 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
552 if (ld.pch == NULL) {
553 /* Well, we couldn't start the capture. */
555 /* On Win32 OSes, the capture devices are probably available to all
556 users; don't warn about permissions problems.
558 Do, however, warn that Token Ring and PPP devices aren't supported. */
559 snprintf(errmsg, sizeof errmsg,
560 "The capture session could not be initiated (%s).\n"
561 "Please check that you have the proper interface specified.\n"
563 "Note that the driver Tethereal uses for packet capture on Windows\n"
564 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
565 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
568 /* If we got a "can't find PPA for XXX" message, warn the user (who
569 is running Ethereal on HP-UX) that they don't have a version
570 of libpcap patched to properly handle HP-UX (the patched version
571 says "can't find /dev/dlpi PPA for XXX" rather than "can't find
573 if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
576 "You are running Tethereal with a version of the libpcap library\n"
577 "that doesn't handle HP-UX network devices well; this means that\n"
578 "Tethereal may not be able to capture packets.\n"
580 "To fix this, you will need to download the source to Tethereal\n"
581 "from www.ethereal.com if you have not already done so, read\n"
582 "the instructions in the \"README.hpux\" file in the source\n"
583 "distribution, download the source to libpcap if you have not\n"
584 "already done so, patch libpcap as per the instructions, rebuild\n"
585 "and install libpcap, and then build Tethereal (if you have already\n"
586 "built Tethereal from source, do a \"make distclean\" and re-run\n"
587 "configure before building).";
590 snprintf(errmsg, sizeof errmsg,
591 "The capture session could not be initiated (%s).\n"
592 "Please check to make sure you have sufficient permissions, and that\n"
593 "you have the proper interface specified.%s", err_str, libpcap_warn);
599 /* A capture filter was specified; set it up. */
600 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
602 * Well, we can't get the netmask for this interface; it's used
603 * only for filters that check for broadcast IP addresses, so
604 * we just warn the user, and punt and use 0.
607 "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
610 if (pcap_compile(ld.pch, &cfile.fcode, cfile.cfilter, 1, netmask) < 0) {
611 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
612 pcap_geterr(ld.pch));
615 if (pcap_setfilter(ld.pch, &cfile.fcode) < 0) {
616 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
617 pcap_geterr(ld.pch));
622 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
623 if (cfile.save_file != NULL) {
624 /* Set up to write to the capture file. */
625 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
626 strcpy(errmsg, "The network you're capturing from is of a type"
627 " that Tethereal doesn't support.");
630 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
631 ld.linktype, pcap_snapshot(ld.pch), &err);
633 if (ld.pdh == NULL) {
634 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
640 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
642 XXX - deal with signal semantics on various platforms. Or just
643 use "sigaction()" and be done with it? */
644 signal(SIGTERM, capture_cleanup);
645 signal(SIGINT, capture_cleanup);
647 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
648 signal(SIGHUP, oldhandler);
651 /* Let the user know what interface was chosen. */
652 printf("Capturing on %s\n", cfile.iface);
654 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
657 /* Send a newline if we were printing packet counts to stdout */
658 if (cfile.save_file != NULL) {
665 g_free(cfile.save_file);
666 cfile.save_file = NULL;
667 fprintf(stderr, "tethereal: %s\n", errmsg);
675 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
678 struct wtap_pkthdr whdr;
679 loop_data *ld = (loop_data *) user;
682 whdr.ts.tv_sec = phdr->ts.tv_sec;
683 whdr.ts.tv_usec = phdr->ts.tv_usec;
684 whdr.caplen = phdr->caplen;
685 whdr.len = phdr->len;
686 whdr.pkt_encap = ld->linktype;
691 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
692 printf("\r%u ", cfile.count);
695 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
700 capture_cleanup(int signum)
707 wtap_dump_close(ld.pdh, &err);
708 /* XXX - complain if this fails */
711 #endif /* HAVE_LIBPCAP */
714 load_cap_file(capture_file *cf, int out_file_type)
722 linktype = wtap_file_encap(cf->wth);
723 if (cf->save_file != NULL) {
724 /* Set up to write to the capture file. */
725 pdh = wtap_dump_open(cf->save_file, out_file_type,
726 linktype, wtap_snapshot_length(cf->wth), &err);
729 /* We couldn't set up to write to the capture file. */
732 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
734 "tethereal: Capture files can't be written in that format.\n");
737 case WTAP_ERR_UNSUPPORTED_ENCAP:
738 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
740 "tethereal: The capture file being read cannot be written in that format.\n");
743 case WTAP_ERR_CANT_OPEN:
745 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
749 case WTAP_ERR_SHORT_WRITE:
751 "tethereal: A full header couldn't be written to the file \"%s\".\n",
758 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
762 "tethereal: The file \"%s\" could not be opened: %s\n.",
763 cf->save_file, strerror(err));
771 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
776 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
780 /* Print up a message box noting that the read failed somewhere along
784 case WTAP_ERR_UNSUPPORTED_ENCAP:
786 "tethereal: The capture file is for a network type that Tethereal doesn't support.\n");
789 case WTAP_ERR_CANT_READ:
791 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
794 case WTAP_ERR_SHORT_READ:
796 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
799 case WTAP_ERR_BAD_RECORD:
801 "tethereal: The capture file appears to be damaged or corrupt.\n");
806 "tethereal: An error occurred while reading the capture file: %s.\n",
820 fill_in_fdata(frame_data *fdata, capture_file *cf,
821 const struct wtap_pkthdr *phdr,
822 const union wtap_pseudo_header *pseudo_header, int offset)
829 fdata->num = cf->count;
830 fdata->pkt_len = phdr->len;
831 fdata->cap_len = phdr->caplen;
832 fdata->file_off = offset;
834 fdata->lnk_t = phdr->pkt_encap;
835 fdata->abs_secs = phdr->ts.tv_sec;
836 fdata->abs_usecs = phdr->ts.tv_usec;
837 fdata->flags.passed_dfilter = 0;
838 fdata->flags.encoding = CHAR_ASCII;
839 fdata->flags.visited = 0;
840 fdata->flags.marked = 0;
842 /* If we don't have the time stamp of the first packet in the
843 capture, it's because this is the first packet. Save the time
844 stamp of this packet as the time stamp of the first packet. */
845 if (!firstsec && !firstusec) {
846 firstsec = fdata->abs_secs;
847 firstusec = fdata->abs_usecs;
850 /* If we don't have the time stamp of the previous displayed packet,
851 it's because this is the first displayed packet. Save the time
852 stamp of this packet as the time stamp of the previous displayed
854 if (!prevsec && !prevusec) {
855 prevsec = fdata->abs_secs;
856 prevusec = fdata->abs_usecs;
859 /* Get the time elapsed between the first packet and this packet. */
860 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
861 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
863 /* If it's greater than the current elapsed time, set the elapsed time
864 to it (we check for "greater than" so as not to be confused by
865 time moving backwards). */
866 if (cf->esec < fdata->rel_secs
867 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
868 cf->esec = fdata->rel_secs;
869 cf->eusec = fdata->rel_usecs;
872 /* Get the time elapsed between the previous displayed packet and
874 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
875 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
876 prevsec = fdata->abs_secs;
877 prevusec = fdata->abs_usecs;
879 fdata->cinfo = &cf->cinfo;
880 for (i = 0; i < fdata->cinfo->num_cols; i++) {
881 fdata->cinfo->col_buf[i][0] = '\0';
882 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
887 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
888 union wtap_pseudo_header *pseudo_header, const u_char *buf)
890 cb_args_t *args = (cb_args_t *) user;
891 capture_file *cf = args->cf;
892 wtap_dumper *pdh = args->pdh;
894 proto_tree *protocol_tree;
901 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
902 protocol_tree = proto_tree_create_root();
903 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
904 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len);
906 protocol_tree = NULL;
911 /* XXX - do something if this fails */
912 wtap_dump(pdh, phdr, pseudo_header, buf, &err);
914 if (protocol_tree != NULL)
915 proto_tree_free(protocol_tree);
917 epan_dissect_free(edt);
921 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
922 union wtap_pseudo_header *pseudo_header, const u_char *buf)
924 cb_args_t *args = (cb_args_t *) user;
925 capture_file *cf = args->cf;
927 proto_tree *protocol_tree;
929 print_args_t print_args;
935 /* The protocol tree will be "visible", i.e., printed, only if we're
936 not printing a summary. */
937 proto_tree_is_visible = verbose;
939 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
942 if (cf->rfcode || verbose)
943 protocol_tree = proto_tree_create_root();
945 protocol_tree = NULL;
946 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
948 passed = dfilter_apply(cf->rfcode, protocol_tree, buf, fdata.cap_len);
950 /* The packet passed the read filter. */
952 /* Print the information in the protocol tree. */
953 print_args.to_file = TRUE;
954 print_args.format = PR_FMT_TEXT;
955 print_args.print_summary = FALSE;
956 print_args.print_hex = print_hex;
957 print_args.expand_all = TRUE;
958 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
959 buf, &fdata, stdout);
961 /* "print_hex_data()" will put out a leading blank line, as well
962 as a trailing one; print one here, to separate the packets,
963 only if "print_hex_data()" won't be called. */
967 /* Just fill in the columns. */
968 fill_in_columns(&fdata);
970 /* Now print them. */
971 for (i = 0; i < cf->cinfo.num_cols; i++) {
972 switch (cf->cinfo.col_fmt[i]) {
975 * Don't print this if we're doing a live capture from a network
976 * interface - if we're doing a live capture, you won't be
977 * able to look at the capture in the future (it's not being
978 * saved anywhere), so the frame numbers are unlikely to be
981 * (XXX - it might be nice to be able to save and print at
982 * the same time, sort of like an "Update list of packets
983 * in real time" capture in Ethereal.)
985 if (cf->iface != NULL)
987 printf("%3s", cf->cinfo.col_data[i]);
993 case COL_ABS_DATE_TIME: /* XXX - wider */
994 printf("%10s", cf->cinfo.col_data[i]);
1000 case COL_DEF_DL_SRC:
1001 case COL_RES_DL_SRC:
1002 case COL_UNRES_DL_SRC:
1003 case COL_DEF_NET_SRC:
1004 case COL_RES_NET_SRC:
1005 case COL_UNRES_NET_SRC:
1006 printf("%12s", cf->cinfo.col_data[i]);
1012 case COL_DEF_DL_DST:
1013 case COL_RES_DL_DST:
1014 case COL_UNRES_DL_DST:
1015 case COL_DEF_NET_DST:
1016 case COL_RES_NET_DST:
1017 case COL_UNRES_NET_DST:
1018 printf("%-12s", cf->cinfo.col_data[i]);
1022 printf("%s", cf->cinfo.col_data[i]);
1025 if (i != cf->cinfo.num_cols - 1) {
1027 * This isn't the last column, so we need to print a
1028 * separator between this column and the next.
1030 * If we printed a network source and are printing a
1031 * network destination of the same type next, separate
1032 * them with "->"; if we printed a network destination
1033 * and are printing a network source of the same type
1034 * next, separate them with "<-"; otherwise separate them
1037 switch (cf->cinfo.col_fmt[i]) {
1042 switch (cf->cinfo.col_fmt[i + 1]) {
1056 case COL_DEF_DL_SRC:
1057 case COL_RES_DL_SRC:
1058 case COL_UNRES_DL_SRC:
1059 switch (cf->cinfo.col_fmt[i + 1]) {
1061 case COL_DEF_DL_DST:
1062 case COL_RES_DL_DST:
1063 case COL_UNRES_DL_DST:
1073 case COL_DEF_NET_SRC:
1074 case COL_RES_NET_SRC:
1075 case COL_UNRES_NET_SRC:
1076 switch (cf->cinfo.col_fmt[i + 1]) {
1078 case COL_DEF_NET_DST:
1079 case COL_RES_NET_DST:
1080 case COL_UNRES_NET_DST:
1093 switch (cf->cinfo.col_fmt[i + 1]) {
1107 case COL_DEF_DL_DST:
1108 case COL_RES_DL_DST:
1109 case COL_UNRES_DL_DST:
1110 switch (cf->cinfo.col_fmt[i + 1]) {
1112 case COL_DEF_DL_SRC:
1113 case COL_RES_DL_SRC:
1114 case COL_UNRES_DL_SRC:
1124 case COL_DEF_NET_DST:
1125 case COL_RES_NET_DST:
1126 case COL_UNRES_NET_DST:
1127 switch (cf->cinfo.col_fmt[i + 1]) {
1129 case COL_DEF_NET_SRC:
1130 case COL_RES_NET_SRC:
1131 case COL_UNRES_NET_SRC:
1150 print_hex_data(stdout, print_args.format, buf,
1151 fdata.cap_len, fdata.flags.encoding);
1156 if (protocol_tree != NULL)
1157 proto_tree_free(protocol_tree);
1159 epan_dissect_free(edt);
1161 proto_tree_is_visible = FALSE;
1165 file_open_error_message(int err, gboolean for_writing)
1168 static char errmsg_errno[1024+1];
1172 case WTAP_ERR_NOT_REGULAR_FILE:
1173 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1176 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1177 case WTAP_ERR_UNSUPPORTED:
1178 /* Seen only when opening a capture file for reading. */
1179 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1182 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1183 /* Seen only when opening a capture file for writing. */
1184 errmsg = "Tethereal does not support writing capture files in that format.";
1187 case WTAP_ERR_UNSUPPORTED_ENCAP:
1188 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1190 errmsg = "Tethereal cannot save this capture in that format.";
1192 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1195 case WTAP_ERR_BAD_RECORD:
1196 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1199 case WTAP_ERR_CANT_OPEN:
1201 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1203 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1206 case WTAP_ERR_SHORT_READ:
1207 errmsg = "The file \"%s\" appears to have been cut short"
1208 " in the middle of a packet.";
1211 case WTAP_ERR_SHORT_WRITE:
1212 errmsg = "A full header couldn't be written to the file \"%s\".";
1217 errmsg = "The path to the file \"%s\" does not exist.";
1219 errmsg = "The file \"%s\" does not exist.";
1224 errmsg = "You do not have permission to create or write to the file \"%s\".";
1226 errmsg = "You do not have permission to read the file \"%s\".";
1230 errmsg = "\"%s\" is a directory (folder), not a file.";
1234 snprintf(errmsg_errno, sizeof(errmsg_errno),
1235 "The file \"%%s\" could not be opened: %s.",
1236 wtap_strerror(err));
1237 errmsg = errmsg_errno;
1244 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1250 struct stat cf_stat;
1251 char err_msg[2048+1];
1253 wth = wtap_open_offline(fname, &err, FALSE);
1257 /* Find the size of the file. */
1258 fh = wtap_file(wth);
1260 if (fstat(fd, &cf_stat) < 0) {
1266 /* The open succeeded. Fill in the information for this file. */
1268 /* Initialize the table of conversations. */
1269 epan_conversation_init();
1271 /* Initialize protocol-specific variables */
1272 init_all_protocols();
1276 cf->f_len = cf_stat.st_size;
1278 /* Set the file name because we need it to set the follow stream filter.
1279 XXX - is that still true? We need it for other reasons, though,
1281 cf->filename = g_strdup(fname);
1283 /* Indicate whether it's a permanent or temporary file. */
1284 cf->is_tempfile = is_tempfile;
1286 /* If it's a temporary capture buffer file, mark it as not saved. */
1287 cf->user_saved = !is_tempfile;
1289 cf->cd_t = wtap_file_type(cf->wth);
1294 cf->snap = wtap_snapshot_length(cf->wth);
1295 cf->progbar_quantum = 0;
1296 cf->progbar_nextstep = 0;
1297 firstsec = 0, firstusec = 0;
1298 prevsec = 0, prevusec = 0;
1303 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1304 fprintf(stderr, "tethereal: %s\n", err_msg);