3 * $Id: tethereal.c,v 1.70 2001/03/24 09:24:41 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->data_src = NULL;
878 fdata->num = cf->count;
879 fdata->pkt_len = phdr->len;
880 fdata->cap_len = phdr->caplen;
881 fdata->file_off = offset;
883 fdata->lnk_t = phdr->pkt_encap;
884 fdata->abs_secs = phdr->ts.tv_sec;
885 fdata->abs_usecs = phdr->ts.tv_usec;
886 fdata->flags.passed_dfilter = 0;
887 fdata->flags.encoding = CHAR_ASCII;
888 fdata->flags.visited = 0;
889 fdata->flags.marked = 0;
891 /* If we don't have the time stamp of the first packet in the
892 capture, it's because this is the first packet. Save the time
893 stamp of this packet as the time stamp of the first packet. */
894 if (!firstsec && !firstusec) {
895 firstsec = fdata->abs_secs;
896 firstusec = fdata->abs_usecs;
899 /* If we don't have the time stamp of the previous displayed packet,
900 it's because this is the first displayed packet. Save the time
901 stamp of this packet as the time stamp of the previous displayed
903 if (!prevsec && !prevusec) {
904 prevsec = fdata->abs_secs;
905 prevusec = fdata->abs_usecs;
908 /* Get the time elapsed between the first packet and this packet. */
909 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
910 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
912 /* If it's greater than the current elapsed time, set the elapsed time
913 to it (we check for "greater than" so as not to be confused by
914 time moving backwards). */
915 if (cf->esec < fdata->rel_secs
916 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
917 cf->esec = fdata->rel_secs;
918 cf->eusec = fdata->rel_usecs;
921 /* Get the time elapsed between the previous displayed packet and
923 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
924 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
925 prevsec = fdata->abs_secs;
926 prevusec = fdata->abs_usecs;
928 fdata->cinfo = &cf->cinfo;
929 for (i = 0; i < fdata->cinfo->num_cols; i++) {
930 fdata->cinfo->col_buf[i][0] = '\0';
931 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
935 /* Free up all data attached to a "frame_data" structure. */
937 clear_fdata(frame_data *fdata)
940 g_slist_free(fdata->pfd);
942 g_slist_free(fdata->data_src);
946 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
947 union wtap_pseudo_header *pseudo_header, const u_char *buf)
949 cb_args_t *args = (cb_args_t *) user;
950 capture_file *cf = args->cf;
951 wtap_dumper *pdh = args->pdh;
953 proto_tree *protocol_tree;
960 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
961 protocol_tree = proto_tree_create_root();
962 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
963 passed = dfilter_apply_edt(cf->rfcode, edt);
965 protocol_tree = NULL;
970 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
972 if (ld.pch != NULL) {
973 /* We're capturing packets, so we're printing a count of packets
974 captured; move to the line after the count. */
975 fprintf(stderr, "\n");
978 show_capture_file_io_error(cf->save_file, err, FALSE);
983 wtap_dump_close(pdh, &err);
987 if (protocol_tree != NULL)
988 proto_tree_free(protocol_tree);
990 epan_dissect_free(edt);
995 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1001 "tethereal: Not all the packets could be written to \"%s\" because there is "
1002 "no space left on the file system.\n",
1009 "tethereal: Not all the packets could be written to \"%s\" because you are "
1010 "too close to, or over your disk quota.\n",
1015 case WTAP_ERR_CANT_CLOSE:
1017 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1021 case WTAP_ERR_SHORT_WRITE:
1023 "tethereal: Not all the packets could be written to \"%s\".\n",
1030 "tethereal: \"%s\" could not be closed: %s.\n",
1031 fname, wtap_strerror(err));
1034 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1035 fname, wtap_strerror(err));
1042 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1043 union wtap_pseudo_header *pseudo_header, const u_char *buf)
1045 cb_args_t *args = (cb_args_t *) user;
1046 capture_file *cf = args->cf;
1048 proto_tree *protocol_tree;
1050 print_args_t print_args;
1051 epan_dissect_t *edt;
1056 /* The protocol tree will be "visible", i.e., printed, only if we're
1057 not printing a summary. */
1058 proto_tree_is_visible = verbose;
1060 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1063 if (cf->rfcode || verbose)
1064 protocol_tree = proto_tree_create_root();
1066 protocol_tree = NULL;
1067 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1069 passed = dfilter_apply_edt(cf->rfcode, edt);
1071 /* The packet passed the read filter. */
1073 /* Print the information in the protocol tree. */
1074 print_args.to_file = TRUE;
1075 print_args.format = PR_FMT_TEXT;
1076 print_args.print_summary = FALSE;
1077 print_args.print_hex = print_hex;
1078 print_args.expand_all = TRUE;
1079 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1080 buf, &fdata, stdout);
1082 /* "print_hex_data()" will put out a leading blank line, as well
1083 as a trailing one; print one here, to separate the packets,
1084 only if "print_hex_data()" won't be called. */
1088 /* Just fill in the columns. */
1089 fill_in_columns(&fdata);
1091 /* Now print them. */
1092 for (i = 0; i < cf->cinfo.num_cols; i++) {
1093 switch (cf->cinfo.col_fmt[i]) {
1096 * Don't print this if we're doing a live capture from a network
1097 * interface - if we're doing a live capture, you won't be
1098 * able to look at the capture in the future (it's not being
1099 * saved anywhere), so the frame numbers are unlikely to be
1102 * (XXX - it might be nice to be able to save and print at
1103 * the same time, sort of like an "Update list of packets
1104 * in real time" capture in Ethereal.)
1106 if (cf->iface != NULL)
1108 printf("%3s", cf->cinfo.col_data[i]);
1114 case COL_ABS_DATE_TIME: /* XXX - wider */
1115 printf("%10s", cf->cinfo.col_data[i]);
1121 case COL_DEF_DL_SRC:
1122 case COL_RES_DL_SRC:
1123 case COL_UNRES_DL_SRC:
1124 case COL_DEF_NET_SRC:
1125 case COL_RES_NET_SRC:
1126 case COL_UNRES_NET_SRC:
1127 printf("%12s", cf->cinfo.col_data[i]);
1133 case COL_DEF_DL_DST:
1134 case COL_RES_DL_DST:
1135 case COL_UNRES_DL_DST:
1136 case COL_DEF_NET_DST:
1137 case COL_RES_NET_DST:
1138 case COL_UNRES_NET_DST:
1139 printf("%-12s", cf->cinfo.col_data[i]);
1143 printf("%s", cf->cinfo.col_data[i]);
1146 if (i != cf->cinfo.num_cols - 1) {
1148 * This isn't the last column, so we need to print a
1149 * separator between this column and the next.
1151 * If we printed a network source and are printing a
1152 * network destination of the same type next, separate
1153 * them with "->"; if we printed a network destination
1154 * and are printing a network source of the same type
1155 * next, separate them with "<-"; otherwise separate them
1158 switch (cf->cinfo.col_fmt[i]) {
1163 switch (cf->cinfo.col_fmt[i + 1]) {
1177 case COL_DEF_DL_SRC:
1178 case COL_RES_DL_SRC:
1179 case COL_UNRES_DL_SRC:
1180 switch (cf->cinfo.col_fmt[i + 1]) {
1182 case COL_DEF_DL_DST:
1183 case COL_RES_DL_DST:
1184 case COL_UNRES_DL_DST:
1194 case COL_DEF_NET_SRC:
1195 case COL_RES_NET_SRC:
1196 case COL_UNRES_NET_SRC:
1197 switch (cf->cinfo.col_fmt[i + 1]) {
1199 case COL_DEF_NET_DST:
1200 case COL_RES_NET_DST:
1201 case COL_UNRES_NET_DST:
1214 switch (cf->cinfo.col_fmt[i + 1]) {
1228 case COL_DEF_DL_DST:
1229 case COL_RES_DL_DST:
1230 case COL_UNRES_DL_DST:
1231 switch (cf->cinfo.col_fmt[i + 1]) {
1233 case COL_DEF_DL_SRC:
1234 case COL_RES_DL_SRC:
1235 case COL_UNRES_DL_SRC:
1245 case COL_DEF_NET_DST:
1246 case COL_RES_NET_DST:
1247 case COL_UNRES_NET_DST:
1248 switch (cf->cinfo.col_fmt[i + 1]) {
1250 case COL_DEF_NET_SRC:
1251 case COL_RES_NET_SRC:
1252 case COL_UNRES_NET_SRC:
1271 print_hex_data(stdout, print_args.format, &fdata);
1277 /* The ANSI C standard does not appear to *require* that a line-buffered
1278 stream be flushed to the host environment whenever a newline is
1279 written, it just says that, on such a stream, characters "are
1280 intended to be transmitted to or from the host environment as a
1281 block when a new-line character is encountered".
1283 The Visual C++ 6.0 C implementation doesn't do what is intended;
1284 even if you set a stream to be line-buffered, it still doesn't
1285 flush the buffer at the end of every line.
1287 So, if the "-l" flag was specified, we flush the standard output
1288 at the end of a packet. This will do the right thing if we're
1289 printing packet summary lines, and, as we print the entire protocol
1290 tree for a single packet without waiting for anything to happen,
1291 it should be as good as line-buffered mode if we're printing
1292 protocol trees. (The whole reason for the "-l" flag in either
1293 tcpdump or Tethereal is to allow the output of a live capture to
1294 be piped to a program or script and to have that script see the
1295 information for the packet as soon as it's printed, rather than
1296 having to wait until a standard I/O buffer fills up. */
1299 if (protocol_tree != NULL)
1300 proto_tree_free(protocol_tree);
1302 epan_dissect_free(edt);
1304 clear_fdata(&fdata);
1306 proto_tree_is_visible = FALSE;
1310 file_open_error_message(int err, gboolean for_writing)
1313 static char errmsg_errno[1024+1];
1317 case WTAP_ERR_NOT_REGULAR_FILE:
1318 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1321 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1322 case WTAP_ERR_UNSUPPORTED:
1323 /* Seen only when opening a capture file for reading. */
1324 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1327 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1328 /* Seen only when opening a capture file for writing. */
1329 errmsg = "Tethereal does not support writing capture files in that format.";
1332 case WTAP_ERR_UNSUPPORTED_ENCAP:
1333 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1335 errmsg = "Tethereal cannot save this capture in that format.";
1337 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1340 case WTAP_ERR_BAD_RECORD:
1341 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1344 case WTAP_ERR_CANT_OPEN:
1346 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1348 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1351 case WTAP_ERR_SHORT_READ:
1352 errmsg = "The file \"%s\" appears to have been cut short"
1353 " in the middle of a packet.";
1356 case WTAP_ERR_SHORT_WRITE:
1357 errmsg = "A full header couldn't be written to the file \"%s\".";
1362 errmsg = "The path to the file \"%s\" does not exist.";
1364 errmsg = "The file \"%s\" does not exist.";
1369 errmsg = "You do not have permission to create or write to the file \"%s\".";
1371 errmsg = "You do not have permission to read the file \"%s\".";
1375 errmsg = "\"%s\" is a directory (folder), not a file.";
1379 snprintf(errmsg_errno, sizeof(errmsg_errno),
1380 "The file \"%%s\" could not be opened: %s.",
1381 wtap_strerror(err));
1382 errmsg = errmsg_errno;
1389 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1395 struct stat cf_stat;
1396 char err_msg[2048+1];
1398 wth = wtap_open_offline(fname, &err, FALSE);
1402 /* Find the size of the file. */
1403 fh = wtap_file(wth);
1405 if (fstat(fd, &cf_stat) < 0) {
1411 /* The open succeeded. Fill in the information for this file. */
1413 /* Initialize the table of conversations. */
1414 epan_conversation_init();
1416 /* Initialize protocol-specific variables */
1417 init_all_protocols();
1421 cf->f_len = cf_stat.st_size;
1423 /* Set the file name because we need it to set the follow stream filter.
1424 XXX - is that still true? We need it for other reasons, though,
1426 cf->filename = g_strdup(fname);
1428 /* Indicate whether it's a permanent or temporary file. */
1429 cf->is_tempfile = is_tempfile;
1431 /* If it's a temporary capture buffer file, mark it as not saved. */
1432 cf->user_saved = !is_tempfile;
1434 cf->cd_t = wtap_file_type(cf->wth);
1436 cf->drops_known = FALSE;
1440 cf->snap = wtap_snapshot_length(cf->wth);
1441 cf->progbar_quantum = 0;
1442 cf->progbar_nextstep = 0;
1443 firstsec = 0, firstusec = 0;
1444 prevsec = 0, prevusec = 0;
1449 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1450 fprintf(stderr, "tethereal: %s\n", err_msg);