3 * $Id: tethereal.c,v 1.98 2001/11/13 23:55:30 gram 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@alumni.rice.edu>
10 * and Guy Harris <guy@alum.mit.edu>.
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>
48 #ifdef HAVE_SYS_STAT_H
63 #include <zlib.h> /* to get the libz version number */
66 #ifdef NEED_SNPRINTF_H
67 # include "snprintf.h"
70 #if defined(HAVE_UCD_SNMP_SNMP_H)
71 #ifdef HAVE_UCD_SNMP_VERSION_H
72 #include <ucd-snmp/version.h>
73 #endif /* HAVE_UCD_SNMP_VERSION_H */
74 #elif defined(HAVE_SNMP_SNMP_H)
75 #ifdef HAVE_SNMP_VERSION_H
76 #include <snmp/version.h>
77 #endif /* HAVE_SNMP_VERSION_H */
80 #ifdef NEED_STRERROR_H
92 #include "timestamp.h"
101 #include "pcap-util.h"
103 #include "conversation.h"
104 #include "reassemble.h"
106 #include "register.h"
109 #include "capture-wpcap.h"
112 static guint32 firstsec, firstusec;
113 static guint32 prevsec, prevusec;
114 static GString *comp_info_str;
115 static gboolean verbose;
116 static gboolean print_hex;
117 static gboolean line_buffered;
120 typedef struct _loop_data {
128 static int capture(int, int);
129 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
131 static void capture_cleanup(int);
139 static int load_cap_file(capture_file *, int);
140 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, long,
141 union wtap_pseudo_header *, const u_char *);
142 static void show_capture_file_io_error(const char *, int, gboolean);
143 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, long,
144 union wtap_pseudo_header *, const u_char *);
148 FILE *data_out_file = NULL;
149 ts_type timestamp_type = RELATIVE;
151 static int promisc_mode = TRUE;
159 fprintf(stderr, "This is GNU t%s %s, compiled %s\n", PACKAGE, VERSION,
162 fprintf(stderr, "t%s [ -DvVhlp ] [ -c <count> ] [ -f <capture filter> ]\n", PACKAGE);
163 fprintf(stderr, "\t[ -F <capture file type> ] [ -i <interface> ] [ -n ] [ -N <resolving> ]\n");
164 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
165 fprintf(stderr, "\t[ -s <snaplen> ] [ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
167 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ] [ -N <resolving> ]\n", PACKAGE);
168 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r <infile> ] [ -R <read filter> ]\n");
169 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -x ]\n");
171 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
172 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
173 if (wtap_dump_can_open(i))
174 fprintf(stderr, "\t%s - %s\n",
175 wtap_file_type_short_string(i), wtap_file_type_string(i));
177 fprintf(stderr, "\tdefault is libpcap\n");
181 get_positive_int(const char *string, const char *name)
186 number = strtol(string, &p, 10);
187 if (p == string || *p != '\0') {
188 fprintf(stderr, "tethereal: The specified %s \"%s\" is not a decimal number\n",
193 fprintf(stderr, "tethereal: The specified %s \"%s\" is a negative number\n",
197 if (number > INT_MAX) {
198 fprintf(stderr, "tethereal: The specified %s \"%s\" is too large (greater than %d)\n",
199 name, string, INT_MAX);
206 main(int argc, char *argv[])
210 gboolean arg_error = FALSE;
212 #ifdef HAVE_PCAP_VERSION
213 extern char pcap_version[];
214 #endif /* HAVE_PCAP_VERSION */
215 #endif /* HAVE_LIBPCAP */
223 int gpf_open_errno, pf_open_errno;
226 gboolean capture_filter_specified = FALSE;
227 int packet_count = 0;
228 GList *if_list, *if_entry;
229 gchar err_str[PCAP_ERRBUF_SIZE];
231 gboolean capture_option_specified = FALSE;
233 int out_file_type = WTAP_FILE_PCAP;
234 gchar *cf_name = NULL, *rfilter = NULL;
235 dfilter_t *rfcode = NULL;
239 /* Register all dissectors; we must do this before checking for the
240 "-G" flag, as the "-G" flag dumps a list of fields registered
241 by the dissectors, and we must do it before we read the preferences,
242 in case any dissectors register preferences. */
243 epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
245 /* Now register the preferences for any non-dissector modules.
246 We must do that before we read the preferences as well. */
247 prefs_register_modules();
249 /* If invoked with the "-G" flag, we dump out a glossary of
250 display filter symbols.
252 We do this here to mirror what happens in the GTK+ version, although
253 it's not necessary here. */
254 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
255 proto_registrar_dump();
259 /* Set the C-language locale to the native environment. */
260 setlocale(LC_ALL, "");
262 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
263 if (gpf_path != NULL) {
264 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
265 strerror(gpf_open_errno));
267 if (pf_path != NULL) {
268 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
269 strerror(pf_open_errno));
273 /* Load Wpcap, if possible */
277 /* Initialize the capture file struct */
279 cfile.plist_end = NULL;
281 cfile.filename = NULL;
282 cfile.user_saved = FALSE;
283 cfile.is_tempfile = FALSE;
285 cfile.dfilter = NULL;
288 cfile.cfilter = g_strdup("");
291 cfile.save_file = NULL;
292 cfile.save_file_fd = -1;
293 cfile.snap = WTAP_MAX_PACKET_SIZE;
295 col_init(&cfile.cinfo, prefs->num_cols);
297 /* Assemble the compile-time options */
298 comp_info_str = g_string_new("");
300 g_string_append(comp_info_str, "with ");
301 g_string_sprintfa(comp_info_str,
302 #ifdef GLIB_MAJOR_VERSION
303 "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
306 "GLib (version unknown)");
310 g_string_append(comp_info_str, ", with libpcap ");
311 #ifdef HAVE_PCAP_VERSION
312 g_string_append(comp_info_str, pcap_version);
313 #else /* HAVE_PCAP_VERSION */
314 g_string_append(comp_info_str, "(version unknown)");
315 #endif /* HAVE_PCAP_VERSION */
316 #else /* HAVE_LIBPCAP */
317 g_string_append(comp_info_str, ", without libpcap");
318 #endif /* HAVE_LIBPCAP */
321 g_string_append(comp_info_str, ", with libz ");
323 g_string_append(comp_info_str, ZLIB_VERSION);
324 #else /* ZLIB_VERSION */
325 g_string_append(comp_info_str, "(version unknown)");
326 #endif /* ZLIB_VERSION */
327 #else /* HAVE_LIBZ */
328 g_string_append(comp_info_str, ", without libz");
329 #endif /* HAVE_LIBZ */
331 /* Oh, this is pretty */
332 #if defined(HAVE_UCD_SNMP_SNMP_H)
333 g_string_append(comp_info_str, ", with UCD SNMP ");
334 #ifdef HAVE_UCD_SNMP_VERSION_H
335 g_string_append(comp_info_str, VersionInfo);
336 #else /* HAVE_UCD_SNMP_VERSION_H */
337 g_string_append(comp_info_str, "(version unknown)");
338 #endif /* HAVE_UCD_SNMP_VERSION_H */
339 #elif defined(HAVE_SNMP_SNMP_H)
340 g_string_append(comp_info_str, ", with CMU SNMP ");
341 #ifdef HAVE_SNMP_VERSION_H
342 g_string_append(comp_info_str, snmp_Version());
343 #else /* HAVE_SNMP_VERSION_H */
344 g_string_append(comp_info_str, "(version unknown)");
345 #endif /* HAVE_SNMP_VERSION_H */
347 g_string_append(comp_info_str, ", without SNMP");
350 /* Now get our args */
351 while ((opt = getopt(argc, argv, "c:Df:F:hi:lnN:o:pr:R:s:t:vw:Vx")) != EOF) {
353 case 'c': /* Capture xxx packets */
355 packet_count = get_positive_int(optarg, "packet count");
357 capture_option_specified = TRUE;
361 case 'D': /* Print a list of capture devices */
363 if_list = get_interface_list(&err, err_str);
364 if (if_list == NULL) {
367 case CANT_GET_INTERFACE_LIST:
368 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
372 case NO_INTERFACES_FOUND:
373 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
378 for (if_entry = g_list_first(if_list); if_entry != NULL;
379 if_entry = g_list_next(if_entry))
380 printf("%s\n", (char *)if_entry->data);
381 free_interface_list(if_list);
384 capture_option_specified = TRUE;
390 capture_filter_specified = TRUE;
391 cfile.cfilter = g_strdup(optarg);
393 capture_option_specified = TRUE;
398 out_file_type = wtap_short_string_to_file_type(optarg);
399 if (out_file_type < 0) {
400 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
405 case 'h': /* Print help and exit */
409 case 'i': /* Use interface xxx */
411 cfile.iface = g_strdup(optarg);
413 capture_option_specified = TRUE;
417 case 'l': /* "Line-buffer" standard output */
418 /* This isn't line-buffering, strictly speaking, it's just
419 flushing the standard output after the information for
420 each packet is printed; however, that should be good
421 enough for all the purposes to which "-l" is put.
423 See the comment in "wtap_dispatch_cb_print()" for an
424 explanation of why we do that, and why we don't just
425 use "setvbuf()" to make the standard output line-buffered
426 (short version: in Windows, "line-buffered" is the same
427 as "fully-buffered", and the output buffer is only flushed
428 when it fills up). */
429 line_buffered = TRUE;
431 case 'n': /* No name resolution */
432 prefs->name_resolve = PREFS_RESOLV_NONE;
434 case 'N': /* Select what types of addresses/port #s to resolve */
435 if (prefs->name_resolve == PREFS_RESOLV_ALL)
436 prefs->name_resolve = PREFS_RESOLV_NONE;
437 badopt = string_to_name_resolve(optarg, &prefs->name_resolve);
438 if (badopt != '\0') {
439 fprintf(stderr, "tethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
444 case 'o': /* Override preference from command line */
445 switch (prefs_set_pref(optarg)) {
447 case PREFS_SET_SYNTAX_ERR:
448 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
452 case PREFS_SET_NO_SUCH_PREF:
453 case PREFS_SET_OBSOLETE:
454 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
460 case 'p': /* Don't capture in promiscuous mode */
464 capture_option_specified = TRUE;
468 case 'r': /* Read capture file xxx */
469 cf_name = g_strdup(optarg);
471 case 'R': /* Read file filter */
474 case 's': /* Set the snapshot (capture) length */
476 cfile.snap = get_positive_int(optarg, "snapshot length");
478 capture_option_specified = TRUE;
482 case 't': /* Time stamp type */
483 if (strcmp(optarg, "r") == 0)
484 timestamp_type = RELATIVE;
485 else if (strcmp(optarg, "a") == 0)
486 timestamp_type = ABSOLUTE;
487 else if (strcmp(optarg, "ad") == 0)
488 timestamp_type = ABSOLUTE_WITH_DATE;
489 else if (strcmp(optarg, "d") == 0)
490 timestamp_type = DELTA;
492 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
494 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
495 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
499 case 'v': /* Show version and exit */
500 printf("t%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
503 case 'w': /* Write to capture file xxx */
504 cfile.save_file = g_strdup(optarg);
506 case 'V': /* Verbose */
509 case 'x': /* Print packet data in hex (and ASCII) */
515 /* If no capture filter or read filter has been specified, and there are
516 still command-line arguments, treat them as the tokens of a capture
517 filter (if no "-r" flag was specified) or a read filter (if a "-r"
518 flag was specified. */
520 if (cf_name != NULL) {
521 if (rfilter != NULL) {
523 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
526 rfilter = get_args_as_string(argc, argv, optind);
529 if (capture_filter_specified) {
531 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
534 cfile.cfilter = get_args_as_string(argc, argv, optind);
536 capture_option_specified = TRUE;
542 /* Start windows sockets */
543 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
546 /* Notify all registered modules that have had any of their preferences
547 changed either from one of the preferences file or from the command
548 line that its preferences have changed. */
552 if (capture_option_specified)
553 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
558 /* Build the column format array */
559 for (i = 0; i < cfile.cinfo.num_cols; i++) {
560 cfile.cinfo.col_fmt[i] = get_column_format(i);
561 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
562 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
564 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
565 cfile.cinfo.col_data[i] = NULL;
566 if (cfile.cinfo.col_fmt[i] == COL_INFO)
567 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
569 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
573 cfile.snap = WTAP_MAX_PACKET_SIZE;
574 else if (cfile.snap < MIN_PACKET_SIZE)
575 cfile.snap = MIN_PACKET_SIZE;
577 if (rfilter != NULL) {
578 if (!dfilter_compile(rfilter, &rfcode)) {
579 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
584 cfile.rfcode = rfcode;
586 err = open_cap_file(cf_name, FALSE, &cfile);
591 err = load_cap_file(&cfile, out_file_type);
598 /* No capture file specified, so we're supposed to do a live capture;
599 do we have support for live captures? */
604 fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
609 /* Yes; did the user specify an interface to use? */
610 if (cfile.iface == NULL) {
611 /* No - pick the first one from the list of interfaces. */
612 if_list = get_interface_list(&err, err_str);
613 if (if_list == NULL) {
616 case CANT_GET_INTERFACE_LIST:
617 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
621 case NO_INTERFACES_FOUND:
622 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
627 cfile.iface = g_strdup(if_list->data); /* first interface */
628 free_interface_list(if_list);
630 capture(packet_count, out_file_type);
633 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
644 /* Do the low-level work of a capture.
645 Returns TRUE if it succeeds, FALSE otherwise. */
647 capture(int packet_count, int out_file_type)
649 gchar open_err_str[PCAP_ERRBUF_SIZE];
650 gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
651 bpf_u_int32 netnum, netmask;
652 struct bpf_program fcode;
653 void (*oldhandler)(int);
657 static const char ppamsg[] = "can't find PPA for ";
660 struct pcap_stat stats;
662 /* Initialize the table of conversations. */
663 epan_conversation_init();
665 /* Initialize protocol-specific variables */
666 init_all_protocols();
668 /* Initialize the common data structures for fragment reassembly.
669 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
670 may free up space for fragments, which it finds by using the
671 data structures that "reassemble_init()" frees. */
674 ld.linktype = WTAP_ENCAP_UNKNOWN;
677 /* Open the network interface to capture from it.
678 Some versions of libpcap may put warnings into the error buffer
679 if they succeed; to tell if that's happened, we have to clear
680 the error buffer, and check if it's still a null string. */
681 open_err_str[0] = '\0';
682 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000,
685 if (ld.pch == NULL) {
686 /* Well, we couldn't start the capture. */
688 /* On Win32 OSes, the capture devices are probably available to all
689 users; don't warn about permissions problems.
691 Do, however, warn that Token Ring and PPP devices aren't supported. */
692 snprintf(errmsg, sizeof errmsg,
693 "The capture session could not be initiated (%s).\n"
694 "Please check that you have the proper interface specified.\n"
696 "Note that the driver Tethereal uses for packet capture on Windows\n"
697 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
698 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
701 /* If we got a "can't find PPA for XXX" message, warn the user (who
702 is running Ethereal on HP-UX) that they don't have a version
703 of libpcap that properly handles HP-UX (libpcap 0.6.x and later
704 versions, which properly handle HP-UX, say "can't find /dev/dlpi
705 PPA for XXX" rather than "can't find PPA for XXX"). */
706 if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
709 "You are running Tethereal with a version of the libpcap library\n"
710 "that doesn't handle HP-UX network devices well; this means that\n"
711 "Tethereal may not be able to capture packets.\n"
713 "To fix this, you should install libpcap 0.6.2, or a later version\n"
714 "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
715 "packaged binary form from the Software Porting And Archive Centre\n"
716 "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
717 "at the URL lists a number of mirror sites.";
720 snprintf(errmsg, sizeof errmsg,
721 "The capture session could not be initiated (%s).\n"
722 "Please check to make sure you have sufficient permissions, and that\n"
723 "you have the proper interface specified.%s", open_err_str, libpcap_warn);
729 /* A capture filter was specified; set it up. */
730 if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
732 * Well, we can't get the netmask for this interface; it's used
733 * only for filters that check for broadcast IP addresses, so
734 * we just warn the user, and punt and use 0.
737 "Warning: Couldn't obtain netmask info (%s)\n.", lookup_net_err_str);
740 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
741 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
742 pcap_geterr(ld.pch));
745 if (pcap_setfilter(ld.pch, &fcode) < 0) {
746 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
747 pcap_geterr(ld.pch));
752 ld.linktype = wtap_pcap_encap_to_wtap_encap(get_pcap_linktype(ld.pch,
754 if (cfile.save_file != NULL) {
755 /* Set up to write to the capture file. */
756 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
757 strcpy(errmsg, "The network you're capturing from is of a type"
758 " that Tethereal doesn't support.");
761 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
762 ld.linktype, pcap_snapshot(ld.pch), &err);
764 if (ld.pdh == NULL) {
765 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
771 /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
772 returned a warning; print it, but keep capturing. */
773 if (open_err_str[0] != '\0')
774 fprintf(stderr, "tethereal: WARNING: %s.\n", open_err_str);
776 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
778 XXX - deal with signal semantics on various platforms. Or just
779 use "sigaction()" and be done with it? */
780 signal(SIGTERM, capture_cleanup);
781 signal(SIGINT, capture_cleanup);
783 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
784 signal(SIGHUP, oldhandler);
787 /* Let the user know what interface was chosen. */
788 fprintf(stderr, "Capturing on %s\n", cfile.iface);
791 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
793 if (cfile.save_file != NULL) {
794 /* We're saving to a file, which means we're printing packet counts
795 to the standard output. Send a newline so that we move to the
796 line after the packet count. */
797 fprintf(stderr, "\n");
800 /* If we got an error while capturing, report it. */
802 fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
803 pcap_geterr(ld.pch));
806 /* Get the capture statistics, and, if any packets were dropped, report
808 if (pcap_stats(ld.pch, &stats) >= 0) {
809 if (stats.ps_drop != 0) {
810 fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
813 fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
814 pcap_geterr(ld.pch));
818 if (cfile.save_file != NULL) {
819 /* We're saving to a file; close the file. */
820 if (!wtap_dump_close(ld.pdh, &err))
821 show_capture_file_io_error(cfile.save_file, err, TRUE);
827 g_free(cfile.save_file);
828 cfile.save_file = NULL;
829 fprintf(stderr, "tethereal: %s\n", errmsg);
837 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
840 struct wtap_pkthdr whdr;
841 loop_data *ld = (loop_data *) user;
844 whdr.ts.tv_sec = phdr->ts.tv_sec;
845 whdr.ts.tv_usec = phdr->ts.tv_usec;
846 whdr.caplen = phdr->caplen;
847 whdr.len = phdr->len;
848 whdr.pkt_encap = ld->linktype;
853 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
854 fprintf(stderr, "\r%u ", cfile.count);
857 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
862 capture_cleanup(int signum)
866 fprintf(stderr, "\n");
868 if (ld.pdh != NULL) {
869 if (!wtap_dump_close(ld.pdh, &err)) {
870 show_capture_file_io_error(cfile.save_file, err, TRUE);
876 #endif /* HAVE_LIBPCAP */
879 load_cap_file(capture_file *cf, int out_file_type)
887 linktype = wtap_file_encap(cf->wth);
888 if (cf->save_file != NULL) {
889 /* Set up to write to the capture file. */
890 pdh = wtap_dump_open(cf->save_file, out_file_type,
891 linktype, wtap_snapshot_length(cf->wth), &err);
894 /* We couldn't set up to write to the capture file. */
897 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
899 "tethereal: Capture files can't be written in that format.\n");
902 case WTAP_ERR_UNSUPPORTED_ENCAP:
903 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
905 "tethereal: The capture file being read cannot be written in that format.\n");
908 case WTAP_ERR_CANT_OPEN:
910 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
914 case WTAP_ERR_SHORT_WRITE:
916 "tethereal: A full header couldn't be written to the file \"%s\".\n",
923 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
927 "tethereal: The file \"%s\" could not be opened: %s\n.",
928 cf->save_file, strerror(err));
936 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
939 /* Now close the capture file. */
940 if (!wtap_dump_close(pdh, &err))
941 show_capture_file_io_error(cfile.save_file, err, TRUE);
945 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
949 /* Print up a message box noting that the read failed somewhere along
953 case WTAP_ERR_UNSUPPORTED_ENCAP:
955 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
959 case WTAP_ERR_CANT_READ:
961 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
965 case WTAP_ERR_SHORT_READ:
967 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
971 case WTAP_ERR_BAD_RECORD:
973 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
979 "tethereal: An error occurred while reading \"%s\": %s.\n",
980 cf->filename, wtap_strerror(err));
993 fill_in_fdata(frame_data *fdata, capture_file *cf,
994 const struct wtap_pkthdr *phdr,
995 const union wtap_pseudo_header *pseudo_header, long offset)
1002 fdata->data_src = NULL;
1003 fdata->num = cf->count;
1004 fdata->pkt_len = phdr->len;
1005 fdata->cap_len = phdr->caplen;
1006 fdata->file_off = offset;
1007 fdata->cinfo = NULL;
1008 fdata->lnk_t = phdr->pkt_encap;
1009 fdata->abs_secs = phdr->ts.tv_sec;
1010 fdata->abs_usecs = phdr->ts.tv_usec;
1011 fdata->flags.passed_dfilter = 0;
1012 fdata->flags.encoding = CHAR_ASCII;
1013 fdata->flags.visited = 0;
1014 fdata->flags.marked = 0;
1016 /* If we don't have the time stamp of the first packet in the
1017 capture, it's because this is the first packet. Save the time
1018 stamp of this packet as the time stamp of the first packet. */
1019 if (!firstsec && !firstusec) {
1020 firstsec = fdata->abs_secs;
1021 firstusec = fdata->abs_usecs;
1024 /* If we don't have the time stamp of the previous displayed packet,
1025 it's because this is the first displayed packet. Save the time
1026 stamp of this packet as the time stamp of the previous displayed
1028 if (!prevsec && !prevusec) {
1029 prevsec = fdata->abs_secs;
1030 prevusec = fdata->abs_usecs;
1033 /* Get the time elapsed between the first packet and this packet. */
1034 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
1035 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
1037 /* If it's greater than the current elapsed time, set the elapsed time
1038 to it (we check for "greater than" so as not to be confused by
1039 time moving backwards). */
1040 if ((gint32)cf->esec < fdata->rel_secs
1041 || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
1042 cf->esec = fdata->rel_secs;
1043 cf->eusec = fdata->rel_usecs;
1046 /* Get the time elapsed between the previous displayed packet and
1048 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
1049 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
1050 prevsec = fdata->abs_secs;
1051 prevusec = fdata->abs_usecs;
1053 fdata->cinfo = &cf->cinfo;
1054 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1055 fdata->cinfo->col_buf[i][0] = '\0';
1056 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
1060 /* Free up all data attached to a "frame_data" structure. */
1062 clear_fdata(frame_data *fdata)
1065 g_slist_free(fdata->pfd);
1066 if (fdata->data_src)
1067 g_slist_free(fdata->data_src);
1071 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr,
1072 long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
1074 cb_args_t *args = (cb_args_t *) user;
1075 capture_file *cf = args->cf;
1076 wtap_dumper *pdh = args->pdh;
1078 proto_tree *protocol_tree;
1081 epan_dissect_t *edt;
1085 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1086 protocol_tree = proto_tree_create_root();
1087 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1088 passed = dfilter_apply_edt(cf->rfcode, edt);
1090 protocol_tree = NULL;
1095 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
1097 if (ld.pch != NULL) {
1098 /* We're capturing packets, so we're printing a count of packets
1099 captured; move to the line after the count. */
1100 fprintf(stderr, "\n");
1103 show_capture_file_io_error(cf->save_file, err, FALSE);
1108 wtap_dump_close(pdh, &err);
1112 if (protocol_tree != NULL)
1113 proto_tree_free(protocol_tree);
1115 epan_dissect_free(edt);
1117 clear_fdata(&fdata);
1121 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1127 "tethereal: Not all the packets could be written to \"%s\" because there is "
1128 "no space left on the file system.\n",
1135 "tethereal: Not all the packets could be written to \"%s\" because you are "
1136 "too close to, or over your disk quota.\n",
1141 case WTAP_ERR_CANT_CLOSE:
1143 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1147 case WTAP_ERR_SHORT_WRITE:
1149 "tethereal: Not all the packets could be written to \"%s\".\n",
1156 "tethereal: \"%s\" could not be closed: %s.\n",
1157 fname, wtap_strerror(err));
1160 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1161 fname, wtap_strerror(err));
1168 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr,
1169 long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
1171 cb_args_t *args = (cb_args_t *) user;
1172 capture_file *cf = args->cf;
1174 proto_tree *protocol_tree;
1176 print_args_t print_args;
1177 epan_dissect_t *edt;
1182 /* The protocol tree will be "visible", i.e., printed, only if we're
1183 not printing a summary. */
1184 proto_tree_is_visible = verbose;
1186 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1189 if (cf->rfcode || verbose)
1190 protocol_tree = proto_tree_create_root();
1192 protocol_tree = NULL;
1193 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1195 passed = dfilter_apply_edt(cf->rfcode, edt);
1197 /* The packet passed the read filter. */
1199 /* Print the information in the protocol tree. */
1200 print_args.to_file = TRUE;
1201 print_args.format = PR_FMT_TEXT;
1202 print_args.print_summary = FALSE;
1203 print_args.print_hex = print_hex;
1204 print_args.expand_all = TRUE;
1205 print_args.suppress_unmarked = FALSE;
1206 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1209 /* "print_hex_data()" will put out a leading blank line, as well
1210 as a trailing one; print one here, to separate the packets,
1211 only if "print_hex_data()" won't be called. */
1215 /* Just fill in the columns. */
1216 fill_in_columns(&fdata);
1218 /* Now print them. */
1219 for (i = 0; i < cf->cinfo.num_cols; i++) {
1220 switch (cf->cinfo.col_fmt[i]) {
1223 * Don't print this if we're doing a live capture from a network
1224 * interface - if we're doing a live capture, you won't be
1225 * able to look at the capture in the future (it's not being
1226 * saved anywhere), so the frame numbers are unlikely to be
1229 * (XXX - it might be nice to be able to save and print at
1230 * the same time, sort of like an "Update list of packets
1231 * in real time" capture in Ethereal.)
1233 if (cf->iface != NULL)
1235 printf("%3s", cf->cinfo.col_data[i]);
1241 case COL_ABS_DATE_TIME: /* XXX - wider */
1242 printf("%10s", cf->cinfo.col_data[i]);
1248 case COL_DEF_DL_SRC:
1249 case COL_RES_DL_SRC:
1250 case COL_UNRES_DL_SRC:
1251 case COL_DEF_NET_SRC:
1252 case COL_RES_NET_SRC:
1253 case COL_UNRES_NET_SRC:
1254 printf("%12s", cf->cinfo.col_data[i]);
1260 case COL_DEF_DL_DST:
1261 case COL_RES_DL_DST:
1262 case COL_UNRES_DL_DST:
1263 case COL_DEF_NET_DST:
1264 case COL_RES_NET_DST:
1265 case COL_UNRES_NET_DST:
1266 printf("%-12s", cf->cinfo.col_data[i]);
1270 printf("%s", cf->cinfo.col_data[i]);
1273 if (i != cf->cinfo.num_cols - 1) {
1275 * This isn't the last column, so we need to print a
1276 * separator between this column and the next.
1278 * If we printed a network source and are printing a
1279 * network destination of the same type next, separate
1280 * them with "->"; if we printed a network destination
1281 * and are printing a network source of the same type
1282 * next, separate them with "<-"; otherwise separate them
1285 switch (cf->cinfo.col_fmt[i]) {
1290 switch (cf->cinfo.col_fmt[i + 1]) {
1304 case COL_DEF_DL_SRC:
1305 case COL_RES_DL_SRC:
1306 case COL_UNRES_DL_SRC:
1307 switch (cf->cinfo.col_fmt[i + 1]) {
1309 case COL_DEF_DL_DST:
1310 case COL_RES_DL_DST:
1311 case COL_UNRES_DL_DST:
1321 case COL_DEF_NET_SRC:
1322 case COL_RES_NET_SRC:
1323 case COL_UNRES_NET_SRC:
1324 switch (cf->cinfo.col_fmt[i + 1]) {
1326 case COL_DEF_NET_DST:
1327 case COL_RES_NET_DST:
1328 case COL_UNRES_NET_DST:
1341 switch (cf->cinfo.col_fmt[i + 1]) {
1355 case COL_DEF_DL_DST:
1356 case COL_RES_DL_DST:
1357 case COL_UNRES_DL_DST:
1358 switch (cf->cinfo.col_fmt[i + 1]) {
1360 case COL_DEF_DL_SRC:
1361 case COL_RES_DL_SRC:
1362 case COL_UNRES_DL_SRC:
1372 case COL_DEF_NET_DST:
1373 case COL_RES_NET_DST:
1374 case COL_UNRES_NET_DST:
1375 switch (cf->cinfo.col_fmt[i + 1]) {
1377 case COL_DEF_NET_SRC:
1378 case COL_RES_NET_SRC:
1379 case COL_UNRES_NET_SRC:
1398 print_hex_data(stdout, print_args.format, &fdata);
1404 /* The ANSI C standard does not appear to *require* that a line-buffered
1405 stream be flushed to the host environment whenever a newline is
1406 written, it just says that, on such a stream, characters "are
1407 intended to be transmitted to or from the host environment as a
1408 block when a new-line character is encountered".
1410 The Visual C++ 6.0 C implementation doesn't do what is intended;
1411 even if you set a stream to be line-buffered, it still doesn't
1412 flush the buffer at the end of every line.
1414 So, if the "-l" flag was specified, we flush the standard output
1415 at the end of a packet. This will do the right thing if we're
1416 printing packet summary lines, and, as we print the entire protocol
1417 tree for a single packet without waiting for anything to happen,
1418 it should be as good as line-buffered mode if we're printing
1419 protocol trees. (The whole reason for the "-l" flag in either
1420 tcpdump or Tethereal is to allow the output of a live capture to
1421 be piped to a program or script and to have that script see the
1422 information for the packet as soon as it's printed, rather than
1423 having to wait until a standard I/O buffer fills up. */
1426 if (protocol_tree != NULL)
1427 proto_tree_free(protocol_tree);
1429 epan_dissect_free(edt);
1431 clear_fdata(&fdata);
1433 proto_tree_is_visible = FALSE;
1437 file_open_error_message(int err, gboolean for_writing)
1440 static char errmsg_errno[1024+1];
1444 case WTAP_ERR_NOT_REGULAR_FILE:
1445 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1448 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1449 case WTAP_ERR_UNSUPPORTED:
1450 /* Seen only when opening a capture file for reading. */
1451 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1454 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1455 /* Seen only when opening a capture file for writing. */
1456 errmsg = "Tethereal does not support writing capture files in that format.";
1459 case WTAP_ERR_UNSUPPORTED_ENCAP:
1460 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1462 errmsg = "Tethereal cannot save this capture in that format.";
1464 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1467 case WTAP_ERR_BAD_RECORD:
1468 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1471 case WTAP_ERR_CANT_OPEN:
1473 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1475 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1478 case WTAP_ERR_SHORT_READ:
1479 errmsg = "The file \"%s\" appears to have been cut short"
1480 " in the middle of a packet.";
1483 case WTAP_ERR_SHORT_WRITE:
1484 errmsg = "A full header couldn't be written to the file \"%s\".";
1489 errmsg = "The path to the file \"%s\" does not exist.";
1491 errmsg = "The file \"%s\" does not exist.";
1496 errmsg = "You do not have permission to create or write to the file \"%s\".";
1498 errmsg = "You do not have permission to read the file \"%s\".";
1502 errmsg = "\"%s\" is a directory (folder), not a file.";
1506 snprintf(errmsg_errno, sizeof(errmsg_errno),
1507 "The file \"%%s\" could not be opened: %s.",
1508 wtap_strerror(err));
1509 errmsg = errmsg_errno;
1516 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1521 struct stat cf_stat;
1522 char err_msg[2048+1];
1524 wth = wtap_open_offline(fname, &err, FALSE);
1528 /* Find the size of the file. */
1530 if (fstat(fd, &cf_stat) < 0) {
1536 /* The open succeeded. Fill in the information for this file. */
1538 /* Initialize the table of conversations. */
1539 epan_conversation_init();
1541 /* Initialize protocol-specific variables */
1542 init_all_protocols();
1544 /* Initialize the common data structures for fragment reassembly.
1545 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
1546 may free up space for fragments, which it finds by using the
1547 data structures that "reassemble_init()" frees. */
1552 cf->f_len = cf_stat.st_size;
1554 /* Set the file name because we need it to set the follow stream filter.
1555 XXX - is that still true? We need it for other reasons, though,
1557 cf->filename = g_strdup(fname);
1559 /* Indicate whether it's a permanent or temporary file. */
1560 cf->is_tempfile = is_tempfile;
1562 /* If it's a temporary capture buffer file, mark it as not saved. */
1563 cf->user_saved = !is_tempfile;
1565 cf->cd_t = wtap_file_type(cf->wth);
1567 cf->drops_known = FALSE;
1571 cf->snap = wtap_snapshot_length(cf->wth);
1572 cf->progbar_quantum = 0;
1573 cf->progbar_nextstep = 0;
1574 firstsec = 0, firstusec = 0;
1575 prevsec = 0, prevusec = 0;
1580 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1581 fprintf(stderr, "tethereal: %s\n", err_msg);