3 * $Id: tethereal.c,v 1.19 2000/02/19 07:59:54 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.
40 #include <sys/types.h>
45 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
54 #if defined(HAVE_UCD_SNMP_SNMP_H)
55 #ifdef HAVE_UCD_SNMP_VERSION_H
56 #include <ucd-snmp/version.h>
57 #endif /* HAVE_UCD_SNMP_VERSION_H */
58 #elif defined(HAVE_SNMP_SNMP_H)
59 #ifdef HAVE_SNMP_VERSION_H
60 #include <snmp/version.h>
61 #endif /* HAVE_SNMP_VERSION_H */
64 #ifdef NEED_STRERROR_H
69 #include "timestamp.h"
79 #include "conversation.h"
82 static guint32 firstsec, firstusec;
83 static guint32 prevsec, prevusec;
84 static gchar comp_info_str[256];
85 static gboolean verbose;
86 static gboolean print_hex;
89 typedef struct _loop_data {
97 static int capture(int, int);
98 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
100 static void capture_cleanup(int);
108 static int load_cap_file(capture_file *, int);
109 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
111 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
113 static gchar *col_info(frame_data *, gint);
117 FILE *data_out_file = NULL;
118 guint main_ctx, file_ctx;
119 ts_type timestamp_type = RELATIVE;
121 /* call initialization routines at program startup time */
123 ethereal_proto_init(void) {
134 ethereal_proto_cleanup(void) {
144 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
145 VERSION, comp_info_str);
147 fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <filter expression> ]\n", PACKAGE);
148 fprintf(stderr, "\t[ -F <capture file type> ] [ -i iface ] [ -n ] [ -r infile ]\n");
149 fprintf(stderr, "\t[ -R <filter expression> ] [ -s snaplen ] [ -t <time stamp format> ]\n");
150 fprintf(stderr, "\t[ -w savefile ] [ -x ]\n");
152 fprintf(stderr, "t%s [ -vVh ] [ -D ] [ -F <capture file type> ] [ -n ] [ -r infile ]\n", PACKAGE);
153 fprintf(stderr, "\t[ -R <filter expression> ] [ -t <time stamp format> ] [ -w savefile ]\n");
154 fprintf(stderr, "\t[ -x ]\n");
156 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
157 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
158 if (wtap_dump_can_open(i))
159 fprintf(stderr, "\t%s - %s\n",
160 wtap_file_type_short_string(i), wtap_file_type_string(i));
162 fprintf(stderr, "\tdefault is libpcap\n");
166 main(int argc, char *argv[])
170 gboolean arg_error = FALSE;
172 extern char pcap_version[];
177 int packet_count = 0;
179 gchar err_str[PCAP_ERRBUF_SIZE];
181 gboolean capture_option_specified = FALSE;
183 int out_file_type = WTAP_FILE_PCAP;
184 gchar *cf_name = NULL, *rfilter = NULL;
185 dfilter *rfcode = NULL;
188 /* If invoked with the "-G" flag, we dump out a glossary of
189 display filter symbols.
191 We do this here to mirror what happens in the GTK+ version, although
192 it's not necessary here. */
193 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
194 ethereal_proto_init();
195 proto_registrar_dump();
199 prefs = read_prefs(&pf_path);
200 if (pf_path != NULL) {
201 fprintf(stderr, "Can't open preferences file \"%s\": %s.\n", pf_path,
205 /* Initialize the capture file struct */
211 cf.user_saved = FALSE;
212 cf.is_tempfile = FALSE;
217 cf.cfilter = g_strdup("");
221 cf.save_file_fd = -1;
222 cf.snap = WTAP_MAX_PACKET_SIZE;
224 cf.cinfo.num_cols = prefs->num_cols;
225 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
226 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
227 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
228 cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
229 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
231 /* Assemble the compile-time options */
232 snprintf(comp_info_str, 256,
233 #ifdef GTK_MAJOR_VERSION
234 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
237 "GTK+ (version unknown), %s%s, %s%s, %s%s",
241 "with libpcap ", pcap_version,
243 "without libpcap", "",
248 "with libz ", ZLIB_VERSION,
249 #else /* ZLIB_VERSION */
250 "with libz ", "(version unknown)",
251 #endif /* ZLIB_VERSION */
252 #else /* HAVE_LIBZ */
254 #endif /* HAVE_LIBZ */
256 /* Oh, this is pretty */
257 #if defined(HAVE_UCD_SNMP_SNMP_H)
258 #ifdef HAVE_UCD_SNMP_VERSION_H
259 "with UCD SNMP ", VersionInfo
260 #else /* HAVE_UCD_SNMP_VERSION_H */
261 "with UCD SNMP ", "(version unknown)"
262 #endif /* HAVE_UCD_SNMP_VERSION_H */
263 #elif defined(HAVE_SNMP_SNMP_H)
264 #ifdef HAVE_SNMP_VERSION_H
265 "with CMU SNMP ", snmp_Version()
266 #else /* HAVE_SNMP_VERSION_H */
267 "with CMU SNMP ", "(version unknown)"
268 #endif /* HAVE_SNMP_VERSION_H */
274 /* Now get our args */
275 while ((opt = getopt(argc, argv, "c:Df:F:hi:nr:R:s:t:vw:Vx")) != EOF) {
277 case 'c': /* Capture xxx packets */
279 packet_count = atoi(optarg);
281 capture_option_specified = TRUE;
285 case 'D': /* Turn off DSCP printing */
286 g_ip_dscp_actif = FALSE;
290 cf.cfilter = g_strdup(optarg);
292 capture_option_specified = TRUE;
297 out_file_type = wtap_short_string_to_file_type(optarg);
298 if (out_file_type < 0) {
299 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
304 case 'h': /* Print help and exit */
308 case 'i': /* Use interface xxx */
310 cf.iface = g_strdup(optarg);
312 capture_option_specified = TRUE;
316 case 'n': /* No name resolution */
317 g_resolving_actif = 0;
319 case 'r': /* Read capture file xxx */
320 cf_name = g_strdup(optarg);
322 case 'R': /* Read file filter */
325 case 's': /* Set the snapshot (capture) length */
327 cf.snap = atoi(optarg);
329 capture_option_specified = TRUE;
333 case 't': /* Time stamp type */
334 if (strcmp(optarg, "r") == 0)
335 timestamp_type = RELATIVE;
336 else if (strcmp(optarg, "a") == 0)
337 timestamp_type = ABSOLUTE;
338 else if (strcmp(optarg, "d") == 0)
339 timestamp_type = DELTA;
341 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
343 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
344 fprintf(stderr, "or \"d\" for delta.\n");
348 case 'v': /* Show version and exit */
349 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
352 case 'w': /* Write to capture file xxx */
353 cf.save_file = g_strdup(optarg);
355 case 'V': /* Verbose */
358 case 'x': /* Print packet data in hex (and ASCII) */
365 if (capture_option_specified)
366 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
371 /* Build the column format array */
372 for (i = 0; i < cf.cinfo.num_cols; i++) {
373 cf.cinfo.col_fmt[i] = get_column_format(i);
374 cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
375 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
377 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
378 if (cf.cinfo.col_fmt[i] == COL_INFO)
379 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
381 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
385 cf.snap = WTAP_MAX_PACKET_SIZE;
386 else if (cf.snap < MIN_PACKET_SIZE)
387 cf.snap = MIN_PACKET_SIZE;
389 ethereal_proto_init(); /* Init anything that needs initializing */
391 if (rfilter != NULL) {
392 if (dfilter_compile(rfilter, &rfcode) != 0) {
393 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
394 ethereal_proto_cleanup();
400 err = open_cap_file(cf_name, FALSE, &cf);
402 ethereal_proto_cleanup();
405 err = load_cap_file(&cf, out_file_type);
407 ethereal_proto_cleanup();
412 /* No capture file specified, so we're supposed to do a live capture;
413 do we have support for live captures? */
415 /* Yes; did the user specify an interface to use? */
416 if (cf.iface == NULL) {
417 /* No - pick the first one from the list of interfaces. */
418 if_list = get_interface_list(&err, err_str);
419 if (if_list == NULL) {
422 case CANT_GET_INTERFACE_LIST:
423 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
427 case NO_INTERFACES_FOUND:
428 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
433 cf.iface = g_strdup(if_list->data); /* first interface */
434 free_interface_list(if_list);
436 capture(packet_count, out_file_type);
439 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
444 ethereal_proto_cleanup();
450 /* Do the low-level work of a capture.
451 Returns TRUE if it succeeds, FALSE otherwise. */
453 capture(int packet_count, int out_file_type)
455 gchar err_str[PCAP_ERRBUF_SIZE];
456 bpf_u_int32 netnum, netmask;
457 void (*oldhandler)(int);
461 /* Initialize the table of conversations. */
464 /* Initialize protocol-specific variables */
465 init_all_protocols();
467 ld.linktype = WTAP_ENCAP_UNKNOWN;
470 /* Open the network interface to capture from it. */
471 ld.pch = pcap_open_live(cf.iface, cf.snap, 1, 1000, err_str);
473 if (ld.pch == NULL) {
474 /* Well, we couldn't start the capture.
475 If this is a child process that does the capturing in sync
476 mode or fork mode, it shouldn't do any UI stuff until we pop up the
477 capture-progress window, and, since we couldn't start the
478 capture, we haven't popped it up. */
479 snprintf(errmsg, sizeof errmsg,
480 "The capture session could not be initiated (%s).\n"
481 "Please check to make sure you have sufficient permissions, and that\n"
482 "you have the proper interface specified.", err_str);
487 /* A capture filter was specified; set it up. */
488 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
489 snprintf(errmsg, sizeof errmsg,
490 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
493 if (pcap_compile(ld.pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
494 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
495 pcap_geterr(ld.pch));
498 if (pcap_setfilter(ld.pch, &cf.fcode) < 0) {
499 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
500 pcap_geterr(ld.pch));
505 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
506 if (cf.save_file != NULL) {
507 /* Set up to write to the capture file. */
508 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
509 strcpy(errmsg, "The network you're capturing from is of a type"
510 " that Tethereal doesn't support.");
513 ld.pdh = wtap_dump_open(cf.save_file, out_file_type,
514 ld.linktype, pcap_snapshot(ld.pch), &err);
516 if (ld.pdh == NULL) {
517 /* We couldn't set up to write to the capture file. */
520 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
521 strcpy(errmsg, "Tethereal does not support writing capture files in that format.");
524 case WTAP_ERR_UNSUPPORTED_ENCAP:
525 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
526 strcpy(errmsg, "Tethereal cannot save this capture in that format.");
529 case WTAP_ERR_CANT_OPEN:
530 strcpy(errmsg, "The file to which the capture would be written"
531 " couldn't be created for some unknown reason.");
534 case WTAP_ERR_SHORT_WRITE:
535 strcpy(errmsg, "A full header couldn't be written to the file"
536 " to which the capture would be written.");
541 sprintf(errmsg, "The file to which the capture would be"
542 " written (\"%s\") could not be opened: Error %d.",
545 sprintf(errmsg, "The file to which the capture would be"
546 " written (\"%s\") could not be opened: %s.",
547 cf.save_file, strerror(err));
555 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
557 XXX - deal with signal semantics on various platforms. Or just
558 use "sigaction()" and be done with it? */
559 signal(SIGTERM, capture_cleanup);
560 signal(SIGINT, capture_cleanup);
561 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
562 signal(SIGHUP, oldhandler);
564 /* Let the user know what interface was chosen. */
565 printf("Capturing on %s\n", cf.iface);
567 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
573 g_free(cf.save_file);
575 fprintf(stderr, "tethereal: %s\n", errmsg);
583 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
586 struct wtap_pkthdr whdr;
587 loop_data *ld = (loop_data *) user;
590 whdr.ts.tv_sec = phdr->ts.tv_sec;
591 whdr.ts.tv_usec = phdr->ts.tv_usec;
592 whdr.caplen = phdr->caplen;
593 whdr.len = phdr->len;
594 whdr.pkt_encap = ld->linktype;
599 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, pd);
601 printf("\r%u ", cf.count);
604 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, pd);
609 capture_cleanup(int signum)
616 wtap_dump_close(ld.pdh, &err);
617 /* XXX - complain if this fails */
620 #endif /* HAVE_LIBPCAP */
623 load_cap_file(capture_file *cf, int out_file_type)
631 linktype = wtap_file_encap(cf->wth);
632 if (cf->save_file != NULL) {
633 /* Set up to write to the capture file. */
634 pdh = wtap_dump_open(cf->save_file, out_file_type,
635 linktype, wtap_snapshot_length(cf->wth), &err);
638 /* We couldn't set up to write to the capture file. */
641 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
643 "tethereal: Capture files can't be written in that format.\n");
646 case WTAP_ERR_UNSUPPORTED_ENCAP:
647 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
649 "tethereal: The capture file being read cannot be written in that format.\n");
652 case WTAP_ERR_CANT_OPEN:
654 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
658 case WTAP_ERR_SHORT_WRITE:
660 "tethereal: A full header couldn't be written to the file \"%s\".\n",
667 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
671 "tethereal: The file \"%s\" could not be opened: %s\n.",
672 cf->save_file, strerror(err));
680 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
685 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
689 /* Print up a message box noting that the read failed somewhere along
693 case WTAP_ERR_UNSUPPORTED_ENCAP:
695 "tethereal: The capture file is for a network type that Tethereal doesn't support.\n");
698 case WTAP_ERR_CANT_READ:
700 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
703 case WTAP_ERR_SHORT_READ:
705 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
708 case WTAP_ERR_BAD_RECORD:
710 "tethereal: The capture file appears to be damaged or corrupt.\n");
715 "tethereal: An error occurred while reading the capture file: %s.\n",
729 fill_in_fdata(frame_data *fdata, capture_file *cf,
730 const struct wtap_pkthdr *phdr, int offset)
736 fdata->pkt_len = phdr->len;
737 fdata->cap_len = phdr->caplen;
738 fdata->file_off = offset;
739 fdata->lnk_t = phdr->pkt_encap;
740 fdata->abs_secs = phdr->ts.tv_sec;
741 fdata->abs_usecs = phdr->ts.tv_usec;
742 fdata->encoding = CHAR_ASCII;
743 fdata->pseudo_header = phdr->pseudo_header;
746 fdata->num = cf->count;
748 /* If we don't have the time stamp of the first packet in the
749 capture, it's because this is the first packet. Save the time
750 stamp of this packet as the time stamp of the first packet. */
751 if (!firstsec && !firstusec) {
752 firstsec = fdata->abs_secs;
753 firstusec = fdata->abs_usecs;
756 /* Get the time elapsed between the first packet and this packet. */
757 cf->esec = fdata->abs_secs - firstsec;
758 if (firstusec <= fdata->abs_usecs) {
759 cf->eusec = fdata->abs_usecs - firstusec;
761 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
765 /* If we don't have the time stamp of the previous displayed packet,
766 it's because this is the first displayed packet. Save the time
767 stamp of this packet as the time stamp of the previous displayed
769 if (!prevsec && !prevusec) {
770 prevsec = fdata->abs_secs;
771 prevusec = fdata->abs_usecs;
774 /* Get the time elapsed between the first packet and this packet. */
775 fdata->rel_secs = cf->esec;
776 fdata->rel_usecs = cf->eusec;
778 /* Get the time elapsed between the previous displayed packet and
780 fdata->del_secs = fdata->abs_secs - prevsec;
781 if (prevusec <= fdata->abs_usecs) {
782 fdata->del_usecs = fdata->abs_usecs - prevusec;
784 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
787 prevsec = fdata->abs_secs;
788 prevusec = fdata->abs_usecs;
790 fdata->cinfo = &cf->cinfo;
791 for (i = 0; i < fdata->cinfo->num_cols; i++) {
792 fdata->cinfo->col_data[i][0] = '\0';
797 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
800 cb_args_t *args = (cb_args_t *) user;
801 capture_file *cf = args->cf;
802 wtap_dumper *pdh = args->pdh;
804 proto_tree *protocol_tree;
810 fill_in_fdata(&fdata, cf, phdr, offset);
811 protocol_tree = proto_tree_create_root();
812 dissect_packet(buf, &fdata, protocol_tree);
813 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
815 protocol_tree = NULL;
819 /* XXX - do something if this fails */
820 wtap_dump(pdh, phdr, buf, &err);
822 if (protocol_tree != NULL)
823 proto_tree_free(protocol_tree);
827 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
830 cb_args_t *args = (cb_args_t *) user;
831 capture_file *cf = args->cf;
833 proto_tree *protocol_tree;
835 print_args_t print_args;
839 fill_in_fdata(&fdata, cf, phdr, offset);
842 if (cf->rfcode || verbose)
843 protocol_tree = proto_tree_create_root();
845 protocol_tree = NULL;
846 dissect_packet(buf, &fdata, protocol_tree);
848 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
850 /* The packet passed the read filter. */
852 /* Print the information in the protocol tree. */
853 print_args.to_file = TRUE;
854 print_args.format = PR_FMT_TEXT;
855 print_args.print_summary = FALSE;
856 print_args.print_hex = print_hex;
857 print_args.expand_all = TRUE;
858 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
859 buf, &fdata, stdout);
861 /* "print_hex_data()" will put out a leading blank line, as well
862 as a trailing one; print one here, to separate the packets,
863 only if "print_hex_data()" won't be called. */
867 /* Just fill in the columns. */
868 fill_in_columns(&fdata);
869 if (cf->iface == NULL) {
870 printf("%3s %10s %12s -> %-12s %s %s\n",
871 col_info(&fdata, COL_NUMBER),
872 col_info(&fdata, COL_CLS_TIME),
873 col_info(&fdata, COL_DEF_SRC),
874 col_info(&fdata, COL_DEF_DST),
875 col_info(&fdata, COL_PROTOCOL),
876 col_info(&fdata, COL_INFO));
878 printf("%12s -> %-12s %s %s\n",
879 col_info(&fdata, COL_DEF_SRC),
880 col_info(&fdata, COL_DEF_DST),
881 col_info(&fdata, COL_PROTOCOL),
882 col_info(&fdata, COL_INFO));
886 print_hex_data(stdout, print_args.format, buf,
887 fdata.cap_len, fdata.encoding);
892 if (protocol_tree != NULL)
893 proto_tree_free(protocol_tree);
897 file_open_error_message(int err, int for_writing)
900 static char errmsg_errno[1024+1];
904 case WTAP_ERR_NOT_REGULAR_FILE:
905 errmsg = "The file \"%s\" is invalid.";
908 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
909 case WTAP_ERR_UNSUPPORTED:
910 /* Seen only when opening a capture file for reading. */
911 errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
914 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
915 /* Seen only when opening a capture file for writing. */
916 errmsg = "Tethereal does not support writing capture files in that format.";
919 case WTAP_ERR_UNSUPPORTED_ENCAP:
920 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
922 errmsg = "Tethereal cannot save this capture in that format.";
924 errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
927 case WTAP_ERR_BAD_RECORD:
928 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
931 case WTAP_ERR_CANT_OPEN:
933 errmsg = "The file \"%s\" could not be created for some unknown reason.";
935 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
938 case WTAP_ERR_SHORT_READ:
939 errmsg = "The file \"%s\" appears to have been cut short"
940 " in the middle of a packet.";
943 case WTAP_ERR_SHORT_WRITE:
944 errmsg = "A full header couldn't be written to the file \"%s\".";
949 errmsg = "The path to the file \"%s\" does not exist.";
951 errmsg = "The file \"%s\" does not exist.";
956 errmsg = "You do not have permission to create or write to the file \"%s\".";
958 errmsg = "You do not have permission to read the file \"%s\".";
962 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
964 errmsg = errmsg_errno;
971 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
978 char err_msg[2048+1];
980 wth = wtap_open_offline(fname, &err);
984 /* Find the size of the file. */
987 if (fstat(fd, &cf_stat) < 0) {
993 /* The open succeeded. Fill in the information for this file. */
995 /* Initialize the table of conversations. */
998 /* Initialize protocol-specific variables */
999 init_all_protocols();
1004 cf->f_len = cf_stat.st_size;
1006 /* Set the file name because we need it to set the follow stream filter.
1007 XXX - is that still true? We need it for other reasons, though,
1009 cf->filename = g_strdup(fname);
1011 /* Indicate whether it's a permanent or temporary file. */
1012 cf->is_tempfile = is_tempfile;
1014 /* If it's a temporary capture buffer file, mark it as not saved. */
1015 cf->user_saved = !is_tempfile;
1017 cf->cd_t = wtap_file_type(cf->wth);
1022 cf->snap = wtap_snapshot_length(cf->wth);
1023 cf->update_progbar = FALSE;
1024 cf->progbar_quantum = 0;
1025 cf->progbar_nextstep = 0;
1026 firstsec = 0, firstusec = 0;
1027 prevsec = 0, prevusec = 0;
1032 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1033 fprintf(stderr, "tethereal: %s\n", err_msg);
1037 /* Get the text in a given column */
1039 col_info(frame_data *fd, gint el) {
1043 for (i = 0; i < fd->cinfo->num_cols; i++) {
1044 if (fd->cinfo->fmt_matx[i][el])
1045 return fd->cinfo->col_data[i];