3 * $Id: tethereal.c,v 1.91 2001/09/05 05:03:47 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 *, int,
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 *, int,
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 */
217 char *gpf_path, *pf_path;
218 int gpf_open_errno, pf_open_errno;
221 gboolean capture_filter_specified = FALSE;
222 int packet_count = 0;
223 GList *if_list, *if_entry;
224 gchar err_str[PCAP_ERRBUF_SIZE];
226 gboolean capture_option_specified = FALSE;
228 int out_file_type = WTAP_FILE_PCAP;
229 gchar *cf_name = NULL, *rfilter = NULL;
230 dfilter_t *rfcode = NULL;
234 /* Register all dissectors; we must do this before checking for the
235 "-G" flag, as the "-G" flag dumps a list of fields registered
236 by the dissectors, and we must do it before we read the preferences,
237 in case any dissectors register preferences. */
238 epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
240 /* Now register the preferences for any non-dissector modules.
241 We must do that before we read the preferences as well. */
242 prefs_register_modules();
244 /* If invoked with the "-G" flag, we dump out a glossary of
245 display filter symbols.
247 We do this here to mirror what happens in the GTK+ version, although
248 it's not necessary here. */
249 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
250 proto_registrar_dump();
254 /* Set the C-language locale to the native environment. */
255 setlocale(LC_ALL, "");
257 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
258 if (gpf_path != NULL) {
259 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
260 strerror(gpf_open_errno));
262 if (pf_path != NULL) {
263 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
264 strerror(pf_open_errno));
268 /* Load Wpcap, if possible */
272 /* Initialize the capture file struct */
274 cfile.plist_end = NULL;
276 cfile.filename = NULL;
277 cfile.user_saved = FALSE;
278 cfile.is_tempfile = FALSE;
280 cfile.dfilter = NULL;
283 cfile.cfilter = g_strdup("");
286 cfile.save_file = NULL;
287 cfile.save_file_fd = -1;
288 cfile.snap = WTAP_MAX_PACKET_SIZE;
290 col_init(&cfile.cinfo, prefs->num_cols);
292 /* Assemble the compile-time options */
293 comp_info_str = g_string_new("");
295 g_string_append(comp_info_str, "with ");
296 g_string_sprintfa(comp_info_str,
297 #ifdef GLIB_MAJOR_VERSION
298 "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
301 "GLib (version unknown)");
305 g_string_append(comp_info_str, ", with libpcap ");
306 #ifdef HAVE_PCAP_VERSION
307 g_string_append(comp_info_str, pcap_version);
308 #else /* HAVE_PCAP_VERSION */
309 g_string_append(comp_info_str, "(version unknown)");
310 #endif /* HAVE_PCAP_VERSION */
311 #else /* HAVE_LIBPCAP */
312 g_string_append(comp_info_str, ", without libpcap");
313 #endif /* HAVE_LIBPCAP */
316 g_string_append(comp_info_str, ", with libz ");
318 g_string_append(comp_info_str, ZLIB_VERSION);
319 #else /* ZLIB_VERSION */
320 g_string_append(comp_info_str, "(version unknown)");
321 #endif /* ZLIB_VERSION */
322 #else /* HAVE_LIBZ */
323 g_string_append(comp_info_str, ", without libz");
324 #endif /* HAVE_LIBZ */
326 /* Oh, this is pretty */
327 #if defined(HAVE_UCD_SNMP_SNMP_H)
328 g_string_append(comp_info_str, ", with UCD SNMP ");
329 #ifdef HAVE_UCD_SNMP_VERSION_H
330 g_string_append(comp_info_str, VersionInfo);
331 #else /* HAVE_UCD_SNMP_VERSION_H */
332 g_string_append(comp_info_str, "(version unknown)");
333 #endif /* HAVE_UCD_SNMP_VERSION_H */
334 #elif defined(HAVE_SNMP_SNMP_H)
335 g_string_append(comp_info_str, ", with CMU SNMP ");
336 #ifdef HAVE_SNMP_VERSION_H
337 g_string_append(comp_info_str, snmp_Version());
338 #else /* HAVE_SNMP_VERSION_H */
339 g_string_append(comp_info_str, "(version unknown)");
340 #endif /* HAVE_SNMP_VERSION_H */
342 g_string_append(comp_info_str, ", without SNMP");
345 /* Now get our args */
346 while ((opt = getopt(argc, argv, "c:Df:F:hi:lnN:o:pr:R:s:t:vw:Vx")) != EOF) {
348 case 'c': /* Capture xxx packets */
350 packet_count = get_positive_int(optarg, "packet count");
352 capture_option_specified = TRUE;
356 case 'D': /* Print a list of capture devices */
358 if_list = get_interface_list(&err, err_str);
359 if (if_list == NULL) {
362 case CANT_GET_INTERFACE_LIST:
363 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
367 case NO_INTERFACES_FOUND:
368 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
373 for (if_entry = g_list_first(if_list); if_entry != NULL;
374 if_entry = g_list_next(if_entry))
375 printf("%s\n", (char *)if_entry->data);
376 free_interface_list(if_list);
379 capture_option_specified = TRUE;
385 capture_filter_specified = TRUE;
386 cfile.cfilter = g_strdup(optarg);
388 capture_option_specified = TRUE;
393 out_file_type = wtap_short_string_to_file_type(optarg);
394 if (out_file_type < 0) {
395 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
400 case 'h': /* Print help and exit */
404 case 'i': /* Use interface xxx */
406 cfile.iface = g_strdup(optarg);
408 capture_option_specified = TRUE;
412 case 'l': /* "Line-buffer" standard output */
413 /* This isn't line-buffering, strictly speaking, it's just
414 flushing the standard output after the information for
415 each packet is printed; however, that should be good
416 enough for all the purposes to which "-l" is put.
418 See the comment in "wtap_dispatch_cb_print()" for an
419 explanation of why we do that, and why we don't just
420 use "setvbuf()" to make the standard output line-buffered
421 (short version: in Windows, "line-buffered" is the same
422 as "fully-buffered", and the output buffer is only flushed
423 when it fills up). */
424 line_buffered = TRUE;
426 case 'n': /* No name resolution */
427 prefs->name_resolve = PREFS_RESOLV_NONE;
429 case 'N': /* Select what types of addresses/port #s to resolve */
430 if (prefs->name_resolve == PREFS_RESOLV_ALL)
431 prefs->name_resolve = PREFS_RESOLV_NONE;
432 badopt = string_to_name_resolve(optarg, &prefs->name_resolve);
433 if (badopt != '\0') {
434 fprintf(stderr, "tethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
439 case 'o': /* Override preference from command line */
440 switch (prefs_set_pref(optarg)) {
442 case PREFS_SET_SYNTAX_ERR:
443 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
447 case PREFS_SET_NO_SUCH_PREF:
448 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
454 case 'p': /* Don't capture in promiscuous mode */
458 capture_option_specified = TRUE;
462 case 'r': /* Read capture file xxx */
463 cf_name = g_strdup(optarg);
465 case 'R': /* Read file filter */
468 case 's': /* Set the snapshot (capture) length */
470 cfile.snap = get_positive_int(optarg, "snapshot length");
472 capture_option_specified = TRUE;
476 case 't': /* Time stamp type */
477 if (strcmp(optarg, "r") == 0)
478 timestamp_type = RELATIVE;
479 else if (strcmp(optarg, "a") == 0)
480 timestamp_type = ABSOLUTE;
481 else if (strcmp(optarg, "ad") == 0)
482 timestamp_type = ABSOLUTE_WITH_DATE;
483 else if (strcmp(optarg, "d") == 0)
484 timestamp_type = DELTA;
486 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
488 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
489 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
493 case 'v': /* Show version and exit */
494 printf("t%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
497 case 'w': /* Write to capture file xxx */
498 cfile.save_file = g_strdup(optarg);
500 case 'V': /* Verbose */
503 case 'x': /* Print packet data in hex (and ASCII) */
509 /* If no capture filter or read filter has been specified, and there are
510 still command-line arguments, treat them as the tokens of a capture
511 filter (if no "-r" flag was specified) or a read filter (if a "-r"
512 flag was specified. */
514 if (cf_name != NULL) {
515 if (rfilter != NULL) {
517 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
520 rfilter = get_args_as_string(argc, argv, optind);
523 if (capture_filter_specified) {
525 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
528 cfile.cfilter = get_args_as_string(argc, argv, optind);
530 capture_option_specified = TRUE;
536 /* Start windows sockets */
537 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
540 /* Notify all registered modules that have had any of their preferences
541 changed either from one of the preferences file or from the command
542 line that its preferences have changed. */
546 if (capture_option_specified)
547 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
552 /* Build the column format array */
553 for (i = 0; i < cfile.cinfo.num_cols; i++) {
554 cfile.cinfo.col_fmt[i] = get_column_format(i);
555 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
556 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
558 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
559 cfile.cinfo.col_data[i] = NULL;
560 if (cfile.cinfo.col_fmt[i] == COL_INFO)
561 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
563 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
567 cfile.snap = WTAP_MAX_PACKET_SIZE;
568 else if (cfile.snap < MIN_PACKET_SIZE)
569 cfile.snap = MIN_PACKET_SIZE;
571 if (rfilter != NULL) {
572 if (!dfilter_compile(rfilter, &rfcode)) {
573 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
578 cfile.rfcode = rfcode;
580 err = open_cap_file(cf_name, FALSE, &cfile);
585 err = load_cap_file(&cfile, out_file_type);
592 /* No capture file specified, so we're supposed to do a live capture;
593 do we have support for live captures? */
598 fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
603 /* Yes; did the user specify an interface to use? */
604 if (cfile.iface == NULL) {
605 /* No - pick the first one from the list of interfaces. */
606 if_list = get_interface_list(&err, err_str);
607 if (if_list == NULL) {
610 case CANT_GET_INTERFACE_LIST:
611 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
615 case NO_INTERFACES_FOUND:
616 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
621 cfile.iface = g_strdup(if_list->data); /* first interface */
622 free_interface_list(if_list);
624 capture(packet_count, out_file_type);
627 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
638 /* Do the low-level work of a capture.
639 Returns TRUE if it succeeds, FALSE otherwise. */
641 capture(int packet_count, int out_file_type)
643 gchar err_str[PCAP_ERRBUF_SIZE];
644 bpf_u_int32 netnum, netmask;
645 struct bpf_program fcode;
646 void (*oldhandler)(int);
650 static const char ppamsg[] = "can't find PPA for ";
653 struct pcap_stat stats;
655 /* Initialize the table of conversations. */
656 epan_conversation_init();
658 /* Initialize protocol-specific variables */
659 init_all_protocols();
661 /* Initialize the common data structures for fragment reassembly.
662 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
663 may free up space for fragments, which it finds by using the
664 data structures that "reassemble_init()" frees. */
667 ld.linktype = WTAP_ENCAP_UNKNOWN;
670 /* Open the network interface to capture from it. */
671 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
673 if (ld.pch == NULL) {
674 /* Well, we couldn't start the capture. */
676 /* On Win32 OSes, the capture devices are probably available to all
677 users; don't warn about permissions problems.
679 Do, however, warn that Token Ring and PPP devices aren't supported. */
680 snprintf(errmsg, sizeof errmsg,
681 "The capture session could not be initiated (%s).\n"
682 "Please check that you have the proper interface specified.\n"
684 "Note that the driver Tethereal uses for packet capture on Windows\n"
685 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
686 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
689 /* If we got a "can't find PPA for XXX" message, warn the user (who
690 is running Ethereal on HP-UX) that they don't have a version
691 of libpcap that properly handles HP-UX (libpcap 0.6.x and later
692 versions, which properly handle HP-UX, say "can't find /dev/dlpi
693 PPA for XXX" rather than "can't find PPA for XXX"). */
694 if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
697 "You are running Tethereal with a version of the libpcap library\n"
698 "that doesn't handle HP-UX network devices well; this means that\n"
699 "Tethereal may not be able to capture packets.\n"
701 "To fix this, you should install libpcap 0.6.2, or a later version\n"
702 "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
703 "packaged binary form from the Software Porting And Archive Centre\n"
704 "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
705 "at the URL lists a number of mirror sites.";
708 snprintf(errmsg, sizeof errmsg,
709 "The capture session could not be initiated (%s).\n"
710 "Please check to make sure you have sufficient permissions, and that\n"
711 "you have the proper interface specified.%s", err_str, libpcap_warn);
717 /* A capture filter was specified; set it up. */
718 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
720 * Well, we can't get the netmask for this interface; it's used
721 * only for filters that check for broadcast IP addresses, so
722 * we just warn the user, and punt and use 0.
725 "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
728 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
729 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
730 pcap_geterr(ld.pch));
733 if (pcap_setfilter(ld.pch, &fcode) < 0) {
734 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
735 pcap_geterr(ld.pch));
740 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
741 if (cfile.save_file != NULL) {
742 /* Set up to write to the capture file. */
743 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
744 strcpy(errmsg, "The network you're capturing from is of a type"
745 " that Tethereal doesn't support.");
748 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
749 ld.linktype, pcap_snapshot(ld.pch), &err);
751 if (ld.pdh == NULL) {
752 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
758 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
760 XXX - deal with signal semantics on various platforms. Or just
761 use "sigaction()" and be done with it? */
762 signal(SIGTERM, capture_cleanup);
763 signal(SIGINT, capture_cleanup);
765 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
766 signal(SIGHUP, oldhandler);
769 /* Let the user know what interface was chosen. */
770 fprintf(stderr, "Capturing on %s\n", cfile.iface);
773 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
775 if (cfile.save_file != NULL) {
776 /* We're saving to a file, which means we're printing packet counts
777 to the standard output. Send a newline so that we move to the
778 line after the packet count. */
779 fprintf(stderr, "\n");
782 /* If we got an error while capturing, report it. */
784 fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
785 pcap_geterr(ld.pch));
788 /* Get the capture statistics, and, if any packets were dropped, report
790 if (pcap_stats(ld.pch, &stats) >= 0) {
791 if (stats.ps_drop != 0) {
792 fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
795 fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
796 pcap_geterr(ld.pch));
800 if (cfile.save_file != NULL) {
801 /* We're saving to a file; close the file. */
802 if (!wtap_dump_close(ld.pdh, &err))
803 show_capture_file_io_error(cfile.save_file, err, TRUE);
809 g_free(cfile.save_file);
810 cfile.save_file = NULL;
811 fprintf(stderr, "tethereal: %s\n", errmsg);
819 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
822 struct wtap_pkthdr whdr;
823 loop_data *ld = (loop_data *) user;
826 whdr.ts.tv_sec = phdr->ts.tv_sec;
827 whdr.ts.tv_usec = phdr->ts.tv_usec;
828 whdr.caplen = phdr->caplen;
829 whdr.len = phdr->len;
830 whdr.pkt_encap = ld->linktype;
835 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
836 fprintf(stderr, "\r%u ", cfile.count);
839 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
844 capture_cleanup(int signum)
848 fprintf(stderr, "\n");
850 if (ld.pdh != NULL) {
851 if (!wtap_dump_close(ld.pdh, &err)) {
852 show_capture_file_io_error(cfile.save_file, err, TRUE);
858 #endif /* HAVE_LIBPCAP */
861 load_cap_file(capture_file *cf, int out_file_type)
869 linktype = wtap_file_encap(cf->wth);
870 if (cf->save_file != NULL) {
871 /* Set up to write to the capture file. */
872 pdh = wtap_dump_open(cf->save_file, out_file_type,
873 linktype, wtap_snapshot_length(cf->wth), &err);
876 /* We couldn't set up to write to the capture file. */
879 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
881 "tethereal: Capture files can't be written in that format.\n");
884 case WTAP_ERR_UNSUPPORTED_ENCAP:
885 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
887 "tethereal: The capture file being read cannot be written in that format.\n");
890 case WTAP_ERR_CANT_OPEN:
892 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
896 case WTAP_ERR_SHORT_WRITE:
898 "tethereal: A full header couldn't be written to the file \"%s\".\n",
905 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
909 "tethereal: The file \"%s\" could not be opened: %s\n.",
910 cf->save_file, strerror(err));
918 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
921 /* Now close the capture file. */
922 if (!wtap_dump_close(pdh, &err))
923 show_capture_file_io_error(cfile.save_file, err, TRUE);
927 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
931 /* Print up a message box noting that the read failed somewhere along
935 case WTAP_ERR_UNSUPPORTED_ENCAP:
937 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
941 case WTAP_ERR_CANT_READ:
943 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
947 case WTAP_ERR_SHORT_READ:
949 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
953 case WTAP_ERR_BAD_RECORD:
955 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
961 "tethereal: An error occurred while reading \"%s\": %s.\n",
962 cf->filename, wtap_strerror(err));
975 fill_in_fdata(frame_data *fdata, capture_file *cf,
976 const struct wtap_pkthdr *phdr,
977 const union wtap_pseudo_header *pseudo_header, int offset)
984 fdata->data_src = NULL;
985 fdata->num = cf->count;
986 fdata->pkt_len = phdr->len;
987 fdata->cap_len = phdr->caplen;
988 fdata->file_off = offset;
990 fdata->lnk_t = phdr->pkt_encap;
991 fdata->abs_secs = phdr->ts.tv_sec;
992 fdata->abs_usecs = phdr->ts.tv_usec;
993 fdata->flags.passed_dfilter = 0;
994 fdata->flags.encoding = CHAR_ASCII;
995 fdata->flags.visited = 0;
996 fdata->flags.marked = 0;
998 /* If we don't have the time stamp of the first packet in the
999 capture, it's because this is the first packet. Save the time
1000 stamp of this packet as the time stamp of the first packet. */
1001 if (!firstsec && !firstusec) {
1002 firstsec = fdata->abs_secs;
1003 firstusec = fdata->abs_usecs;
1006 /* If we don't have the time stamp of the previous displayed packet,
1007 it's because this is the first displayed packet. Save the time
1008 stamp of this packet as the time stamp of the previous displayed
1010 if (!prevsec && !prevusec) {
1011 prevsec = fdata->abs_secs;
1012 prevusec = fdata->abs_usecs;
1015 /* Get the time elapsed between the first packet and this packet. */
1016 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
1017 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
1019 /* If it's greater than the current elapsed time, set the elapsed time
1020 to it (we check for "greater than" so as not to be confused by
1021 time moving backwards). */
1022 if (cf->esec < fdata->rel_secs
1023 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
1024 cf->esec = fdata->rel_secs;
1025 cf->eusec = fdata->rel_usecs;
1028 /* Get the time elapsed between the previous displayed packet and
1030 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
1031 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
1032 prevsec = fdata->abs_secs;
1033 prevusec = fdata->abs_usecs;
1035 fdata->cinfo = &cf->cinfo;
1036 for (i = 0; i < fdata->cinfo->num_cols; i++) {
1037 fdata->cinfo->col_buf[i][0] = '\0';
1038 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
1042 /* Free up all data attached to a "frame_data" structure. */
1044 clear_fdata(frame_data *fdata)
1047 g_slist_free(fdata->pfd);
1048 if (fdata->data_src)
1049 g_slist_free(fdata->data_src);
1053 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1054 union wtap_pseudo_header *pseudo_header, const u_char *buf)
1056 cb_args_t *args = (cb_args_t *) user;
1057 capture_file *cf = args->cf;
1058 wtap_dumper *pdh = args->pdh;
1060 proto_tree *protocol_tree;
1063 epan_dissect_t *edt;
1067 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1068 protocol_tree = proto_tree_create_root();
1069 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1070 passed = dfilter_apply_edt(cf->rfcode, edt);
1072 protocol_tree = NULL;
1077 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
1079 if (ld.pch != NULL) {
1080 /* We're capturing packets, so we're printing a count of packets
1081 captured; move to the line after the count. */
1082 fprintf(stderr, "\n");
1085 show_capture_file_io_error(cf->save_file, err, FALSE);
1090 wtap_dump_close(pdh, &err);
1094 if (protocol_tree != NULL)
1095 proto_tree_free(protocol_tree);
1097 epan_dissect_free(edt);
1099 clear_fdata(&fdata);
1103 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1109 "tethereal: Not all the packets could be written to \"%s\" because there is "
1110 "no space left on the file system.\n",
1117 "tethereal: Not all the packets could be written to \"%s\" because you are "
1118 "too close to, or over your disk quota.\n",
1123 case WTAP_ERR_CANT_CLOSE:
1125 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1129 case WTAP_ERR_SHORT_WRITE:
1131 "tethereal: Not all the packets could be written to \"%s\".\n",
1138 "tethereal: \"%s\" could not be closed: %s.\n",
1139 fname, wtap_strerror(err));
1142 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1143 fname, wtap_strerror(err));
1150 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1151 union wtap_pseudo_header *pseudo_header, const u_char *buf)
1153 cb_args_t *args = (cb_args_t *) user;
1154 capture_file *cf = args->cf;
1156 proto_tree *protocol_tree;
1158 print_args_t print_args;
1159 epan_dissect_t *edt;
1164 /* The protocol tree will be "visible", i.e., printed, only if we're
1165 not printing a summary. */
1166 proto_tree_is_visible = verbose;
1168 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1171 if (cf->rfcode || verbose)
1172 protocol_tree = proto_tree_create_root();
1174 protocol_tree = NULL;
1175 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1177 passed = dfilter_apply_edt(cf->rfcode, edt);
1179 /* The packet passed the read filter. */
1181 /* Print the information in the protocol tree. */
1182 print_args.to_file = TRUE;
1183 print_args.format = PR_FMT_TEXT;
1184 print_args.print_summary = FALSE;
1185 print_args.print_hex = print_hex;
1186 print_args.expand_all = TRUE;
1187 print_args.suppress_unmarked = FALSE;
1188 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1191 /* "print_hex_data()" will put out a leading blank line, as well
1192 as a trailing one; print one here, to separate the packets,
1193 only if "print_hex_data()" won't be called. */
1197 /* Just fill in the columns. */
1198 fill_in_columns(&fdata);
1200 /* Now print them. */
1201 for (i = 0; i < cf->cinfo.num_cols; i++) {
1202 switch (cf->cinfo.col_fmt[i]) {
1205 * Don't print this if we're doing a live capture from a network
1206 * interface - if we're doing a live capture, you won't be
1207 * able to look at the capture in the future (it's not being
1208 * saved anywhere), so the frame numbers are unlikely to be
1211 * (XXX - it might be nice to be able to save and print at
1212 * the same time, sort of like an "Update list of packets
1213 * in real time" capture in Ethereal.)
1215 if (cf->iface != NULL)
1217 printf("%3s", cf->cinfo.col_data[i]);
1223 case COL_ABS_DATE_TIME: /* XXX - wider */
1224 printf("%10s", cf->cinfo.col_data[i]);
1230 case COL_DEF_DL_SRC:
1231 case COL_RES_DL_SRC:
1232 case COL_UNRES_DL_SRC:
1233 case COL_DEF_NET_SRC:
1234 case COL_RES_NET_SRC:
1235 case COL_UNRES_NET_SRC:
1236 printf("%12s", cf->cinfo.col_data[i]);
1242 case COL_DEF_DL_DST:
1243 case COL_RES_DL_DST:
1244 case COL_UNRES_DL_DST:
1245 case COL_DEF_NET_DST:
1246 case COL_RES_NET_DST:
1247 case COL_UNRES_NET_DST:
1248 printf("%-12s", cf->cinfo.col_data[i]);
1252 printf("%s", cf->cinfo.col_data[i]);
1255 if (i != cf->cinfo.num_cols - 1) {
1257 * This isn't the last column, so we need to print a
1258 * separator between this column and the next.
1260 * If we printed a network source and are printing a
1261 * network destination of the same type next, separate
1262 * them with "->"; if we printed a network destination
1263 * and are printing a network source of the same type
1264 * next, separate them with "<-"; otherwise separate them
1267 switch (cf->cinfo.col_fmt[i]) {
1272 switch (cf->cinfo.col_fmt[i + 1]) {
1286 case COL_DEF_DL_SRC:
1287 case COL_RES_DL_SRC:
1288 case COL_UNRES_DL_SRC:
1289 switch (cf->cinfo.col_fmt[i + 1]) {
1291 case COL_DEF_DL_DST:
1292 case COL_RES_DL_DST:
1293 case COL_UNRES_DL_DST:
1303 case COL_DEF_NET_SRC:
1304 case COL_RES_NET_SRC:
1305 case COL_UNRES_NET_SRC:
1306 switch (cf->cinfo.col_fmt[i + 1]) {
1308 case COL_DEF_NET_DST:
1309 case COL_RES_NET_DST:
1310 case COL_UNRES_NET_DST:
1323 switch (cf->cinfo.col_fmt[i + 1]) {
1337 case COL_DEF_DL_DST:
1338 case COL_RES_DL_DST:
1339 case COL_UNRES_DL_DST:
1340 switch (cf->cinfo.col_fmt[i + 1]) {
1342 case COL_DEF_DL_SRC:
1343 case COL_RES_DL_SRC:
1344 case COL_UNRES_DL_SRC:
1354 case COL_DEF_NET_DST:
1355 case COL_RES_NET_DST:
1356 case COL_UNRES_NET_DST:
1357 switch (cf->cinfo.col_fmt[i + 1]) {
1359 case COL_DEF_NET_SRC:
1360 case COL_RES_NET_SRC:
1361 case COL_UNRES_NET_SRC:
1380 print_hex_data(stdout, print_args.format, &fdata);
1386 /* The ANSI C standard does not appear to *require* that a line-buffered
1387 stream be flushed to the host environment whenever a newline is
1388 written, it just says that, on such a stream, characters "are
1389 intended to be transmitted to or from the host environment as a
1390 block when a new-line character is encountered".
1392 The Visual C++ 6.0 C implementation doesn't do what is intended;
1393 even if you set a stream to be line-buffered, it still doesn't
1394 flush the buffer at the end of every line.
1396 So, if the "-l" flag was specified, we flush the standard output
1397 at the end of a packet. This will do the right thing if we're
1398 printing packet summary lines, and, as we print the entire protocol
1399 tree for a single packet without waiting for anything to happen,
1400 it should be as good as line-buffered mode if we're printing
1401 protocol trees. (The whole reason for the "-l" flag in either
1402 tcpdump or Tethereal is to allow the output of a live capture to
1403 be piped to a program or script and to have that script see the
1404 information for the packet as soon as it's printed, rather than
1405 having to wait until a standard I/O buffer fills up. */
1408 if (protocol_tree != NULL)
1409 proto_tree_free(protocol_tree);
1411 epan_dissect_free(edt);
1413 clear_fdata(&fdata);
1415 proto_tree_is_visible = FALSE;
1419 file_open_error_message(int err, gboolean for_writing)
1422 static char errmsg_errno[1024+1];
1426 case WTAP_ERR_NOT_REGULAR_FILE:
1427 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1430 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1431 case WTAP_ERR_UNSUPPORTED:
1432 /* Seen only when opening a capture file for reading. */
1433 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1436 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1437 /* Seen only when opening a capture file for writing. */
1438 errmsg = "Tethereal does not support writing capture files in that format.";
1441 case WTAP_ERR_UNSUPPORTED_ENCAP:
1442 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1444 errmsg = "Tethereal cannot save this capture in that format.";
1446 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1449 case WTAP_ERR_BAD_RECORD:
1450 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1453 case WTAP_ERR_CANT_OPEN:
1455 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1457 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1460 case WTAP_ERR_SHORT_READ:
1461 errmsg = "The file \"%s\" appears to have been cut short"
1462 " in the middle of a packet.";
1465 case WTAP_ERR_SHORT_WRITE:
1466 errmsg = "A full header couldn't be written to the file \"%s\".";
1471 errmsg = "The path to the file \"%s\" does not exist.";
1473 errmsg = "The file \"%s\" does not exist.";
1478 errmsg = "You do not have permission to create or write to the file \"%s\".";
1480 errmsg = "You do not have permission to read the file \"%s\".";
1484 errmsg = "\"%s\" is a directory (folder), not a file.";
1488 snprintf(errmsg_errno, sizeof(errmsg_errno),
1489 "The file \"%%s\" could not be opened: %s.",
1490 wtap_strerror(err));
1491 errmsg = errmsg_errno;
1498 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1503 struct stat cf_stat;
1504 char err_msg[2048+1];
1506 wth = wtap_open_offline(fname, &err, FALSE);
1510 /* Find the size of the file. */
1512 if (fstat(fd, &cf_stat) < 0) {
1518 /* The open succeeded. Fill in the information for this file. */
1520 /* Initialize the table of conversations. */
1521 epan_conversation_init();
1523 /* Initialize protocol-specific variables */
1524 init_all_protocols();
1526 /* Initialize the common data structures for fragment reassembly.
1527 Must be done *after* "init_all_protocols()", as "init_all_protocols()"
1528 may free up space for fragments, which it finds by using the
1529 data structures that "reassemble_init()" frees. */
1534 cf->f_len = cf_stat.st_size;
1536 /* Set the file name because we need it to set the follow stream filter.
1537 XXX - is that still true? We need it for other reasons, though,
1539 cf->filename = g_strdup(fname);
1541 /* Indicate whether it's a permanent or temporary file. */
1542 cf->is_tempfile = is_tempfile;
1544 /* If it's a temporary capture buffer file, mark it as not saved. */
1545 cf->user_saved = !is_tempfile;
1547 cf->cd_t = wtap_file_type(cf->wth);
1549 cf->drops_known = FALSE;
1553 cf->snap = wtap_snapshot_length(cf->wth);
1554 cf->progbar_quantum = 0;
1555 cf->progbar_nextstep = 0;
1556 firstsec = 0, firstusec = 0;
1557 prevsec = 0, prevusec = 0;
1562 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1563 fprintf(stderr, "tethereal: %s\n", err_msg);