3 * $Id: tethereal.c,v 1.77 2001/04/07 06:58:17 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
7 * Copyright 1998 Gerald Combs
9 * Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
46 #ifdef HAVE_SYS_STAT_H
60 #ifdef NEED_SNPRINTF_H
61 # include "snprintf.h"
64 #if defined(HAVE_UCD_SNMP_SNMP_H)
65 #ifdef HAVE_UCD_SNMP_VERSION_H
66 #include <ucd-snmp/version.h>
67 #endif /* HAVE_UCD_SNMP_VERSION_H */
68 #elif defined(HAVE_SNMP_SNMP_H)
69 #ifdef HAVE_SNMP_VERSION_H
70 #include <snmp/version.h>
71 #endif /* HAVE_SNMP_VERSION_H */
74 #ifdef NEED_STRERROR_H
86 #include "timestamp.h"
94 #include "conversation.h"
99 #include "capture-wpcap.h"
102 static guint32 firstsec, firstusec;
103 static guint32 prevsec, prevusec;
104 static GString *comp_info_str;
105 static gboolean verbose;
106 static gboolean print_hex;
107 static gboolean line_buffered;
110 typedef struct _loop_data {
118 static int capture(int, int);
119 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
121 static void capture_cleanup(int);
129 static int load_cap_file(capture_file *, int);
130 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
131 union wtap_pseudo_header *, const u_char *);
132 static void show_capture_file_io_error(const char *, int, gboolean);
133 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
134 union wtap_pseudo_header *, const u_char *);
138 FILE *data_out_file = NULL;
139 guint main_ctx, file_ctx;
140 ts_type timestamp_type = RELATIVE;
142 static int promisc_mode = TRUE;
150 fprintf(stderr, "This is GNU t%s %s, compiled %s\n", PACKAGE, VERSION,
153 fprintf(stderr, "t%s [ -DvVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
154 fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
155 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
156 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
158 fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
159 fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
160 fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
162 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
163 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
164 if (wtap_dump_can_open(i))
165 fprintf(stderr, "\t%s - %s\n",
166 wtap_file_type_short_string(i), wtap_file_type_string(i));
168 fprintf(stderr, "\tdefault is libpcap\n");
172 main(int argc, char *argv[])
176 gboolean arg_error = FALSE;
179 char pcap_version[] = WPCAP_STRING;
181 extern char pcap_version[];
189 char *gpf_path, *pf_path;
190 int gpf_open_errno, pf_open_errno;
193 gboolean capture_filter_specified = FALSE;
194 int packet_count = 0;
195 GList *if_list, *if_entry;
196 gchar err_str[PCAP_ERRBUF_SIZE];
198 gboolean capture_option_specified = FALSE;
200 int out_file_type = WTAP_FILE_PCAP;
201 gchar *cf_name = NULL, *rfilter = NULL;
202 dfilter_t *rfcode = NULL;
205 /* Register all dissectors; we must do this before checking for the
206 "-G" flag, as the "-G" flag dumps a list of fields registered
207 by the dissectors, and we must do it before we read the preferences,
208 in case any dissectors register preferences. */
209 epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
211 /* Now register the preferences for any non-dissector modules.
212 We must do that before we read the preferences as well. */
213 prefs_register_modules();
215 /* If invoked with the "-G" flag, we dump out a glossary of
216 display filter symbols.
218 We do this here to mirror what happens in the GTK+ version, although
219 it's not necessary here. */
220 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
221 proto_registrar_dump();
225 /* Set the C-language locale to the native environment. */
226 setlocale(LC_ALL, "");
228 prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
229 if (gpf_path != NULL) {
230 fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
231 strerror(gpf_open_errno));
233 if (pf_path != NULL) {
234 fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
235 strerror(pf_open_errno));
239 /* Load Wpcap, if possible */
243 /* Initialize the capture file struct */
245 cfile.plist_end = NULL;
247 cfile.filename = NULL;
248 cfile.user_saved = FALSE;
249 cfile.is_tempfile = FALSE;
251 cfile.dfilter = NULL;
254 cfile.cfilter = g_strdup("");
257 cfile.save_file = NULL;
258 cfile.save_file_fd = -1;
259 cfile.snap = WTAP_MAX_PACKET_SIZE;
261 col_init(&cfile.cinfo, prefs->num_cols);
263 /* Assemble the compile-time options */
264 comp_info_str = g_string_new("");
266 g_string_append(comp_info_str, "with ");
267 g_string_sprintfa(comp_info_str,
268 #ifdef GLIB_MAJOR_VERSION
269 "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
272 "GLib (version unknown)");
276 g_string_append(comp_info_str, ", with libpcap ");
277 g_string_append(comp_info_str, pcap_version);
279 g_string_append(comp_info_str, ", without libpcap");
283 g_string_append(comp_info_str, ", with libz ");
285 g_string_append(comp_info_str, ZLIB_VERSION);
286 #else /* ZLIB_VERSION */
287 g_string_append(comp_info_str, "(version unknown)");
288 #endif /* ZLIB_VERSION */
289 #else /* HAVE_LIBZ */
290 g_string_append(comp_info_str, ", without libz");
291 #endif /* HAVE_LIBZ */
293 /* Oh, this is pretty */
294 #if defined(HAVE_UCD_SNMP_SNMP_H)
295 g_string_append(comp_info_str, ", with UCD SNMP ");
296 #ifdef HAVE_UCD_SNMP_VERSION_H
297 g_string_append(comp_info_str, VersionInfo);
298 #else /* HAVE_UCD_SNMP_VERSION_H */
299 g_string_append(comp_info_str, "(version unknown)");
300 #endif /* HAVE_UCD_SNMP_VERSION_H */
301 #elif defined(HAVE_SNMP_SNMP_H)
302 g_string_append(comp_info_str, ", with CMU SNMP ");
303 #ifdef HAVE_SNMP_VERSION_H
304 g_string_append(comp_info_str, snmp_Version());
305 #else /* HAVE_SNMP_VERSION_H */
306 g_string_append(comp_info_str, "(version unknown)");
307 #endif /* HAVE_SNMP_VERSION_H */
309 g_string_append(comp_info_str, ", without SNMP");
312 /* Now get our args */
313 while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
315 case 'c': /* Capture xxx packets */
317 packet_count = atoi(optarg);
319 capture_option_specified = TRUE;
323 case 'D': /* Print a list of capture devices */
325 if_list = get_interface_list(&err, err_str);
326 if (if_list == NULL) {
329 case CANT_GET_INTERFACE_LIST:
330 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
334 case NO_INTERFACES_FOUND:
335 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
340 for (if_entry = g_list_first(if_list); if_entry != NULL;
341 if_entry = g_list_next(if_entry))
342 printf("%s\n", (char *)if_entry->data);
343 free_interface_list(if_list);
346 capture_option_specified = TRUE;
352 capture_filter_specified = TRUE;
353 cfile.cfilter = g_strdup(optarg);
355 capture_option_specified = TRUE;
360 out_file_type = wtap_short_string_to_file_type(optarg);
361 if (out_file_type < 0) {
362 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
367 case 'h': /* Print help and exit */
371 case 'i': /* Use interface xxx */
373 cfile.iface = g_strdup(optarg);
375 capture_option_specified = TRUE;
379 case 'l': /* "Line-buffer" standard output */
380 /* This isn't line-buffering, strictly speaking, it's just
381 flushing the standard output after the information for
382 each packet is printed; however, that should be good
383 enough for all the purposes to which "-l" is put.
385 See the comment in "wtap_dispatch_cb_print()" for an
386 explanation of why we do that, and why we don't just
387 use "setvbuf()" to make the standard output line-buffered
388 (short version: in Windows, "line-buffered" is the same
389 as "fully-buffered", and the output buffer is only flushed
390 when it fills up). */
391 line_buffered = TRUE;
393 case 'n': /* No name resolution */
394 g_resolving_actif = 0;
396 case 'o': /* Override preference from command line */
397 switch (prefs_set_pref(optarg)) {
399 case PREFS_SET_SYNTAX_ERR:
400 fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
404 case PREFS_SET_NO_SUCH_PREF:
405 fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
411 case 'p': /* Don't capture in promiscuous mode */
415 capture_option_specified = TRUE;
419 case 'r': /* Read capture file xxx */
420 cf_name = g_strdup(optarg);
422 case 'R': /* Read file filter */
425 case 's': /* Set the snapshot (capture) length */
427 cfile.snap = atoi(optarg);
429 capture_option_specified = TRUE;
433 case 't': /* Time stamp type */
434 if (strcmp(optarg, "r") == 0)
435 timestamp_type = RELATIVE;
436 else if (strcmp(optarg, "a") == 0)
437 timestamp_type = ABSOLUTE;
438 else if (strcmp(optarg, "ad") == 0)
439 timestamp_type = ABSOLUTE_WITH_DATE;
440 else if (strcmp(optarg, "d") == 0)
441 timestamp_type = DELTA;
443 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
445 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
446 fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
450 case 'v': /* Show version and exit */
451 printf("t%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
454 case 'w': /* Write to capture file xxx */
455 cfile.save_file = g_strdup(optarg);
457 case 'V': /* Verbose */
460 case 'x': /* Print packet data in hex (and ASCII) */
466 /* If no capture filter or read filter has been specified, and there are
467 still command-line arguments, treat them as the tokens of a capture
468 filter (if no "-r" flag was specified) or a read filter (if a "-r"
469 flag was specified. */
471 if (cf_name != NULL) {
472 if (rfilter != NULL) {
474 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
477 rfilter = get_args_as_string(argc, argv, optind);
480 if (capture_filter_specified) {
482 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
485 cfile.cfilter = get_args_as_string(argc, argv, optind);
487 capture_option_specified = TRUE;
493 /* Start windows sockets */
494 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
497 /* Notify all registered modules that have had any of their preferences
498 changed either from one of the preferences file or from the command
499 line that its preferences have changed. */
503 if (capture_option_specified)
504 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
509 /* Build the column format array */
510 for (i = 0; i < cfile.cinfo.num_cols; i++) {
511 cfile.cinfo.col_fmt[i] = get_column_format(i);
512 cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
513 cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
515 get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
516 cfile.cinfo.col_data[i] = NULL;
517 if (cfile.cinfo.col_fmt[i] == COL_INFO)
518 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
520 cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
524 cfile.snap = WTAP_MAX_PACKET_SIZE;
525 else if (cfile.snap < MIN_PACKET_SIZE)
526 cfile.snap = MIN_PACKET_SIZE;
528 if (rfilter != NULL) {
529 if (!dfilter_compile(rfilter, &rfcode)) {
530 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
535 cfile.rfcode = rfcode;
537 err = open_cap_file(cf_name, FALSE, &cfile);
542 err = load_cap_file(&cfile, out_file_type);
549 /* No capture file specified, so we're supposed to do a live capture;
550 do we have support for live captures? */
555 fprintf(stderr, "tethereal: Could not load wpcap.dll.\n");
560 /* Yes; did the user specify an interface to use? */
561 if (cfile.iface == NULL) {
562 /* No - pick the first one from the list of interfaces. */
563 if_list = get_interface_list(&err, err_str);
564 if (if_list == NULL) {
567 case CANT_GET_INTERFACE_LIST:
568 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
572 case NO_INTERFACES_FOUND:
573 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
578 cfile.iface = g_strdup(if_list->data); /* first interface */
579 free_interface_list(if_list);
581 capture(packet_count, out_file_type);
584 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
595 /* Do the low-level work of a capture.
596 Returns TRUE if it succeeds, FALSE otherwise. */
598 capture(int packet_count, int out_file_type)
600 gchar err_str[PCAP_ERRBUF_SIZE];
601 bpf_u_int32 netnum, netmask;
602 struct bpf_program fcode;
603 void (*oldhandler)(int);
607 static const char ppamsg[] = "can't find PPA for ";
610 struct pcap_stat stats;
612 /* Initialize the table of conversations. */
613 epan_conversation_init();
615 /* Initialize protocol-specific variables */
616 init_all_protocols();
618 ld.linktype = WTAP_ENCAP_UNKNOWN;
621 /* Open the network interface to capture from it. */
622 ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
624 if (ld.pch == NULL) {
625 /* Well, we couldn't start the capture. */
627 /* On Win32 OSes, the capture devices are probably available to all
628 users; don't warn about permissions problems.
630 Do, however, warn that Token Ring and PPP devices aren't supported. */
631 snprintf(errmsg, sizeof errmsg,
632 "The capture session could not be initiated (%s).\n"
633 "Please check that you have the proper interface specified.\n"
635 "Note that the driver Tethereal uses for packet capture on Windows\n"
636 "doesn't support capturing on Token Ring interfaces, and doesn't\n"
637 "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
640 /* If we got a "can't find PPA for XXX" message, warn the user (who
641 is running Ethereal on HP-UX) that they don't have a version
642 of libpcap patched to properly handle HP-UX (the patched version
643 says "can't find /dev/dlpi PPA for XXX" rather than "can't find
645 if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
648 "You are running Tethereal with a version of the libpcap library\n"
649 "that doesn't handle HP-UX network devices well; this means that\n"
650 "Tethereal may not be able to capture packets.\n"
652 "To fix this, you will need to download the source to Tethereal\n"
653 "from www.ethereal.com if you have not already done so, read\n"
654 "the instructions in the \"README.hpux\" file in the source\n"
655 "distribution, download the source to libpcap if you have not\n"
656 "already done so, patch libpcap as per the instructions, rebuild\n"
657 "and install libpcap, and then build Tethereal (if you have already\n"
658 "built Tethereal from source, do a \"make distclean\" and re-run\n"
659 "configure before building).";
662 snprintf(errmsg, sizeof errmsg,
663 "The capture session could not be initiated (%s).\n"
664 "Please check to make sure you have sufficient permissions, and that\n"
665 "you have the proper interface specified.%s", err_str, libpcap_warn);
671 /* A capture filter was specified; set it up. */
672 if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
674 * Well, we can't get the netmask for this interface; it's used
675 * only for filters that check for broadcast IP addresses, so
676 * we just warn the user, and punt and use 0.
679 "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
682 if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
683 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
684 pcap_geterr(ld.pch));
687 if (pcap_setfilter(ld.pch, &fcode) < 0) {
688 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
689 pcap_geterr(ld.pch));
694 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
695 if (cfile.save_file != NULL) {
696 /* Set up to write to the capture file. */
697 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
698 strcpy(errmsg, "The network you're capturing from is of a type"
699 " that Tethereal doesn't support.");
702 ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
703 ld.linktype, pcap_snapshot(ld.pch), &err);
705 if (ld.pdh == NULL) {
706 snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
712 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
714 XXX - deal with signal semantics on various platforms. Or just
715 use "sigaction()" and be done with it? */
716 signal(SIGTERM, capture_cleanup);
717 signal(SIGINT, capture_cleanup);
719 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
720 signal(SIGHUP, oldhandler);
723 /* Let the user know what interface was chosen. */
724 fprintf(stderr, "Capturing on %s\n", cfile.iface);
727 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
729 if (cfile.save_file != NULL) {
730 /* We're saving to a file, which means we're printing packet counts
731 to the standard output. Send a newline so that we move to the
732 line after the packet count. */
733 fprintf(stderr, "\n");
736 /* If we got an error while capturing, report it. */
738 fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
739 pcap_geterr(ld.pch));
742 /* Get the capture statistics, and, if any packets were dropped, report
744 if (pcap_stats(ld.pch, &stats) >= 0) {
745 if (stats.ps_drop != 0) {
746 fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
749 fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
750 pcap_geterr(ld.pch));
757 g_free(cfile.save_file);
758 cfile.save_file = NULL;
759 fprintf(stderr, "tethereal: %s\n", errmsg);
767 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
770 struct wtap_pkthdr whdr;
771 loop_data *ld = (loop_data *) user;
774 whdr.ts.tv_sec = phdr->ts.tv_sec;
775 whdr.ts.tv_usec = phdr->ts.tv_usec;
776 whdr.caplen = phdr->caplen;
777 whdr.len = phdr->len;
778 whdr.pkt_encap = ld->linktype;
783 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
784 fprintf(stderr, "\r%u ", cfile.count);
787 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
792 capture_cleanup(int signum)
796 fprintf(stderr, "\n");
798 if (ld.pdh != NULL) {
799 if (!wtap_dump_close(ld.pdh, &err)) {
800 show_capture_file_io_error(cfile.save_file, err, TRUE);
806 #endif /* HAVE_LIBPCAP */
809 load_cap_file(capture_file *cf, int out_file_type)
817 linktype = wtap_file_encap(cf->wth);
818 if (cf->save_file != NULL) {
819 /* Set up to write to the capture file. */
820 pdh = wtap_dump_open(cf->save_file, out_file_type,
821 linktype, wtap_snapshot_length(cf->wth), &err);
824 /* We couldn't set up to write to the capture file. */
827 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
829 "tethereal: Capture files can't be written in that format.\n");
832 case WTAP_ERR_UNSUPPORTED_ENCAP:
833 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
835 "tethereal: The capture file being read cannot be written in that format.\n");
838 case WTAP_ERR_CANT_OPEN:
840 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
844 case WTAP_ERR_SHORT_WRITE:
846 "tethereal: A full header couldn't be written to the file \"%s\".\n",
853 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
857 "tethereal: The file \"%s\" could not be opened: %s\n.",
858 cf->save_file, strerror(err));
866 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
871 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
875 /* Print up a message box noting that the read failed somewhere along
879 case WTAP_ERR_UNSUPPORTED_ENCAP:
881 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
885 case WTAP_ERR_CANT_READ:
887 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
891 case WTAP_ERR_SHORT_READ:
893 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
897 case WTAP_ERR_BAD_RECORD:
899 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
905 "tethereal: An error occurred while reading \"%s\": %s.\n",
906 cf->filename, wtap_strerror(err));
919 fill_in_fdata(frame_data *fdata, capture_file *cf,
920 const struct wtap_pkthdr *phdr,
921 const union wtap_pseudo_header *pseudo_header, int offset)
928 fdata->data_src = NULL;
929 fdata->num = cf->count;
930 fdata->pkt_len = phdr->len;
931 fdata->cap_len = phdr->caplen;
932 fdata->file_off = offset;
934 fdata->lnk_t = phdr->pkt_encap;
935 fdata->abs_secs = phdr->ts.tv_sec;
936 fdata->abs_usecs = phdr->ts.tv_usec;
937 fdata->flags.passed_dfilter = 0;
938 fdata->flags.encoding = CHAR_ASCII;
939 fdata->flags.visited = 0;
940 fdata->flags.marked = 0;
942 /* If we don't have the time stamp of the first packet in the
943 capture, it's because this is the first packet. Save the time
944 stamp of this packet as the time stamp of the first packet. */
945 if (!firstsec && !firstusec) {
946 firstsec = fdata->abs_secs;
947 firstusec = fdata->abs_usecs;
950 /* If we don't have the time stamp of the previous displayed packet,
951 it's because this is the first displayed packet. Save the time
952 stamp of this packet as the time stamp of the previous displayed
954 if (!prevsec && !prevusec) {
955 prevsec = fdata->abs_secs;
956 prevusec = fdata->abs_usecs;
959 /* Get the time elapsed between the first packet and this packet. */
960 compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
961 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
963 /* If it's greater than the current elapsed time, set the elapsed time
964 to it (we check for "greater than" so as not to be confused by
965 time moving backwards). */
966 if (cf->esec < fdata->rel_secs
967 || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
968 cf->esec = fdata->rel_secs;
969 cf->eusec = fdata->rel_usecs;
972 /* Get the time elapsed between the previous displayed packet and
974 compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
975 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
976 prevsec = fdata->abs_secs;
977 prevusec = fdata->abs_usecs;
979 fdata->cinfo = &cf->cinfo;
980 for (i = 0; i < fdata->cinfo->num_cols; i++) {
981 fdata->cinfo->col_buf[i][0] = '\0';
982 fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
986 /* Free up all data attached to a "frame_data" structure. */
988 clear_fdata(frame_data *fdata)
991 g_slist_free(fdata->pfd);
993 g_slist_free(fdata->data_src);
997 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
998 union wtap_pseudo_header *pseudo_header, const u_char *buf)
1000 cb_args_t *args = (cb_args_t *) user;
1001 capture_file *cf = args->cf;
1002 wtap_dumper *pdh = args->pdh;
1004 proto_tree *protocol_tree;
1007 epan_dissect_t *edt;
1011 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1012 protocol_tree = proto_tree_create_root();
1013 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1014 passed = dfilter_apply_edt(cf->rfcode, edt);
1016 protocol_tree = NULL;
1021 if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
1023 if (ld.pch != NULL) {
1024 /* We're capturing packets, so we're printing a count of packets
1025 captured; move to the line after the count. */
1026 fprintf(stderr, "\n");
1029 show_capture_file_io_error(cf->save_file, err, FALSE);
1034 wtap_dump_close(pdh, &err);
1038 if (protocol_tree != NULL)
1039 proto_tree_free(protocol_tree);
1041 epan_dissect_free(edt);
1043 clear_fdata(&fdata);
1047 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
1053 "tethereal: Not all the packets could be written to \"%s\" because there is "
1054 "no space left on the file system.\n",
1061 "tethereal: Not all the packets could be written to \"%s\" because you are "
1062 "too close to, or over your disk quota.\n",
1067 case WTAP_ERR_CANT_CLOSE:
1069 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1073 case WTAP_ERR_SHORT_WRITE:
1075 "tethereal: Not all the packets could be written to \"%s\".\n",
1082 "tethereal: \"%s\" could not be closed: %s.\n",
1083 fname, wtap_strerror(err));
1086 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1087 fname, wtap_strerror(err));
1094 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1095 union wtap_pseudo_header *pseudo_header, const u_char *buf)
1097 cb_args_t *args = (cb_args_t *) user;
1098 capture_file *cf = args->cf;
1100 proto_tree *protocol_tree;
1102 print_args_t print_args;
1103 epan_dissect_t *edt;
1108 /* The protocol tree will be "visible", i.e., printed, only if we're
1109 not printing a summary. */
1110 proto_tree_is_visible = verbose;
1112 fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1115 if (cf->rfcode || verbose)
1116 protocol_tree = proto_tree_create_root();
1118 protocol_tree = NULL;
1119 edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1121 passed = dfilter_apply_edt(cf->rfcode, edt);
1123 /* The packet passed the read filter. */
1125 /* Print the information in the protocol tree. */
1126 print_args.to_file = TRUE;
1127 print_args.format = PR_FMT_TEXT;
1128 print_args.print_summary = FALSE;
1129 print_args.print_hex = print_hex;
1130 print_args.expand_all = TRUE;
1131 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1132 buf, &fdata, stdout);
1134 /* "print_hex_data()" will put out a leading blank line, as well
1135 as a trailing one; print one here, to separate the packets,
1136 only if "print_hex_data()" won't be called. */
1140 /* Just fill in the columns. */
1141 fill_in_columns(&fdata);
1143 /* Now print them. */
1144 for (i = 0; i < cf->cinfo.num_cols; i++) {
1145 switch (cf->cinfo.col_fmt[i]) {
1148 * Don't print this if we're doing a live capture from a network
1149 * interface - if we're doing a live capture, you won't be
1150 * able to look at the capture in the future (it's not being
1151 * saved anywhere), so the frame numbers are unlikely to be
1154 * (XXX - it might be nice to be able to save and print at
1155 * the same time, sort of like an "Update list of packets
1156 * in real time" capture in Ethereal.)
1158 if (cf->iface != NULL)
1160 printf("%3s", cf->cinfo.col_data[i]);
1166 case COL_ABS_DATE_TIME: /* XXX - wider */
1167 printf("%10s", cf->cinfo.col_data[i]);
1173 case COL_DEF_DL_SRC:
1174 case COL_RES_DL_SRC:
1175 case COL_UNRES_DL_SRC:
1176 case COL_DEF_NET_SRC:
1177 case COL_RES_NET_SRC:
1178 case COL_UNRES_NET_SRC:
1179 printf("%12s", cf->cinfo.col_data[i]);
1185 case COL_DEF_DL_DST:
1186 case COL_RES_DL_DST:
1187 case COL_UNRES_DL_DST:
1188 case COL_DEF_NET_DST:
1189 case COL_RES_NET_DST:
1190 case COL_UNRES_NET_DST:
1191 printf("%-12s", cf->cinfo.col_data[i]);
1195 printf("%s", cf->cinfo.col_data[i]);
1198 if (i != cf->cinfo.num_cols - 1) {
1200 * This isn't the last column, so we need to print a
1201 * separator between this column and the next.
1203 * If we printed a network source and are printing a
1204 * network destination of the same type next, separate
1205 * them with "->"; if we printed a network destination
1206 * and are printing a network source of the same type
1207 * next, separate them with "<-"; otherwise separate them
1210 switch (cf->cinfo.col_fmt[i]) {
1215 switch (cf->cinfo.col_fmt[i + 1]) {
1229 case COL_DEF_DL_SRC:
1230 case COL_RES_DL_SRC:
1231 case COL_UNRES_DL_SRC:
1232 switch (cf->cinfo.col_fmt[i + 1]) {
1234 case COL_DEF_DL_DST:
1235 case COL_RES_DL_DST:
1236 case COL_UNRES_DL_DST:
1246 case COL_DEF_NET_SRC:
1247 case COL_RES_NET_SRC:
1248 case COL_UNRES_NET_SRC:
1249 switch (cf->cinfo.col_fmt[i + 1]) {
1251 case COL_DEF_NET_DST:
1252 case COL_RES_NET_DST:
1253 case COL_UNRES_NET_DST:
1266 switch (cf->cinfo.col_fmt[i + 1]) {
1280 case COL_DEF_DL_DST:
1281 case COL_RES_DL_DST:
1282 case COL_UNRES_DL_DST:
1283 switch (cf->cinfo.col_fmt[i + 1]) {
1285 case COL_DEF_DL_SRC:
1286 case COL_RES_DL_SRC:
1287 case COL_UNRES_DL_SRC:
1297 case COL_DEF_NET_DST:
1298 case COL_RES_NET_DST:
1299 case COL_UNRES_NET_DST:
1300 switch (cf->cinfo.col_fmt[i + 1]) {
1302 case COL_DEF_NET_SRC:
1303 case COL_RES_NET_SRC:
1304 case COL_UNRES_NET_SRC:
1323 print_hex_data(stdout, print_args.format, &fdata);
1329 /* The ANSI C standard does not appear to *require* that a line-buffered
1330 stream be flushed to the host environment whenever a newline is
1331 written, it just says that, on such a stream, characters "are
1332 intended to be transmitted to or from the host environment as a
1333 block when a new-line character is encountered".
1335 The Visual C++ 6.0 C implementation doesn't do what is intended;
1336 even if you set a stream to be line-buffered, it still doesn't
1337 flush the buffer at the end of every line.
1339 So, if the "-l" flag was specified, we flush the standard output
1340 at the end of a packet. This will do the right thing if we're
1341 printing packet summary lines, and, as we print the entire protocol
1342 tree for a single packet without waiting for anything to happen,
1343 it should be as good as line-buffered mode if we're printing
1344 protocol trees. (The whole reason for the "-l" flag in either
1345 tcpdump or Tethereal is to allow the output of a live capture to
1346 be piped to a program or script and to have that script see the
1347 information for the packet as soon as it's printed, rather than
1348 having to wait until a standard I/O buffer fills up. */
1351 if (protocol_tree != NULL)
1352 proto_tree_free(protocol_tree);
1354 epan_dissect_free(edt);
1356 clear_fdata(&fdata);
1358 proto_tree_is_visible = FALSE;
1362 file_open_error_message(int err, gboolean for_writing)
1365 static char errmsg_errno[1024+1];
1369 case WTAP_ERR_NOT_REGULAR_FILE:
1370 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1373 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1374 case WTAP_ERR_UNSUPPORTED:
1375 /* Seen only when opening a capture file for reading. */
1376 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1379 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1380 /* Seen only when opening a capture file for writing. */
1381 errmsg = "Tethereal does not support writing capture files in that format.";
1384 case WTAP_ERR_UNSUPPORTED_ENCAP:
1385 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1387 errmsg = "Tethereal cannot save this capture in that format.";
1389 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1392 case WTAP_ERR_BAD_RECORD:
1393 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1396 case WTAP_ERR_CANT_OPEN:
1398 errmsg = "The file \"%s\" could not be created for some unknown reason.";
1400 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1403 case WTAP_ERR_SHORT_READ:
1404 errmsg = "The file \"%s\" appears to have been cut short"
1405 " in the middle of a packet.";
1408 case WTAP_ERR_SHORT_WRITE:
1409 errmsg = "A full header couldn't be written to the file \"%s\".";
1414 errmsg = "The path to the file \"%s\" does not exist.";
1416 errmsg = "The file \"%s\" does not exist.";
1421 errmsg = "You do not have permission to create or write to the file \"%s\".";
1423 errmsg = "You do not have permission to read the file \"%s\".";
1427 errmsg = "\"%s\" is a directory (folder), not a file.";
1431 snprintf(errmsg_errno, sizeof(errmsg_errno),
1432 "The file \"%%s\" could not be opened: %s.",
1433 wtap_strerror(err));
1434 errmsg = errmsg_errno;
1441 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1447 struct stat cf_stat;
1448 char err_msg[2048+1];
1450 wth = wtap_open_offline(fname, &err, FALSE);
1454 /* Find the size of the file. */
1455 fh = wtap_file(wth);
1457 if (fstat(fd, &cf_stat) < 0) {
1463 /* The open succeeded. Fill in the information for this file. */
1465 /* Initialize the table of conversations. */
1466 epan_conversation_init();
1468 /* Initialize protocol-specific variables */
1469 init_all_protocols();
1473 cf->f_len = cf_stat.st_size;
1475 /* Set the file name because we need it to set the follow stream filter.
1476 XXX - is that still true? We need it for other reasons, though,
1478 cf->filename = g_strdup(fname);
1480 /* Indicate whether it's a permanent or temporary file. */
1481 cf->is_tempfile = is_tempfile;
1483 /* If it's a temporary capture buffer file, mark it as not saved. */
1484 cf->user_saved = !is_tempfile;
1486 cf->cd_t = wtap_file_type(cf->wth);
1488 cf->drops_known = FALSE;
1492 cf->snap = wtap_snapshot_length(cf->wth);
1493 cf->progbar_quantum = 0;
1494 cf->progbar_nextstep = 0;
1495 firstsec = 0, firstusec = 0;
1496 prevsec = 0, prevusec = 0;
1501 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1502 fprintf(stderr, "tethereal: %s\n", err_msg);