3 * $Id: tethereal.c,v 1.16 2000/01/26 05:30:02 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 Ethereal 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 Ethereal 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;
591 whdr.caplen = phdr->caplen;
592 whdr.len = phdr->len;
593 whdr.pkt_encap = ld->linktype;
598 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, pd);
600 printf("\r%u ", cf.count);
603 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, pd);
608 capture_cleanup(int signum)
615 wtap_dump_close(ld.pdh, &err);
616 /* XXX - complain if this fails */
619 #endif /* HAVE_LIBPCAP */
622 load_cap_file(capture_file *cf, int out_file_type)
630 linktype = wtap_file_encap(cf->wth);
631 if (cf->save_file != NULL) {
632 /* Set up to write to the capture file. */
633 pdh = wtap_dump_open(cf->save_file, out_file_type,
634 linktype, wtap_snapshot_length(cf->wth), &err);
637 /* We couldn't set up to write to the capture file. */
640 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
642 "tethereal: Capture files can't be written in that format.\n");
645 case WTAP_ERR_UNSUPPORTED_ENCAP:
646 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
648 "tethereal: The capture file being read cannot be written in that format.\n");
651 case WTAP_ERR_CANT_OPEN:
653 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
657 case WTAP_ERR_SHORT_WRITE:
659 "tethereal: A full header couldn't be written to the file \"%s\".\n",
666 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
670 "tethereal: The file \"%s\" could not be opened: %s\n.",
671 cf->save_file, strerror(err));
679 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
684 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
688 /* Print up a message box noting that the read failed somewhere along
692 case WTAP_ERR_CANT_READ:
694 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
697 case WTAP_ERR_SHORT_READ:
699 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
702 case WTAP_ERR_BAD_RECORD:
704 "tethereal: The capture file appears to be damaged or corrupt.\n");
709 "tethereal: An error occurred while reading the capture file: %s.\n",
723 fill_in_fdata(frame_data *fdata, capture_file *cf,
724 const struct wtap_pkthdr *phdr, int offset)
730 fdata->pkt_len = phdr->len;
731 fdata->cap_len = phdr->caplen;
732 fdata->file_off = offset;
733 fdata->lnk_t = phdr->pkt_encap;
734 fdata->abs_secs = phdr->ts.tv_sec;
735 fdata->abs_usecs = phdr->ts.tv_usec;
736 fdata->encoding = CHAR_ASCII;
737 fdata->pseudo_header = phdr->pseudo_header;
740 fdata->num = cf->count;
742 /* If we don't have the time stamp of the first packet in the
743 capture, it's because this is the first packet. Save the time
744 stamp of this packet as the time stamp of the first packet. */
745 if (!firstsec && !firstusec) {
746 firstsec = fdata->abs_secs;
747 firstusec = fdata->abs_usecs;
750 /* Get the time elapsed between the first packet and this packet. */
751 cf->esec = fdata->abs_secs - firstsec;
752 if (firstusec <= fdata->abs_usecs) {
753 cf->eusec = fdata->abs_usecs - firstusec;
755 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
759 /* If we don't have the time stamp of the previous displayed packet,
760 it's because this is the first displayed packet. Save the time
761 stamp of this packet as the time stamp of the previous displayed
763 if (!prevsec && !prevusec) {
764 prevsec = fdata->abs_secs;
765 prevusec = fdata->abs_usecs;
768 /* Get the time elapsed between the first packet and this packet. */
769 fdata->rel_secs = cf->esec;
770 fdata->rel_usecs = cf->eusec;
772 /* Get the time elapsed between the previous displayed packet and
774 fdata->del_secs = fdata->abs_secs - prevsec;
775 if (prevusec <= fdata->abs_usecs) {
776 fdata->del_usecs = fdata->abs_usecs - prevusec;
778 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
781 prevsec = fdata->abs_secs;
782 prevusec = fdata->abs_usecs;
784 fdata->cinfo = &cf->cinfo;
785 for (i = 0; i < fdata->cinfo->num_cols; i++) {
786 fdata->cinfo->col_data[i][0] = '\0';
791 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
794 cb_args_t *args = (cb_args_t *) user;
795 capture_file *cf = args->cf;
796 wtap_dumper *pdh = args->pdh;
798 proto_tree *protocol_tree;
804 fill_in_fdata(&fdata, cf, phdr, offset);
805 protocol_tree = proto_tree_create_root();
806 dissect_packet(buf, &fdata, protocol_tree);
807 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
809 protocol_tree = NULL;
813 /* XXX - do something if this fails */
814 wtap_dump(pdh, phdr, buf, &err);
816 if (protocol_tree != NULL)
817 proto_tree_free(protocol_tree);
821 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
824 cb_args_t *args = (cb_args_t *) user;
825 capture_file *cf = args->cf;
827 proto_tree *protocol_tree;
829 print_args_t print_args;
833 fill_in_fdata(&fdata, cf, phdr, offset);
836 if (cf->rfcode || verbose)
837 protocol_tree = proto_tree_create_root();
839 protocol_tree = NULL;
840 dissect_packet(buf, &fdata, protocol_tree);
842 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
844 /* The packet passed the read filter. */
846 /* Print the information in the protocol tree. */
847 print_args.to_file = TRUE;
848 print_args.format = PR_FMT_TEXT;
849 print_args.print_summary = FALSE;
850 print_args.print_hex = print_hex;
851 print_args.expand_all = TRUE;
852 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
853 buf, &fdata, stdout);
855 /* "print_hex_data()" will put out a leading blank line, as well
856 as a trailing one; print one here, to separate the packets,
857 only if "print_hex_data()" won't be called. */
861 /* Just fill in the columns. */
862 fill_in_columns(&fdata);
863 if (cf->iface == NULL) {
864 printf("%3s %10s %12s -> %-12s %s %s\n",
865 col_info(&fdata, COL_NUMBER),
866 col_info(&fdata, COL_CLS_TIME),
867 col_info(&fdata, COL_DEF_SRC),
868 col_info(&fdata, COL_DEF_DST),
869 col_info(&fdata, COL_PROTOCOL),
870 col_info(&fdata, COL_INFO));
872 printf("%12s -> %-12s %s %s\n",
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));
880 print_hex_data(stdout, print_args.format, buf,
881 fdata.cap_len, fdata.encoding);
886 if (protocol_tree != NULL)
887 proto_tree_free(protocol_tree);
891 file_open_error_message(int err, int for_writing)
894 static char errmsg_errno[1024+1];
898 case WTAP_ERR_NOT_REGULAR_FILE:
899 errmsg = "The file \"%s\" is invalid.";
902 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
903 case WTAP_ERR_UNSUPPORTED:
904 /* Seen only when opening a capture file for reading. */
905 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
908 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
909 /* Seen only when opening a capture file for writing. */
910 errmsg = "Ethereal does not support writing capture files in that format.";
913 case WTAP_ERR_UNSUPPORTED_ENCAP:
914 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
915 /* Seen only when opening a capture file for writing. */
916 errmsg = "Ethereal cannot save this capture in that format.";
919 case WTAP_ERR_BAD_RECORD:
920 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
923 case WTAP_ERR_CANT_OPEN:
925 errmsg = "The file \"%s\" could not be created for some unknown reason.";
927 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
930 case WTAP_ERR_SHORT_READ:
931 errmsg = "The file \"%s\" appears to have been cut short"
932 " in the middle of a packet.";
935 case WTAP_ERR_SHORT_WRITE:
936 errmsg = "A full header couldn't be written to the file \"%s\".";
941 errmsg = "The path to the file \"%s\" does not exist.";
943 errmsg = "The file \"%s\" does not exist.";
948 errmsg = "You do not have permission to create or write to the file \"%s\".";
950 errmsg = "You do not have permission to read the file \"%s\".";
954 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
956 errmsg = errmsg_errno;
963 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
970 char err_msg[2048+1];
972 wth = wtap_open_offline(fname, &err);
976 /* Find the size of the file. */
979 if (fstat(fd, &cf_stat) < 0) {
985 /* The open succeeded. Fill in the information for this file. */
987 /* Initialize the table of conversations. */
990 /* Initialize protocol-specific variables */
991 init_all_protocols();
996 cf->f_len = cf_stat.st_size;
998 /* Set the file name because we need it to set the follow stream filter.
999 XXX - is that still true? We need it for other reasons, though,
1001 cf->filename = g_strdup(fname);
1003 /* Indicate whether it's a permanent or temporary file. */
1004 cf->is_tempfile = is_tempfile;
1006 /* If it's a temporary capture buffer file, mark it as not saved. */
1007 cf->user_saved = !is_tempfile;
1009 cf->cd_t = wtap_file_type(cf->wth);
1014 cf->snap = wtap_snapshot_length(cf->wth);
1015 cf->update_progbar = FALSE;
1016 cf->progbar_quantum = 0;
1017 cf->progbar_nextstep = 0;
1018 firstsec = 0, firstusec = 0;
1019 prevsec = 0, prevusec = 0;
1024 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1025 fprintf(stderr, "tethereal: %s\n", err_msg);
1029 /* Get the text in a given column */
1031 col_info(frame_data *fd, gint el) {
1035 for (i = 0; i < fd->cinfo->num_cols; i++) {
1036 if (fd->cinfo->fmt_matx[i][el])
1037 return fd->cinfo->col_data[i];