/* tethereal.c
*
- * $Id: tethereal.c,v 1.83 2001/05/31 08:36:41 guy Exp $
+ * $Id: tethereal.c,v 1.97 2001/11/09 07:44:48 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
#include <pcap.h>
#endif
+#ifdef HAVE_LIBZ
+#include <zlib.h> /* to get the libz version number */
+#endif
+
#ifdef NEED_SNPRINTF_H
# include "snprintf.h"
#endif
#include "print.h"
#include "resolv.h"
#include "util.h"
+#ifdef HAVE_LIBPCAP
+#include "pcap-util.h"
+#endif
#include "conversation.h"
+#include "reassemble.h"
#include "plugins.h"
#include "register.h"
} cb_args_t;
static int load_cap_file(capture_file *, int);
-static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
+static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, long,
union wtap_pseudo_header *, const u_char *);
static void show_capture_file_io_error(const char *, int, gboolean);
-static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
+static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, long,
union wtap_pseudo_header *, const u_char *);
packet_info pi;
capture_file cfile;
FILE *data_out_file = NULL;
-guint main_ctx, file_ctx;
ts_type timestamp_type = RELATIVE;
#ifdef HAVE_LIBPCAP
static int promisc_mode = TRUE;
extern char *optarg;
gboolean arg_error = FALSE;
#ifdef HAVE_LIBPCAP
-#ifdef WIN32
- char pcap_version[] = WPCAP_STRING;
-#else
+#ifdef HAVE_PCAP_VERSION
extern char pcap_version[];
-#endif
-#endif
+#endif /* HAVE_PCAP_VERSION */
+#endif /* HAVE_LIBPCAP */
#ifdef WIN32
WSADATA wsaData;
#endif
- char *gpf_path, *pf_path;
+ char *gpf_path;
+ const char *pf_path;
int gpf_open_errno, pf_open_errno;
int err;
#ifdef HAVE_LIBPCAP
#ifdef HAVE_LIBPCAP
g_string_append(comp_info_str, ", with libpcap ");
+#ifdef HAVE_PCAP_VERSION
g_string_append(comp_info_str, pcap_version);
-#else
+#else /* HAVE_PCAP_VERSION */
+ g_string_append(comp_info_str, "(version unknown)");
+#endif /* HAVE_PCAP_VERSION */
+#else /* HAVE_LIBPCAP */
g_string_append(comp_info_str, ", without libpcap");
-#endif
+#endif /* HAVE_LIBPCAP */
#ifdef HAVE_LIBZ
g_string_append(comp_info_str, ", with libz ");
break;
case PREFS_SET_NO_SUCH_PREF:
+ case PREFS_SET_OBSOLETE:
fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
optarg);
exit(1);
static int
capture(int packet_count, int out_file_type)
{
- gchar err_str[PCAP_ERRBUF_SIZE];
+ gchar open_err_str[PCAP_ERRBUF_SIZE];
+ gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
bpf_u_int32 netnum, netmask;
struct bpf_program fcode;
void (*oldhandler)(int);
/* Initialize protocol-specific variables */
init_all_protocols();
+ /* Initialize the common data structures for fragment reassembly.
+ Must be done *after* "init_all_protocols()", as "init_all_protocols()"
+ may free up space for fragments, which it finds by using the
+ data structures that "reassemble_init()" frees. */
+ reassemble_init();
+
ld.linktype = WTAP_ENCAP_UNKNOWN;
ld.pdh = NULL;
- /* Open the network interface to capture from it. */
- ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
+ /* Open the network interface to capture from it.
+ Some versions of libpcap may put warnings into the error buffer
+ if they succeed; to tell if that's happened, we have to clear
+ the error buffer, and check if it's still a null string. */
+ open_err_str[0] = '\0';
+ ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000,
+ open_err_str);
if (ld.pch == NULL) {
/* Well, we couldn't start the capture. */
"Note that the driver Tethereal uses for packet capture on Windows\n"
"doesn't support capturing on Token Ring interfaces, and doesn't\n"
"support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
- err_str);
+ open_err_str);
#else
/* If we got a "can't find PPA for XXX" message, warn the user (who
is running Ethereal on HP-UX) that they don't have a version
of libpcap that properly handles HP-UX (libpcap 0.6.x and later
versions, which properly handle HP-UX, say "can't find /dev/dlpi
PPA for XXX" rather than "can't find PPA for XXX"). */
- if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
+ if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
libpcap_warn =
"\n\n"
"You are running Tethereal with a version of the libpcap library\n"
snprintf(errmsg, sizeof errmsg,
"The capture session could not be initiated (%s).\n"
"Please check to make sure you have sufficient permissions, and that\n"
- "you have the proper interface specified.%s", err_str, libpcap_warn);
+ "you have the proper interface specified.%s", open_err_str, libpcap_warn);
#endif
goto error;
}
if (cfile.cfilter) {
/* A capture filter was specified; set it up. */
- if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
+ if (pcap_lookupnet(cfile.iface, &netnum, &netmask, lookup_net_err_str) < 0) {
/*
* Well, we can't get the netmask for this interface; it's used
* only for filters that check for broadcast IP addresses, so
* we just warn the user, and punt and use 0.
*/
fprintf(stderr,
- "Warning: Couldn't obtain netmask info (%s)\n.", err_str);
+ "Warning: Couldn't obtain netmask info (%s)\n.", lookup_net_err_str);
netmask = 0;
}
if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
}
}
- ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
+ ld.linktype = wtap_pcap_encap_to_wtap_encap(get_pcap_linktype(ld.pch,
+ cfile.iface));
if (cfile.save_file != NULL) {
/* Set up to write to the capture file. */
if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
}
}
+ /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
+ returned a warning; print it, but keep capturing. */
+ if (open_err_str[0] != '\0')
+ fprintf(stderr, "tethereal: WARNING: %s.\n", open_err_str);
+
/* Catch SIGINT and SIGTERM and, if we get either of them, clean up
and exit.
XXX - deal with signal semantics on various platforms. Or just
}
pcap_close(ld.pch);
+ if (cfile.save_file != NULL) {
+ /* We're saving to a file; close the file. */
+ if (!wtap_dump_close(ld.pdh, &err))
+ show_capture_file_io_error(cfile.save_file, err, TRUE);
+ }
+
return TRUE;
error:
args.pdh = pdh;
success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
&err);
+
+ /* Now close the capture file. */
+ if (!wtap_dump_close(pdh, &err))
+ show_capture_file_io_error(cfile.save_file, err, TRUE);
} else {
args.cf = cf;
args.pdh = NULL;
static void
fill_in_fdata(frame_data *fdata, capture_file *cf,
const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header, int offset)
+ const union wtap_pseudo_header *pseudo_header, long offset)
{
int i;
/* If it's greater than the current elapsed time, set the elapsed time
to it (we check for "greater than" so as not to be confused by
time moving backwards). */
- if (cf->esec < fdata->rel_secs
- || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
+ if ((gint32)cf->esec < fdata->rel_secs
+ || ((gint32)cf->esec == fdata->rel_secs && (gint32)cf->eusec < fdata->rel_usecs)) {
cf->esec = fdata->rel_secs;
cf->eusec = fdata->rel_usecs;
}
}
static void
-wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
- union wtap_pseudo_header *pseudo_header, const u_char *buf)
+wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr,
+ long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
{
cb_args_t *args = (cb_args_t *) user;
capture_file *cf = args->cf;
}
static void
-wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
- union wtap_pseudo_header *pseudo_header, const u_char *buf)
+wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr,
+ long offset, union wtap_pseudo_header *pseudo_header, const u_char *buf)
{
cb_args_t *args = (cb_args_t *) user;
capture_file *cf = args->cf;
print_args.print_summary = FALSE;
print_args.print_hex = print_hex;
print_args.expand_all = TRUE;
+ print_args.suppress_unmarked = FALSE;
proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
- buf, &fdata, stdout);
+ &fdata, stdout);
if (!print_hex) {
/* "print_hex_data()" will put out a leading blank line, as well
as a trailing one; print one here, to separate the packets,
{
wtap *wth;
int err;
- FILE_T fh;
int fd;
struct stat cf_stat;
char err_msg[2048+1];
goto fail;
/* Find the size of the file. */
- fh = wtap_file(wth);
fd = wtap_fd(wth);
if (fstat(fd, &cf_stat) < 0) {
err = errno;
/* Initialize protocol-specific variables */
init_all_protocols();
+ /* Initialize the common data structures for fragment reassembly.
+ Must be done *after* "init_all_protocols()", as "init_all_protocols()"
+ may free up space for fragments, which it finds by using the
+ data structures that "reassemble_init()" frees. */
+ reassemble_init();
+
cf->wth = wth;
cf->filed = fd;
cf->f_len = cf_stat.st_size;