3 * $Id: tethereal.c,v 1.96 2001/11/04 02:50:19 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@ethereal.com>
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.
43 #ifdef HAVE_SYS_TYPES_H
44 #include <sys/types.h>
47 #ifdef HAVE_SYS_STAT_H
62 #include <zlib.h> /* to get the libz version number */
65 #ifdef NEED_SNPRINTF_H
66 # include "snprintf.h"
69 #if defined(HAVE_UCD_SNMP_SNMP_H)
70 #ifdef HAVE_UCD_SNMP_VERSION_H
71 #include <ucd-snmp/version.h>
72 #endif /* HAVE_UCD_SNMP_VERSION_H */
73 #elif defined(HAVE_SNMP_SNMP_H)
74 #ifdef HAVE_SNMP_VERSION_H
75 #include <snmp/version.h>
76 #endif /* HAVE_SNMP_VERSION_H */
79 #ifdef NEED_STRERROR_H
91 #include "timestamp.h"
99 #include "conversation.h"
100 #include "reassemble.h"
102 #include "register.h"
105 #include "capture-wpcap.h"
108 static guint32 firstsec, firstusec;
109 static guint32 prevsec, prevusec;
110 static GString *comp_info_str;
111 static gboolean verbose;
112 static gboolean print_hex;
113 static gboolean line_buffered;
116 typedef struct _loop_data {
124 static int capture(int, int);
125 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
127 static void capture_cleanup(int);
135 static int load_cap_file(capture_file *, int);
136 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, long,
137 union wtap_pseudo_header *, const u_char *);
138 static void show_capture_file_io_error(const char *, int, gboolean);
139 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, long,
140 union wtap_pseudo_header *, const u_char *);
144 FILE *data_out_file = NULL;
145 ts_type timestamp_type = RELATIVE;
147 static int promisc_mode = TRUE;
155 fprintf(stderr, "This is GNU t%s %s, compiled %s\n", PACKAGE, VERSION,
158 fprintf(stderr, "t%s [ -DvVhlp ] [ -c <count> ] [ -f <capture filter> ]\n", PACKAGE);
159 fprintf(stderr, "\t[ -F <capture file type> ] [ -i <interface> ] [ -n ] [ -N <resolving> ]\n");
160 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
161 fprintf(stderr, "\t[ -s <snaplen> ] [ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
163 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ] [ -N <resolving> ]\n", PACKAGE);
164 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
165 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
167 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
168 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
169 if (wtap_dump_can_open(i))
170 fprintf(stderr, "\t%s - %s\n",
171 wtap_file_type_short_string(i), wtap_file_type_string(i));
173 fprintf(stderr, "\tdefault is libpcap\n");
177 get_positive_int(const char *string, const char *name)
182 number = strtol(string, &p, 10);
183 if (p == string || *p != '\0') {
184 fprintf(stderr, "tethereal: The specified %s \"%s\" is not a decimal number\n",
189 fprintf(stderr, "tethereal: The specified %s \"%s\" is a negative number\n",
193 if (number > INT_MAX) {
194 fprintf(stderr, "tethereal: The specified %s \"%s\" is too large (greater than %d)\n",
195 name, string, INT_MAX);
202 main(int argc, char *argv[])
206 gboolean arg_error = FALSE;
208 #ifdef HAVE_PCAP_VERSION
209 extern char pcap_version[];
210 #endif /* HAVE_PCAP_VERSION */
211 #endif /* HAVE_LIBPCAP */
219 int gpf_open_errno, pf_open_errno;
222 gboolean capture_filter_specified = FALSE;
223 int packet_count = 0;
224 GList *if_list, *if_entry;
225 gchar err_str[PCAP_ERRBUF_SIZE];
227 gboolean capture_option_specified = FALSE;
229 int out_file_type = WTAP_FILE_PCAP;
230 gchar *cf_name = NULL, *rfilter = NULL;
231 dfilter_t *rfcode = NULL;
235 /* Register all dissectors; we must do this before checking for the
236 "-G" flag, as the "-G" flag dumps a list of fields registered
237 by the dissectors, and we must do it before we read the preferences,
238 in case any dissectors register preferences. */
239 epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
241 /* Now register the preferences for any non-dissector modules.
242 We must do that before we read the preferences as well. */
243 prefs_register_modules();
245 /* If invoked with the "-G" flag, we dump out a glossary of
246 display filter symbols.
248 We do this here to mirror what happens in the GTK+ version, although
249 it's not necessary here. */
250 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
251 proto_registrar_dump();
255 /* Set the C-language locale to the native environment. */
256 setlocale(LC_ALL, "");
258 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
259 if (gpf_path != NULL) {
260 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
261 strerror(gpf_open_errno));
263 if (pf_path != NULL) {
264 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
265 strerror(pf_open_errno));
269 /* Load Wpcap, if possible */
273 /* Initialize the capture file struct */
275 cfile.plist_end = NULL;
277 cfile.filename = NULL;
278 cfile.user_saved = FALSE;
279 cfile.is_tempfile = FALSE;
281 cfile.dfilter = NULL;
284 cfile.cfilter = g_strdup("");
287 cfile.save_file = NULL;
288 cfile.save_file_fd = -1;
289 cfile.snap = WTAP_MAX_PACKET_SIZE;
291 col_init(&cfile.cinfo, prefs->num_cols);
293 /* Assemble the compile-time options */
294 comp_info_str = g_string_new("");
296 g_string_append(comp_info_str, "with ");
297 g_string_sprintfa(comp_info_str,
298 #ifdef GLIB_MAJOR_VERSION
299 "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
302 "GLib (version unknown)");
306 g_string_append(comp_info_str, ", with libpcap ");
307 #ifdef HAVE_PCAP_VERSION
308 g_string_append(comp_info_str, pcap_version);
309 #else /* HAVE_PCAP_VERSION */
310 g_string_append(comp_info_str, "(version unknown)");
311 #endif /* HAVE_PCAP_VERSION */
312 #else /* HAVE_LIBPCAP */
313 g_string_append(comp_info_str, ", without libpcap");
314 #endif /* HAVE_LIBPCAP */
317 g_string_append(comp_info_str, ", with libz ");
319 g_string_append(comp_info_str, ZLIB_VERSION);
320 #else /* ZLIB_VERSION */
321 g_string_append(comp_info_str, "(version unknown)");
322 #endif /* ZLIB_VERSION */
323 #else /* HAVE_LIBZ */
324 g_string_append(comp_info_str, ", without libz");
325 #endif /* HAVE_LIBZ */
327 /* Oh, this is pretty */
328 #if defined(HAVE_UCD_SNMP_SNMP_H)
329 g_string_append(comp_info_str, ", with UCD SNMP ");
330 #ifdef HAVE_UCD_SNMP_VERSION_H
331 g_string_append(comp_info_str, VersionInfo);
332 #else /* HAVE_UCD_SNMP_VERSION_H */
333 g_string_append(comp_info_str, "(version unknown)");
334 #endif /* HAVE_UCD_SNMP_VERSION_H */
335 #elif defined(HAVE_SNMP_SNMP_H)
336 g_string_append(comp_info_str, ", with CMU SNMP ");
337 #ifdef HAVE_SNMP_VERSION_H
338 g_string_append(comp_info_str, snmp_Version());
339 #else /* HAVE_SNMP_VERSION_H */
340 g_string_append(comp_info_str, "(version unknown)");
341 #endif /* HAVE_SNMP_VERSION_H */
343 g_string_append(comp_info_str, ", without SNMP");
346 /* Now get our args */
347 while ((opt = getopt(argc, argv, "c:Df:F:hi:lnN:o:pr:R:s:t:vw:Vx")) != EOF) {
349 case 'c': /* Capture xxx packets */
351 packet_count = get_positive_int(optarg, "packet count");
353 capture_option_specified = TRUE;
357 case 'D': /* Print a list of capture devices */
359 if_list = get_interface_list(&err, err_str);
360 if (if_list == NULL) {
363 case CANT_GET_INTERFACE_LIST:
364 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
368 case NO_INTERFACES_FOUND:
369 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
374 for (if_entry = g_list_first(if_list); if_entry != NULL;
375 if_entry = g_list_next(if_entry))
376 printf("%s\n", (char *)if_entry->data);
377 free_interface_list(if_list);
380 capture_option_specified = TRUE;
386 capture_filter_specified = TRUE;
387 cfile.cfilter = g_strdup(optarg);
389 capture_option_specified = TRUE;
394 out_file_type = wtap_short_string_to_file_type(optarg);
395 if (out_file_type < 0) {
396 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
401 case 'h': /* Print help and exit */
405 case 'i': /* Use interface xxx */
407 cfile.iface = g_strdup(optarg);
409 capture_option_specified = TRUE;
413 case 'l': /* "Line-buffer" standard output */
414 /* This isn't line-buffering, strictly speaking, it's just
415 flushing the standard output after the information for
416 each packet is printed; however, that should be good
417 enough for all the purposes to which "-l" is put.
419 See the comment in "wtap_dispatch_cb_print()" for an
420 explanation of why we do that, and why we don't just
421 use "setvbuf()" to make the standard output line-buffered
422 (short version: in Windows, "line-buffered" is the same
423 as "fully-buffered", and the output buffer is only flushed
424 when it fills up). */
425 line_buffered = TRUE;
427 case 'n': /* No name resolution */
428 prefs->name_resolve = PREFS_RESOLV_NONE;
430 case 'N': /* Select what types of addresses/port #s to resolve */
431 if (prefs->name_resolve == PREFS_RESOLV_ALL)
432 prefs->name_resolve = PREFS_RESOLV_NONE;
433 badopt = string_to_name_resolve(optarg, &prefs->name_resolve);
434 if (badopt != '\0') {
435 fprintf(stderr, "tethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
440 case 'o': /* Override preference from command line */
441 switch (prefs_set_pref(optarg)) {
443 case PREFS_SET_SYNTAX_ERR:
444 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
448 case PREFS_SET_NO_SUCH_PREF:
449 case PREFS_SET_OBSOLETE:
450 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
456 case 'p': /* Don't capture in promiscuous mode */
460 capture_option_specified = TRUE;
464 case 'r': /* Read capture file xxx */
465 cf_name = g_strdup(optarg);
467 case 'R': /* Read file filter */
470 case 's': /* Set the snapshot (capture) length */
472 cfile.snap = get_positive_int(optarg, "snapshot length");
474 capture_option_specified = TRUE;
478 case 't': /* Time stamp type */
479 if (strcmp(optarg, "r") == 0)
480 timestamp_type = RELATIVE;
481 else if (strcmp(optarg, "a") == 0)
482 timestamp_type = ABSOLUTE;
483 else if (strcmp(optarg, "ad") == 0)
484 timestamp_type = ABSOLUTE_WITH_DATE;
485 else if (strcmp(optarg, "d") == 0)
486 timestamp_type = DELTA;
488 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
490 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
491 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
495 case 'v': /* Show version and exit */
496 printf("t%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
499 case 'w': /* Write to capture file xxx */
500 cfile.save_file = g_strdup(optarg);
502 case 'V': /* Verbose */
505 case 'x': /* Print packet data in hex (and ASCII) */
511 /* If no capture filter or read filter has been specified, and there are
512 still command-line arguments, treat them as the tokens of a capture
513 filter (if no "-r" flag was specified) or a read filter (if a "-r"
514 flag was specified. */
516 if (cf_name != NULL) {
517 if (rfilter != NULL) {
519 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
522 rfilter = get_args_as_string(argc, argv, optind);
525 if (capture_filter_specified) {
527 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
530 cfile.cfilter = get_args_as_string(argc, argv, optind);
532 capture_option_specified = TRUE;
538 /* Start windows sockets */
539 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
542 /* Notify all registered modules that have had any of their preferences
543 changed either from one of the preferences file or from the command
544 line that its preferences have changed. */
548 if (capture_option_specified)
549 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
554 /* Build the column format array */
555 for (i = 0; i < cfile.cinfo.num_cols; i++) {
556 cfile.cinfo.col_fmt[i] = get_column_format(i);
557 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
558 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
560 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
561 cfile.cinfo.col_data[i] = NULL;
562 if (cfile.cinfo.col_fmt[i] == COL_INFO)
563 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
565 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
569 cfile.snap = WTAP_MAX_PACKET_SIZE;
570 else if (cfile.snap < MIN_PACKET_SIZE)
571 cfile.snap = MIN_PACKET_SIZE;
573 if (rfilter != NULL) {
574 if (!dfilter_compile(rfilter, &rfcode)) {
575 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
580 cfile.rfcode = rfcode;
582 err = open_cap_file(cf_name, FALSE, &cfile);
587 err = load_cap_file(&cfile, out_file_type);
594 /* No capture file specified, so we're supposed to do a live capture;
595 do we have support for live captures? */
600 fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
605 /* Yes; did the user specify an interface to use? */
606 if (cfile.iface == NULL) {
607 /* No - pick the first one from the list of interfaces. */
608 if_list = get_interface_list(&err, err_str);
609 if (if_list == NULL) {
612 case CANT_GET_INTERFACE_LIST:
613 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
617 case NO_INTERFACES_FOUND:
618 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
623 cfile.iface = g_strdup(if_list->data); /* first interface */
624 free_interface_list(if_list);
626 capture(packet_count, out_file_type);
629 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
640 /* Do the low-level work of a capture.
641 Returns TRUE if it succeeds, FALSE otherwise. */
643 capture(int packet_count, int out_file_type)
645 gchar open_err_str[PCAP_ERRBUF_SIZE];
646 gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
647 bpf_u_int32 netnum, netmask;
648 struct bpf_program fcode;
649 void (*oldhandler)(int);
653 static const char ppamsg[] = "can't find PPA for ";
656 struct pcap_stat stats;
658 /* Initialize the table of conversations. */
659 epan_conversation_init();
661 /* Initialize protocol-specific variables */
662 init_all_protocols();
664 /* Initialize the common data structures for fragment reassembly.
665 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
666 may free up space for fragments, which it finds by using the
667 data structures that "reassemble_init()" frees. */
670 ld.linktype = WTAP_ENCAP_UNKNOWN;
673 /* Open the network interface to capture from it.
674 Some versions of libpcap may put warnings into the error buffer
675 if they succeed; to tell if that's happened, we have to clear
676 the error buffer, and check if it's still a null string. */
677 open_err_str[0] = '\0';
678 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000,
681 if (ld.pch == NULL) {
682 /* Well, we couldn't start the capture. */
684 /* On Win32 OSes, the capture devices are probably available to all
685 users; don't warn about permissions problems.
687 Do, however, warn that Token Ring and PPP devices aren't supported. */
688 snprintf(errmsg, sizeof errmsg,
689 "The capture session could not be initiated (%s).\n"
690 "Please check that you have the proper interface specified.\n"
692 "Note that the driver Tethereal uses for packet capture on Windows\n"
693 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
694 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
697 /* If we got a "can't find PPA for XXX" message, warn the user (who
698 is running Ethereal on HP-UX) that they don't have a version
699 of libpcap that properly handles HP-UX (libpcap 0.6.x and later
700 versions, which properly handle HP-UX, say "can't find /dev/dlpi
701 PPA for XXX" rather than "can't find PPA for XXX"). */
702 if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
705 "You are running Tethereal with a version of the libpcap library\n"
706 "that doesn't handle HP-UX network devices well; this means that\n"
707 "Tethereal may not be able to capture packets.\n"
709 "To fix this, you should install libpcap 0.6.2, or a later version\n"
710 "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
711 "packaged binary form from the Software Porting And Archive Centre\n"
712 "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
713 "at the URL lists a number of mirror sites.";
716 snprintf(errmsg, sizeof errmsg,
717 "The capture session could not be initiated (%s).\n"
718 "Please check to make sure you have sufficient permissions, and that\n"
719 "you have the proper interface specified.%s", open_err_str, libpcap_warn);
725 /* A capture filter was specified; set it up. */
726 if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
728 * Well, we can't get the netmask for this interface; it's used
729 * only for filters that check for broadcast IP addresses, so
730 * we just warn the user, and punt and use 0.
733 "Warning: Couldn't obtain netmask info (%s)\n.", lookup_net_err_str);
736 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
737 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
738 pcap_geterr(ld.pch));
741 if (pcap_setfilter(ld.pch, &fcode) < 0) {
742 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
743 pcap_geterr(ld.pch));
748 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
749 if (cfile.save_file != NULL) {
750 /* Set up to write to the capture file. */
751 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
752 strcpy(errmsg, "The network you're capturing from is of a type"
753 " that Tethereal doesn't support.");
756 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
757 ld.linktype, pcap_snapshot(ld.pch), &err);
759 if (ld.pdh == NULL) {
760 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
766 /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
767 returned a warning; print it, but keep capturing. */
768 if (open_err_str[0] != '\0')
769 fprintf(stderr, "tethereal: WARNING: %s.\n", open_err_str);
771 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
773 XXX - deal with signal semantics on various platforms. Or just
774 use "sigaction()" and be done with it? */
775 signal(SIGTERM, capture_cleanup);
776 signal(SIGINT, capture_cleanup);
778 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
779 signal(SIGHUP, oldhandler);
782 /* Let the user know what interface was chosen. */
783 fprintf(stderr, "Capturing on %s\n", cfile.iface);
786 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
788 if (cfile.save_file != NULL) {
789 /* We're saving to a file, which means we're printing packet counts
790 to the standard output. Send a newline so that we move to the
791 line after the packet count. */
792 fprintf(stderr, "\n");
795 /* If we got an error while capturing, report it. */
797 fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
798 pcap_geterr(ld.pch));
801 /* Get the capture statistics, and, if any packets were dropped, report
803 if (pcap_stats(ld.pch, &stats) >= 0) {
804 if (stats.ps_drop != 0) {
805 fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
808 fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
809 pcap_geterr(ld.pch));
813 if (cfile.save_file != NULL) {
814 /* We're saving to a file; close the file. */
815 if (!wtap_dump_close(ld.pdh, &err))
816 show_capture_file_io_error(cfile.save_file, err, TRUE);
822 g_free(cfile.save_file);
823 cfile.save_file = NULL;
824 fprintf(stderr, "tethereal: %s\n", errmsg);
832 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
835 struct wtap_pkthdr whdr;
836 loop_data *ld = (loop_data *) user;
839 whdr.ts.tv_sec = phdr->ts.tv_sec;
840 whdr.ts.tv_usec = phdr->ts.tv_usec;
841 whdr.caplen = phdr->caplen;
842 whdr.len = phdr->len;
843 whdr.pkt_encap = ld->linktype;
848 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
849 fprintf(stderr, "\r%u ", cfile.count);
852 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
857 capture_cleanup(int signum)
861 fprintf(stderr, "\n");
863 if (ld.pdh != NULL) {
864 if (!wtap_dump_close(ld.pdh, &err)) {
865 show_capture_file_io_error(cfile.save_file, err, TRUE);
871 #endif /* HAVE_LIBPCAP */
874 load_cap_file(capture_file *cf, int out_file_type)
882 linktype = wtap_file_encap(cf->wth);
883 if (cf->save_file != NULL) {
884 /* Set up to write to the capture file. */
885 pdh = wtap_dump_open(cf->save_file, out_file_type,
886 linktype, wtap_snapshot_length(cf->wth), &err);
889 /* We couldn't set up to write to the capture file. */
892 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
894 "tethereal: Capture files can't be written in that format.\n");
897 case WTAP_ERR_UNSUPPORTED_ENCAP:
898 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
900 "tethereal: The capture file being read cannot be written in that format.\n");
903 case WTAP_ERR_CANT_OPEN:
905 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
909 case WTAP_ERR_SHORT_WRITE:
911 "tethereal: A full header couldn't be written to the file \"%s\".\n",
918 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
922 "tethereal: The file \"%s\" could not be opened: %s\n.",
923 cf->save_file, strerror(err));
931 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
934 /* Now close the capture file. */
935 if (!wtap_dump_close(pdh, &err))
936 show_capture_file_io_error(cfile.save_file, err, TRUE);
940 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
944 /* Print up a message box noting that the read failed somewhere along
948 case WTAP_ERR_UNSUPPORTED_ENCAP:
950 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
954 case WTAP_ERR_CANT_READ:
956 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
960 case WTAP_ERR_SHORT_READ:
962 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
966 case WTAP_ERR_BAD_RECORD:
968 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
974 "tethereal: An error occurred while reading \"%s\": %s.\n",
975 cf->filename, wtap_strerror(err));
988 fill_in_fdata(frame_data *fdata, capture_file *cf,
989 const struct wtap_pkthdr *phdr,
990 const union wtap_pseudo_header *pseudo_header, long offset)
997 fdata->data_src = NULL;
998 fdata->num = cf->count;
999 fdata->pkt_len = phdr->len;
1000 fdata->cap_len = phdr->caplen;
1001 fdata->file_off = offset;
1002 fdata->cinfo = NULL;
1003 fdata->lnk_t = phdr->pkt_encap;
1004 fdata->abs_secs = phdr->ts.tv_sec;
1005 fdata->abs_usecs = phdr->ts.tv_usec;
1006 fdata->flags.passed_dfilter = 0;
1007 fdata->flags.encoding = CHAR_ASCII;
1008 fdata->flags.visited = 0;
1009 fdata->flags.marked = 0;
1011 /* If we don't have the time stamp of the first packet in the
1012 capture, it's because this is the first packet. Save the time
1013 stamp of this packet as the time stamp of the first packet. */
1014 if (!firstsec && !firstusec) {
1015 firstsec = fdata->abs_secs;
1016 firstusec = fdata->abs_usecs;
1019 /* If we don't have the time stamp of the previous displayed packet,
1020 it's because this is the first displayed packet. Save the time
1021 stamp of this packet as the time stamp of the previous displayed
1023 if (!prevsec && !prevusec) {
1024 prevsec = fdata->abs_secs;
1025 prevusec = fdata->abs_usecs;
1028 /* Get the time elapsed between the first packet and this packet. */
1029 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
1030 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
1032 /* If it's greater than the current elapsed time, set the elapsed time
1033 to it (we check for "greater than" so as not to be confused by
1034 time moving backwards). */
1035 if ((gint32)cf->esec < fdata->rel_secs
1036 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
1037 cf->esec = fdata->rel_secs;
1038 cf->eusec = fdata->rel_usecs;
1041 /* Get the time elapsed between the previous displayed packet and
1043 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
1044 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
1045 prevsec = fdata->abs_secs;
1046 prevusec = fdata->abs_usecs;
1048 fdata->cinfo = &cf->cinfo;
1049 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1050 fdata->cinfo->col_buf[i][0] = '\0';
1051 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
1055 /* Free up all data attached to a "frame_data" structure. */
1057 clear_fdata(frame_data *fdata)
1060 g_slist_free(fdata->pfd);
1061 if (fdata->data_src)
1062 g_slist_free(fdata->data_src);
1066 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr,
1067 long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
1069 cb_args_t *args = (cb_args_t *) user;
1070 capture_file *cf = args->cf;
1071 wtap_dumper *pdh = args->pdh;
1073 proto_tree *protocol_tree;
1076 epan_dissect_t *edt;
1080 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1081 protocol_tree = proto_tree_create_root();
1082 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1083 passed = dfilter_apply_edt(cf->rfcode, edt);
1085 protocol_tree = NULL;
1090 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
1092 if (ld.pch != NULL) {
1093 /* We're capturing packets, so we're printing a count of packets
1094 captured; move to the line after the count. */
1095 fprintf(stderr, "\n");
1098 show_capture_file_io_error(cf->save_file, err, FALSE);
1103 wtap_dump_close(pdh, &err);
1107 if (protocol_tree != NULL)
1108 proto_tree_free(protocol_tree);
1110 epan_dissect_free(edt);
1112 clear_fdata(&fdata);
1116 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1122 "tethereal: Not all the packets could be written to \"%s\" because there is "
1123 "no space left on the file system.\n",
1130 "tethereal: Not all the packets could be written to \"%s\" because you are "
1131 "too close to, or over your disk quota.\n",
1136 case WTAP_ERR_CANT_CLOSE:
1138 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1142 case WTAP_ERR_SHORT_WRITE:
1144 "tethereal: Not all the packets could be written to \"%s\".\n",
1151 "tethereal: \"%s\" could not be closed: %s.\n",
1152 fname, wtap_strerror(err));
1155 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1156 fname, wtap_strerror(err));
1163 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr,
1164 long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
1166 cb_args_t *args = (cb_args_t *) user;
1167 capture_file *cf = args->cf;
1169 proto_tree *protocol_tree;
1171 print_args_t print_args;
1172 epan_dissect_t *edt;
1177 /* The protocol tree will be "visible", i.e., printed, only if we're
1178 not printing a summary. */
1179 proto_tree_is_visible = verbose;
1181 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1184 if (cf->rfcode || verbose)
1185 protocol_tree = proto_tree_create_root();
1187 protocol_tree = NULL;
1188 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1190 passed = dfilter_apply_edt(cf->rfcode, edt);
1192 /* The packet passed the read filter. */
1194 /* Print the information in the protocol tree. */
1195 print_args.to_file = TRUE;
1196 print_args.format = PR_FMT_TEXT;
1197 print_args.print_summary = FALSE;
1198 print_args.print_hex = print_hex;
1199 print_args.expand_all = TRUE;
1200 print_args.suppress_unmarked = FALSE;
1201 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1204 /* "print_hex_data()" will put out a leading blank line, as well
1205 as a trailing one; print one here, to separate the packets,
1206 only if "print_hex_data()" won't be called. */
1210 /* Just fill in the columns. */
1211 fill_in_columns(&fdata);
1213 /* Now print them. */
1214 for (i = 0; i < cf->cinfo.num_cols; i++) {
1215 switch (cf->cinfo.col_fmt[i]) {
1218 * Don't print this if we're doing a live capture from a network
1219 * interface - if we're doing a live capture, you won't be
1220 * able to look at the capture in the future (it's not being
1221 * saved anywhere), so the frame numbers are unlikely to be
1224 * (XXX - it might be nice to be able to save and print at
1225 * the same time, sort of like an "Update list of packets
1226 * in real time" capture in Ethereal.)
1228 if (cf->iface != NULL)
1230 printf("%3s", cf->cinfo.col_data[i]);
1236 case COL_ABS_DATE_TIME: /* XXX - wider */
1237 printf("%10s", cf->cinfo.col_data[i]);
1243 case COL_DEF_DL_SRC:
1244 case COL_RES_DL_SRC:
1245 case COL_UNRES_DL_SRC:
1246 case COL_DEF_NET_SRC:
1247 case COL_RES_NET_SRC:
1248 case COL_UNRES_NET_SRC:
1249 printf("%12s", cf->cinfo.col_data[i]);
1255 case COL_DEF_DL_DST:
1256 case COL_RES_DL_DST:
1257 case COL_UNRES_DL_DST:
1258 case COL_DEF_NET_DST:
1259 case COL_RES_NET_DST:
1260 case COL_UNRES_NET_DST:
1261 printf("%-12s", cf->cinfo.col_data[i]);
1265 printf("%s", cf->cinfo.col_data[i]);
1268 if (i != cf->cinfo.num_cols - 1) {
1270 * This isn't the last column, so we need to print a
1271 * separator between this column and the next.
1273 * If we printed a network source and are printing a
1274 * network destination of the same type next, separate
1275 * them with "->"; if we printed a network destination
1276 * and are printing a network source of the same type
1277 * next, separate them with "<-"; otherwise separate them
1280 switch (cf->cinfo.col_fmt[i]) {
1285 switch (cf->cinfo.col_fmt[i + 1]) {
1299 case COL_DEF_DL_SRC:
1300 case COL_RES_DL_SRC:
1301 case COL_UNRES_DL_SRC:
1302 switch (cf->cinfo.col_fmt[i + 1]) {
1304 case COL_DEF_DL_DST:
1305 case COL_RES_DL_DST:
1306 case COL_UNRES_DL_DST:
1316 case COL_DEF_NET_SRC:
1317 case COL_RES_NET_SRC:
1318 case COL_UNRES_NET_SRC:
1319 switch (cf->cinfo.col_fmt[i + 1]) {
1321 case COL_DEF_NET_DST:
1322 case COL_RES_NET_DST:
1323 case COL_UNRES_NET_DST:
1336 switch (cf->cinfo.col_fmt[i + 1]) {
1350 case COL_DEF_DL_DST:
1351 case COL_RES_DL_DST:
1352 case COL_UNRES_DL_DST:
1353 switch (cf->cinfo.col_fmt[i + 1]) {
1355 case COL_DEF_DL_SRC:
1356 case COL_RES_DL_SRC:
1357 case COL_UNRES_DL_SRC:
1367 case COL_DEF_NET_DST:
1368 case COL_RES_NET_DST:
1369 case COL_UNRES_NET_DST:
1370 switch (cf->cinfo.col_fmt[i + 1]) {
1372 case COL_DEF_NET_SRC:
1373 case COL_RES_NET_SRC:
1374 case COL_UNRES_NET_SRC:
1393 print_hex_data(stdout, print_args.format, &fdata);
1399 /* The ANSI C standard does not appear to *require* that a line-buffered
1400 stream be flushed to the host environment whenever a newline is
1401 written, it just says that, on such a stream, characters "are
1402 intended to be transmitted to or from the host environment as a
1403 block when a new-line character is encountered".
1405 The Visual C++ 6.0 C implementation doesn't do what is intended;
1406 even if you set a stream to be line-buffered, it still doesn't
1407 flush the buffer at the end of every line.
1409 So, if the "-l" flag was specified, we flush the standard output
1410 at the end of a packet. This will do the right thing if we're
1411 printing packet summary lines, and, as we print the entire protocol
1412 tree for a single packet without waiting for anything to happen,
1413 it should be as good as line-buffered mode if we're printing
1414 protocol trees. (The whole reason for the "-l" flag in either
1415 tcpdump or Tethereal is to allow the output of a live capture to
1416 be piped to a program or script and to have that script see the
1417 information for the packet as soon as it's printed, rather than
1418 having to wait until a standard I/O buffer fills up. */
1421 if (protocol_tree != NULL)
1422 proto_tree_free(protocol_tree);
1424 epan_dissect_free(edt);
1426 clear_fdata(&fdata);
1428 proto_tree_is_visible = FALSE;
1432 file_open_error_message(int err, gboolean for_writing)
1435 static char errmsg_errno[1024+1];
1439 case WTAP_ERR_NOT_REGULAR_FILE:
1440 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1443 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1444 case WTAP_ERR_UNSUPPORTED:
1445 /* Seen only when opening a capture file for reading. */
1446 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1449 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1450 /* Seen only when opening a capture file for writing. */
1451 errmsg = "Tethereal does not support writing capture files in that format.";
1454 case WTAP_ERR_UNSUPPORTED_ENCAP:
1455 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1457 errmsg = "Tethereal cannot save this capture in that format.";
1459 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1462 case WTAP_ERR_BAD_RECORD:
1463 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1466 case WTAP_ERR_CANT_OPEN:
1468 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1470 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1473 case WTAP_ERR_SHORT_READ:
1474 errmsg = "The file \"%s\" appears to have been cut short"
1475 " in the middle of a packet.";
1478 case WTAP_ERR_SHORT_WRITE:
1479 errmsg = "A full header couldn't be written to the file \"%s\".";
1484 errmsg = "The path to the file \"%s\" does not exist.";
1486 errmsg = "The file \"%s\" does not exist.";
1491 errmsg = "You do not have permission to create or write to the file \"%s\".";
1493 errmsg = "You do not have permission to read the file \"%s\".";
1497 errmsg = "\"%s\" is a directory (folder), not a file.";
1501 snprintf(errmsg_errno, sizeof(errmsg_errno),
1502 "The file \"%%s\" could not be opened: %s.",
1503 wtap_strerror(err));
1504 errmsg = errmsg_errno;
1511 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1516 struct stat cf_stat;
1517 char err_msg[2048+1];
1519 wth = wtap_open_offline(fname, &err, FALSE);
1523 /* Find the size of the file. */
1525 if (fstat(fd, &cf_stat) < 0) {
1531 /* The open succeeded. Fill in the information for this file. */
1533 /* Initialize the table of conversations. */
1534 epan_conversation_init();
1536 /* Initialize protocol-specific variables */
1537 init_all_protocols();
1539 /* Initialize the common data structures for fragment reassembly.
1540 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
1541 may free up space for fragments, which it finds by using the
1542 data structures that "reassemble_init()" frees. */
1547 cf->f_len = cf_stat.st_size;
1549 /* Set the file name because we need it to set the follow stream filter.
1550 XXX - is that still true? We need it for other reasons, though,
1552 cf->filename = g_strdup(fname);
1554 /* Indicate whether it's a permanent or temporary file. */
1555 cf->is_tempfile = is_tempfile;
1557 /* If it's a temporary capture buffer file, mark it as not saved. */
1558 cf->user_saved = !is_tempfile;
1560 cf->cd_t = wtap_file_type(cf->wth);
1562 cf->drops_known = FALSE;
1566 cf->snap = wtap_snapshot_length(cf->wth);
1567 cf->progbar_quantum = 0;
1568 cf->progbar_nextstep = 0;
1569 firstsec = 0, firstusec = 0;
1570 prevsec = 0, prevusec = 0;
1575 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1576 fprintf(stderr, "tethereal: %s\n", err_msg);