3 * $Id: tethereal.c,v 1.68 2001/02/18 03:38:42 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
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;
102 static gboolean line_buffered;
105 typedef struct _loop_data {
113 static int capture(int, int);
114 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
116 static void capture_cleanup(int);
124 static int load_cap_file(capture_file *, int);
125 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
126 union wtap_pseudo_header *, const u_char *);
127 static void show_capture_file_io_error(const char *, int, gboolean);
128 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
129 union wtap_pseudo_header *, const u_char *);
133 FILE *data_out_file = NULL;
134 guint main_ctx, file_ctx;
135 ts_type timestamp_type = RELATIVE;
137 static int promisc_mode = TRUE;
145 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
146 VERSION, comp_info_str);
148 fprintf(stderr, "t%s [ -vVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
149 fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
150 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
151 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
153 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
154 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
155 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
157 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
158 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
159 if (wtap_dump_can_open(i))
160 fprintf(stderr, "\t%s - %s\n",
161 wtap_file_type_short_string(i), wtap_file_type_string(i));
163 fprintf(stderr, "\tdefault is libpcap\n");
167 main(int argc, char *argv[])
171 gboolean arg_error = FALSE;
174 char pcap_version[] = "0.4a6";
176 extern char pcap_version[];
184 char *gpf_path, *pf_path;
185 int gpf_open_errno, pf_open_errno;
188 gboolean capture_filter_specified = FALSE;
189 int packet_count = 0;
191 gchar err_str[PCAP_ERRBUF_SIZE];
193 gboolean capture_option_specified = FALSE;
195 int out_file_type = WTAP_FILE_PCAP;
196 gchar *cf_name = NULL, *rfilter = NULL;
197 dfilter_t *rfcode = NULL;
200 /* Register all dissectors; we must do this before checking for the
201 "-G" flag, as the "-G" flag dumps a list of fields registered
202 by the dissectors, and we must do it before we read the preferences,
203 in case any dissectors register preferences. */
204 epan_init(PLUGIN_DIR);
206 /* Now register the preferences for any non-dissector modules.
207 We must do that before we read the preferences as well. */
208 prefs_register_modules();
210 /* If invoked with the "-G" flag, we dump out a glossary of
211 display filter symbols.
213 We do this here to mirror what happens in the GTK+ version, although
214 it's not necessary here. */
215 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
216 proto_registrar_dump();
220 /* Set the C-language locale to the native environment. */
221 setlocale(LC_ALL, "");
223 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
224 if (gpf_path != NULL) {
225 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
226 strerror(gpf_open_errno));
228 if (pf_path != NULL) {
229 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
230 strerror(pf_open_errno));
233 /* Initialize the capture file struct */
235 cfile.plist_end = NULL;
237 cfile.filename = NULL;
238 cfile.user_saved = FALSE;
239 cfile.is_tempfile = FALSE;
241 cfile.dfilter = NULL;
244 cfile.cfilter = g_strdup("");
247 cfile.save_file = NULL;
248 cfile.save_file_fd = -1;
249 cfile.snap = WTAP_MAX_PACKET_SIZE;
251 col_init(&cfile.cinfo, prefs->num_cols);
253 /* Assemble the compile-time options */
254 snprintf(comp_info_str, 256,
255 #ifdef GTK_MAJOR_VERSION
256 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
259 "GTK+ (version unknown), %s%s, %s%s, %s%s",
263 "with libpcap ", pcap_version,
265 "without libpcap", "",
270 "with libz ", ZLIB_VERSION,
271 #else /* ZLIB_VERSION */
272 "with libz ", "(version unknown)",
273 #endif /* ZLIB_VERSION */
274 #else /* HAVE_LIBZ */
276 #endif /* HAVE_LIBZ */
278 /* Oh, this is pretty */
279 #if defined(HAVE_UCD_SNMP_SNMP_H)
280 #ifdef HAVE_UCD_SNMP_VERSION_H
281 "with UCD SNMP ", VersionInfo
282 #else /* HAVE_UCD_SNMP_VERSION_H */
283 "with UCD SNMP ", "(version unknown)"
284 #endif /* HAVE_UCD_SNMP_VERSION_H */
285 #elif defined(HAVE_SNMP_SNMP_H)
286 #ifdef HAVE_SNMP_VERSION_H
287 "with CMU SNMP ", snmp_Version()
288 #else /* HAVE_SNMP_VERSION_H */
289 "with CMU SNMP ", "(version unknown)"
290 #endif /* HAVE_SNMP_VERSION_H */
296 /* Now get our args */
297 while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
299 case 'c': /* Capture xxx packets */
301 packet_count = atoi(optarg);
303 capture_option_specified = TRUE;
309 capture_filter_specified = TRUE;
310 cfile.cfilter = g_strdup(optarg);
312 capture_option_specified = TRUE;
317 out_file_type = wtap_short_string_to_file_type(optarg);
318 if (out_file_type < 0) {
319 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
324 case 'h': /* Print help and exit */
328 case 'i': /* Use interface xxx */
330 cfile.iface = g_strdup(optarg);
332 capture_option_specified = TRUE;
336 case 'l': /* "Line-buffer" standard output */
337 /* This isn't line-buffering, strictly speaking, it's just
338 flushing the standard output after the information for
339 each packet is printed; however, that should be good
340 enough for all the purposes to which "-l" is put.
342 See the comment in "wtap_dispatch_cb_print()" for an
343 explanation of why we do that, and why we don't just
344 use "setvbuf()" to make the standard output line-buffered
345 (short version: in Windows, "line-buffered" is the same
346 as "fully-buffered", and the output buffer is only flushed
347 when it fills up). */
348 line_buffered = TRUE;
350 case 'n': /* No name resolution */
351 g_resolving_actif = 0;
353 case 'o': /* Override preference from command line */
354 switch (prefs_set_pref(optarg)) {
356 case PREFS_SET_SYNTAX_ERR:
357 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
361 case PREFS_SET_NO_SUCH_PREF:
362 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
368 case 'p': /* Don't capture in promiscuous mode */
372 capture_option_specified = TRUE;
376 case 'r': /* Read capture file xxx */
377 cf_name = g_strdup(optarg);
379 case 'R': /* Read file filter */
382 case 's': /* Set the snapshot (capture) length */
384 cfile.snap = atoi(optarg);
386 capture_option_specified = TRUE;
390 case 't': /* Time stamp type */
391 if (strcmp(optarg, "r") == 0)
392 timestamp_type = RELATIVE;
393 else if (strcmp(optarg, "a") == 0)
394 timestamp_type = ABSOLUTE;
395 else if (strcmp(optarg, "ad") == 0)
396 timestamp_type = ABSOLUTE_WITH_DATE;
397 else if (strcmp(optarg, "d") == 0)
398 timestamp_type = DELTA;
400 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
402 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
403 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
407 case 'v': /* Show version and exit */
408 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
411 case 'w': /* Write to capture file xxx */
412 cfile.save_file = g_strdup(optarg);
414 case 'V': /* Verbose */
417 case 'x': /* Print packet data in hex (and ASCII) */
423 /* If no capture filter or read filter has been specified, and there are
424 still command-line arguments, treat them as the tokens of a capture
425 filter (if no "-r" flag was specified) or a read filter (if a "-r"
426 flag was specified. */
428 if (cf_name != NULL) {
429 if (rfilter != NULL) {
431 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
434 rfilter = get_args_as_string(argc, argv, optind);
437 if (capture_filter_specified) {
439 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
442 cfile.cfilter = get_args_as_string(argc, argv, optind);
444 capture_option_specified = TRUE;
450 /* Start windows sockets */
451 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
454 /* Notify all registered modules that have had any of their preferences
455 changed either from one of the preferences file or from the command
456 line that its preferences have changed. */
460 if (capture_option_specified)
461 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
466 /* Build the column format array */
467 for (i = 0; i < cfile.cinfo.num_cols; i++) {
468 cfile.cinfo.col_fmt[i] = get_column_format(i);
469 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
470 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
472 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
473 cfile.cinfo.col_data[i] = NULL;
474 if (cfile.cinfo.col_fmt[i] == COL_INFO)
475 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
477 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
481 cfile.snap = WTAP_MAX_PACKET_SIZE;
482 else if (cfile.snap < MIN_PACKET_SIZE)
483 cfile.snap = MIN_PACKET_SIZE;
485 if (rfilter != NULL) {
486 if (!dfilter_compile(rfilter, &rfcode)) {
487 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
492 cfile.rfcode = rfcode;
494 err = open_cap_file(cf_name, FALSE, &cfile);
499 err = load_cap_file(&cfile, out_file_type);
506 /* No capture file specified, so we're supposed to do a live capture;
507 do we have support for live captures? */
509 /* Yes; did the user specify an interface to use? */
510 if (cfile.iface == NULL) {
511 /* No - pick the first one from the list of interfaces. */
512 if_list = get_interface_list(&err, err_str);
513 if (if_list == NULL) {
516 case CANT_GET_INTERFACE_LIST:
517 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
521 case NO_INTERFACES_FOUND:
522 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
527 cfile.iface = g_strdup(if_list->data); /* first interface */
528 free_interface_list(if_list);
530 capture(packet_count, out_file_type);
533 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
544 /* Do the low-level work of a capture.
545 Returns TRUE if it succeeds, FALSE otherwise. */
547 capture(int packet_count, int out_file_type)
549 gchar err_str[PCAP_ERRBUF_SIZE];
550 bpf_u_int32 netnum, netmask;
551 struct bpf_program fcode;
552 void (*oldhandler)(int);
556 static const char ppamsg[] = "can't find PPA for ";
559 struct pcap_stat stats;
561 /* Initialize the table of conversations. */
562 epan_conversation_init();
564 /* Initialize protocol-specific variables */
565 init_all_protocols();
567 ld.linktype = WTAP_ENCAP_UNKNOWN;
570 /* Open the network interface to capture from it. */
571 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
573 if (ld.pch == NULL) {
574 /* Well, we couldn't start the capture. */
576 /* On Win32 OSes, the capture devices are probably available to all
577 users; don't warn about permissions problems.
579 Do, however, warn that Token Ring and PPP devices aren't supported. */
580 snprintf(errmsg, sizeof errmsg,
581 "The capture session could not be initiated (%s).\n"
582 "Please check that you have the proper interface specified.\n"
584 "Note that the driver Tethereal uses for packet capture on Windows\n"
585 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
586 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
589 /* If we got a "can't find PPA for XXX" message, warn the user (who
590 is running Ethereal on HP-UX) that they don't have a version
591 of libpcap patched to properly handle HP-UX (the patched version
592 says "can't find /dev/dlpi PPA for XXX" rather than "can't find
594 if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
597 "You are running Tethereal with a version of the libpcap library\n"
598 "that doesn't handle HP-UX network devices well; this means that\n"
599 "Tethereal may not be able to capture packets.\n"
601 "To fix this, you will need to download the source to Tethereal\n"
602 "from www.ethereal.com if you have not already done so, read\n"
603 "the instructions in the \"README.hpux\" file in the source\n"
604 "distribution, download the source to libpcap if you have not\n"
605 "already done so, patch libpcap as per the instructions, rebuild\n"
606 "and install libpcap, and then build Tethereal (if you have already\n"
607 "built Tethereal from source, do a \"make distclean\" and re-run\n"
608 "configure before building).";
611 snprintf(errmsg, sizeof errmsg,
612 "The capture session could not be initiated (%s).\n"
613 "Please check to make sure you have sufficient permissions, and that\n"
614 "you have the proper interface specified.%s", err_str, libpcap_warn);
620 /* A capture filter was specified; set it up. */
621 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
623 * Well, we can't get the netmask for this interface; it's used
624 * only for filters that check for broadcast IP addresses, so
625 * we just warn the user, and punt and use 0.
628 "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
631 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
632 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
633 pcap_geterr(ld.pch));
636 if (pcap_setfilter(ld.pch, &fcode) < 0) {
637 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
638 pcap_geterr(ld.pch));
643 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
644 if (cfile.save_file != NULL) {
645 /* Set up to write to the capture file. */
646 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
647 strcpy(errmsg, "The network you're capturing from is of a type"
648 " that Tethereal doesn't support.");
651 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
652 ld.linktype, pcap_snapshot(ld.pch), &err);
654 if (ld.pdh == NULL) {
655 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
661 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
663 XXX - deal with signal semantics on various platforms. Or just
664 use "sigaction()" and be done with it? */
665 signal(SIGTERM, capture_cleanup);
666 signal(SIGINT, capture_cleanup);
668 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
669 signal(SIGHUP, oldhandler);
672 /* Let the user know what interface was chosen. */
673 fprintf(stderr, "Capturing on %s\n", cfile.iface);
676 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
678 if (cfile.save_file != NULL) {
679 /* We're saving to a file, which means we're printing packet counts
680 to the standard output. Send a newline so that we move to the
681 line after the packet count. */
682 fprintf(stderr, "\n");
685 /* If we got an error while capturing, report it. */
687 fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
688 pcap_geterr(ld.pch));
691 /* Get the capture statistics, and, if any packets were dropped, report
693 if (pcap_stats(ld.pch, &stats) >= 0) {
694 if (stats.ps_drop != 0) {
695 fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
698 fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
699 pcap_geterr(ld.pch));
706 g_free(cfile.save_file);
707 cfile.save_file = NULL;
708 fprintf(stderr, "tethereal: %s\n", errmsg);
716 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
719 struct wtap_pkthdr whdr;
720 loop_data *ld = (loop_data *) user;
723 whdr.ts.tv_sec = phdr->ts.tv_sec;
724 whdr.ts.tv_usec = phdr->ts.tv_usec;
725 whdr.caplen = phdr->caplen;
726 whdr.len = phdr->len;
727 whdr.pkt_encap = ld->linktype;
732 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
733 fprintf(stderr, "\r%u ", cfile.count);
736 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
741 capture_cleanup(int signum)
745 fprintf(stderr, "\n");
747 if (ld.pdh != NULL) {
748 if (!wtap_dump_close(ld.pdh, &err)) {
749 show_capture_file_io_error(cfile.save_file, err, TRUE);
755 #endif /* HAVE_LIBPCAP */
758 load_cap_file(capture_file *cf, int out_file_type)
766 linktype = wtap_file_encap(cf->wth);
767 if (cf->save_file != NULL) {
768 /* Set up to write to the capture file. */
769 pdh = wtap_dump_open(cf->save_file, out_file_type,
770 linktype, wtap_snapshot_length(cf->wth), &err);
773 /* We couldn't set up to write to the capture file. */
776 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
778 "tethereal: Capture files can't be written in that format.\n");
781 case WTAP_ERR_UNSUPPORTED_ENCAP:
782 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
784 "tethereal: The capture file being read cannot be written in that format.\n");
787 case WTAP_ERR_CANT_OPEN:
789 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
793 case WTAP_ERR_SHORT_WRITE:
795 "tethereal: A full header couldn't be written to the file \"%s\".\n",
802 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
806 "tethereal: The file \"%s\" could not be opened: %s\n.",
807 cf->save_file, strerror(err));
815 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
820 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
824 /* Print up a message box noting that the read failed somewhere along
828 case WTAP_ERR_UNSUPPORTED_ENCAP:
830 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
834 case WTAP_ERR_CANT_READ:
836 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
840 case WTAP_ERR_SHORT_READ:
842 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
846 case WTAP_ERR_BAD_RECORD:
848 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
854 "tethereal: An error occurred while reading \"%s\": %s.\n",
855 cf->filename, wtap_strerror(err));
868 fill_in_fdata(frame_data *fdata, capture_file *cf,
869 const struct wtap_pkthdr *phdr,
870 const union wtap_pseudo_header *pseudo_header, int offset)
877 fdata->num = cf->count;
878 fdata->pkt_len = phdr->len;
879 fdata->cap_len = phdr->caplen;
880 fdata->file_off = offset;
882 fdata->lnk_t = phdr->pkt_encap;
883 fdata->abs_secs = phdr->ts.tv_sec;
884 fdata->abs_usecs = phdr->ts.tv_usec;
885 fdata->flags.passed_dfilter = 0;
886 fdata->flags.encoding = CHAR_ASCII;
887 fdata->flags.visited = 0;
888 fdata->flags.marked = 0;
890 /* If we don't have the time stamp of the first packet in the
891 capture, it's because this is the first packet. Save the time
892 stamp of this packet as the time stamp of the first packet. */
893 if (!firstsec && !firstusec) {
894 firstsec = fdata->abs_secs;
895 firstusec = fdata->abs_usecs;
898 /* If we don't have the time stamp of the previous displayed packet,
899 it's because this is the first displayed packet. Save the time
900 stamp of this packet as the time stamp of the previous displayed
902 if (!prevsec && !prevusec) {
903 prevsec = fdata->abs_secs;
904 prevusec = fdata->abs_usecs;
907 /* Get the time elapsed between the first packet and this packet. */
908 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
909 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
911 /* If it's greater than the current elapsed time, set the elapsed time
912 to it (we check for "greater than" so as not to be confused by
913 time moving backwards). */
914 if (cf->esec < fdata->rel_secs
915 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
916 cf->esec = fdata->rel_secs;
917 cf->eusec = fdata->rel_usecs;
920 /* Get the time elapsed between the previous displayed packet and
922 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
923 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
924 prevsec = fdata->abs_secs;
925 prevusec = fdata->abs_usecs;
927 fdata->cinfo = &cf->cinfo;
928 for (i = 0; i < fdata->cinfo->num_cols; i++) {
929 fdata->cinfo->col_buf[i][0] = '\0';
930 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
935 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
936 union wtap_pseudo_header *pseudo_header, const u_char *buf)
938 cb_args_t *args = (cb_args_t *) user;
939 capture_file *cf = args->cf;
940 wtap_dumper *pdh = args->pdh;
942 proto_tree *protocol_tree;
949 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
950 protocol_tree = proto_tree_create_root();
951 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
952 passed = dfilter_apply_edt(cf->rfcode, edt);
954 protocol_tree = NULL;
959 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
961 if (ld.pch != NULL) {
962 /* We're capturing packets, so we're printing a count of packets
963 captured; move to the line after the count. */
964 fprintf(stderr, "\n");
967 show_capture_file_io_error(cf->save_file, err, FALSE);
972 wtap_dump_close(pdh, &err);
976 if (protocol_tree != NULL)
977 proto_tree_free(protocol_tree);
979 epan_dissect_free(edt);
983 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
989 "tethereal: Not all the packets could be written to \"%s\" because there is "
990 "no space left on the file system.\n",
997 "tethereal: Not all the packets could be written to \"%s\" because you are "
998 "too close to, or over your disk quota.\n",
1003 case WTAP_ERR_CANT_CLOSE:
1005 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1009 case WTAP_ERR_SHORT_WRITE:
1011 "tethereal: Not all the packets could be written to \"%s\".\n",
1018 "tethereal: \"%s\" could not be closed: %s.\n",
1019 fname, wtap_strerror(err));
1022 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1023 fname, wtap_strerror(err));
1030 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1031 union wtap_pseudo_header *pseudo_header, const u_char *buf)
1033 cb_args_t *args = (cb_args_t *) user;
1034 capture_file *cf = args->cf;
1036 proto_tree *protocol_tree;
1038 print_args_t print_args;
1039 epan_dissect_t *edt;
1044 /* The protocol tree will be "visible", i.e., printed, only if we're
1045 not printing a summary. */
1046 proto_tree_is_visible = verbose;
1048 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1051 if (cf->rfcode || verbose)
1052 protocol_tree = proto_tree_create_root();
1054 protocol_tree = NULL;
1055 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1057 passed = dfilter_apply_edt(cf->rfcode, edt);
1059 /* The packet passed the read filter. */
1061 /* Print the information in the protocol tree. */
1062 print_args.to_file = TRUE;
1063 print_args.format = PR_FMT_TEXT;
1064 print_args.print_summary = FALSE;
1065 print_args.print_hex = print_hex;
1066 print_args.expand_all = TRUE;
1067 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1068 buf, &fdata, stdout);
1070 /* "print_hex_data()" will put out a leading blank line, as well
1071 as a trailing one; print one here, to separate the packets,
1072 only if "print_hex_data()" won't be called. */
1076 /* Just fill in the columns. */
1077 fill_in_columns(&fdata);
1079 /* Now print them. */
1080 for (i = 0; i < cf->cinfo.num_cols; i++) {
1081 switch (cf->cinfo.col_fmt[i]) {
1084 * Don't print this if we're doing a live capture from a network
1085 * interface - if we're doing a live capture, you won't be
1086 * able to look at the capture in the future (it's not being
1087 * saved anywhere), so the frame numbers are unlikely to be
1090 * (XXX - it might be nice to be able to save and print at
1091 * the same time, sort of like an "Update list of packets
1092 * in real time" capture in Ethereal.)
1094 if (cf->iface != NULL)
1096 printf("%3s", cf->cinfo.col_data[i]);
1102 case COL_ABS_DATE_TIME: /* XXX - wider */
1103 printf("%10s", cf->cinfo.col_data[i]);
1109 case COL_DEF_DL_SRC:
1110 case COL_RES_DL_SRC:
1111 case COL_UNRES_DL_SRC:
1112 case COL_DEF_NET_SRC:
1113 case COL_RES_NET_SRC:
1114 case COL_UNRES_NET_SRC:
1115 printf("%12s", cf->cinfo.col_data[i]);
1121 case COL_DEF_DL_DST:
1122 case COL_RES_DL_DST:
1123 case COL_UNRES_DL_DST:
1124 case COL_DEF_NET_DST:
1125 case COL_RES_NET_DST:
1126 case COL_UNRES_NET_DST:
1127 printf("%-12s", cf->cinfo.col_data[i]);
1131 printf("%s", cf->cinfo.col_data[i]);
1134 if (i != cf->cinfo.num_cols - 1) {
1136 * This isn't the last column, so we need to print a
1137 * separator between this column and the next.
1139 * If we printed a network source and are printing a
1140 * network destination of the same type next, separate
1141 * them with "->"; if we printed a network destination
1142 * and are printing a network source of the same type
1143 * next, separate them with "<-"; otherwise separate them
1146 switch (cf->cinfo.col_fmt[i]) {
1151 switch (cf->cinfo.col_fmt[i + 1]) {
1165 case COL_DEF_DL_SRC:
1166 case COL_RES_DL_SRC:
1167 case COL_UNRES_DL_SRC:
1168 switch (cf->cinfo.col_fmt[i + 1]) {
1170 case COL_DEF_DL_DST:
1171 case COL_RES_DL_DST:
1172 case COL_UNRES_DL_DST:
1182 case COL_DEF_NET_SRC:
1183 case COL_RES_NET_SRC:
1184 case COL_UNRES_NET_SRC:
1185 switch (cf->cinfo.col_fmt[i + 1]) {
1187 case COL_DEF_NET_DST:
1188 case COL_RES_NET_DST:
1189 case COL_UNRES_NET_DST:
1202 switch (cf->cinfo.col_fmt[i + 1]) {
1216 case COL_DEF_DL_DST:
1217 case COL_RES_DL_DST:
1218 case COL_UNRES_DL_DST:
1219 switch (cf->cinfo.col_fmt[i + 1]) {
1221 case COL_DEF_DL_SRC:
1222 case COL_RES_DL_SRC:
1223 case COL_UNRES_DL_SRC:
1233 case COL_DEF_NET_DST:
1234 case COL_RES_NET_DST:
1235 case COL_UNRES_NET_DST:
1236 switch (cf->cinfo.col_fmt[i + 1]) {
1238 case COL_DEF_NET_SRC:
1239 case COL_RES_NET_SRC:
1240 case COL_UNRES_NET_SRC:
1259 print_hex_data(stdout, print_args.format, buf,
1260 fdata.cap_len, fdata.flags.encoding);
1266 /* The ANSI C standard does not appear to *require* that a line-buffered
1267 stream be flushed to the host environment whenever a newline is
1268 written, it just says that, on such a stream, characters "are
1269 intended to be transmitted to or from the host environment as a
1270 block when a new-line character is encountered".
1272 The Visual C++ 6.0 C implementation doesn't do what is intended;
1273 even if you set a stream to be line-buffered, it still doesn't
1274 flush the buffer at the end of every line.
1276 So, if the "-l" flag was specified, we flush the standard output
1277 at the end of a packet. This will do the right thing if we're
1278 printing packet summary lines, and, as we print the entire protocol
1279 tree for a single packet without waiting for anything to happen,
1280 it should be as good as line-buffered mode if we're printing
1281 protocol trees. (The whole reason for the "-l" flag in either
1282 tcpdump or Tethereal is to allow the output of a live capture to
1283 be piped to a program or script and to have that script see the
1284 information for the packet as soon as it's printed, rather than
1285 having to wait until a standard I/O buffer fills up. */
1288 if (protocol_tree != NULL)
1289 proto_tree_free(protocol_tree);
1291 epan_dissect_free(edt);
1293 proto_tree_is_visible = FALSE;
1297 file_open_error_message(int err, gboolean for_writing)
1300 static char errmsg_errno[1024+1];
1304 case WTAP_ERR_NOT_REGULAR_FILE:
1305 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1308 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1309 case WTAP_ERR_UNSUPPORTED:
1310 /* Seen only when opening a capture file for reading. */
1311 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1314 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1315 /* Seen only when opening a capture file for writing. */
1316 errmsg = "Tethereal does not support writing capture files in that format.";
1319 case WTAP_ERR_UNSUPPORTED_ENCAP:
1320 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1322 errmsg = "Tethereal cannot save this capture in that format.";
1324 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1327 case WTAP_ERR_BAD_RECORD:
1328 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1331 case WTAP_ERR_CANT_OPEN:
1333 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1335 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1338 case WTAP_ERR_SHORT_READ:
1339 errmsg = "The file \"%s\" appears to have been cut short"
1340 " in the middle of a packet.";
1343 case WTAP_ERR_SHORT_WRITE:
1344 errmsg = "A full header couldn't be written to the file \"%s\".";
1349 errmsg = "The path to the file \"%s\" does not exist.";
1351 errmsg = "The file \"%s\" does not exist.";
1356 errmsg = "You do not have permission to create or write to the file \"%s\".";
1358 errmsg = "You do not have permission to read the file \"%s\".";
1362 errmsg = "\"%s\" is a directory (folder), not a file.";
1366 snprintf(errmsg_errno, sizeof(errmsg_errno),
1367 "The file \"%%s\" could not be opened: %s.",
1368 wtap_strerror(err));
1369 errmsg = errmsg_errno;
1376 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1382 struct stat cf_stat;
1383 char err_msg[2048+1];
1385 wth = wtap_open_offline(fname, &err, FALSE);
1389 /* Find the size of the file. */
1390 fh = wtap_file(wth);
1392 if (fstat(fd, &cf_stat) < 0) {
1398 /* The open succeeded. Fill in the information for this file. */
1400 /* Initialize the table of conversations. */
1401 epan_conversation_init();
1403 /* Initialize protocol-specific variables */
1404 init_all_protocols();
1408 cf->f_len = cf_stat.st_size;
1410 /* Set the file name because we need it to set the follow stream filter.
1411 XXX - is that still true? We need it for other reasons, though,
1413 cf->filename = g_strdup(fname);
1415 /* Indicate whether it's a permanent or temporary file. */
1416 cf->is_tempfile = is_tempfile;
1418 /* If it's a temporary capture buffer file, mark it as not saved. */
1419 cf->user_saved = !is_tempfile;
1421 cf->cd_t = wtap_file_type(cf->wth);
1423 cf->drops_known = FALSE;
1427 cf->snap = wtap_snapshot_length(cf->wth);
1428 cf->progbar_quantum = 0;
1429 cf->progbar_nextstep = 0;
1430 firstsec = 0, firstusec = 0;
1431 prevsec = 0, prevusec = 0;
1436 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1437 fprintf(stderr, "tethereal: %s\n", err_msg);