Add support for remote capture if libpcap supports it.
diff --git a/config.h.in b/config.h.in
index 9915b23..8464d5d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -130,6 +130,9 @@
/* Define to 1 if you have the `pcap_findalldevs' function. */
#undef HAVE_PCAP_FINDALLDEVS
+/* Define to 1 if you have the `pcap_findalldevs_ex' function. */
+#undef HAVE_PCAP_FINDALLDEVS_EX
+
/* Define to 1 if you have the `pcap_free_datalinks' function. */
#undef HAVE_PCAP_FREE_DATALINKS
@@ -145,6 +148,9 @@
/* Define to 1 if you have the <pcap/nflog.h> header file. */
#undef HAVE_PCAP_NFLOG_H
+/* Define to 1 if you have the `pcap_open' function. */
+#undef HAVE_PCAP_OPEN
+
/* Define to 1 if you have the <pcap/pcap-inttypes.h> header file. */
#undef HAVE_PCAP_PCAP_INTTYPES_H
diff --git a/configure b/configure
index a6424e2..215445d 100755
--- a/configure
+++ b/configure
@@ -5969,25 +5969,12 @@
# Check for a miscellaneous collection of functions which we use
# if we have them.
#
-for ac_func in pcap_findalldevs pcap_dump_flush pcap_lib_version
+for ac_func in pcap_findalldevs
do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ ac_fn_c_check_func "$LINENO" "pcap_findalldevs" "ac_cv_func_pcap_findalldevs"
+if test "x$ac_cv_func_pcap_findalldevs" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in pcap_setdirection pcap_set_immediate_mode pcap_dump_ftell64
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_PCAP_FINDALLDEVS 1
_ACEOF
fi
@@ -6009,6 +5996,17 @@
CPPFLAGS="$savedcppflags"
fi
+for ac_func in pcap_dump_flush pcap_lib_version
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
if test $ac_cv_func_pcap_lib_version = "no" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pcap_version is defined by libpcap" >&5
@@ -6046,6 +6044,30 @@
$as_echo "no" >&6; }
fi
fi
+for ac_func in pcap_setdirection pcap_set_immediate_mode pcap_dump_ftell64
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+for ac_func in pcap_open pcap_findalldevs_ex
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
#
# Check for special debugging functions
diff --git a/configure.in b/configure.in
index 76becf7..7f4169d 100644
--- a/configure.in
+++ b/configure.in
@@ -615,8 +615,7 @@
# Check for a miscellaneous collection of functions which we use
# if we have them.
#
-AC_CHECK_FUNCS(pcap_findalldevs pcap_dump_flush pcap_lib_version)
-AC_CHECK_FUNCS(pcap_setdirection pcap_set_immediate_mode pcap_dump_ftell64)
+AC_CHECK_FUNCS(pcap_findalldevs)
if test $ac_cv_func_pcap_findalldevs = "yes" ; then
dnl Check for Mac OS X, which may ship pcap.h from 0.6 but libpcap may
dnl be 0.8; this means that lib has pcap_findalldevs but header doesn't
@@ -626,7 +625,7 @@
AC_CHECK_TYPES(pcap_if_t, , , [#include <pcap.h>])
CPPFLAGS="$savedcppflags"
fi
-
+AC_CHECK_FUNCS(pcap_dump_flush pcap_lib_version)
if test $ac_cv_func_pcap_lib_version = "no" ; then
AC_MSG_CHECKING(whether pcap_version is defined by libpcap)
AC_TRY_LINK([],
@@ -644,6 +643,8 @@
AC_MSG_RESULT(no)
fi
fi
+AC_CHECK_FUNCS(pcap_setdirection pcap_set_immediate_mode pcap_dump_ftell64)
+AC_CHECK_FUNCS(pcap_open pcap_findalldevs_ex)
#
# Check for special debugging functions
diff --git a/tcpdump.c b/tcpdump.c
index ecd41fc..695cedb 100644
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -87,6 +87,9 @@
#include <sys/nv.h>
#endif /* HAVE_CASPER */
#endif /* HAVE_CAPSICUM */
+#ifdef HAVE_PCAP_OPEN
+#define HAVE_REMOTE
+#endif
#include <pcap.h>
#include <signal.h>
#include <stdio.h>
@@ -145,7 +148,13 @@
static long Cflag; /* rotate dump files after this many bytes */
#endif
static int Cflag_count; /* Keep track of which file number we're writing */
+#ifdef HAVE_PCAP_FINDALLDEVS
static int Dflag; /* list available devices and exit */
+#endif
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+static char *remote_interfaces_source; /* list available devices from this source and exit */
+#endif
+
/*
* This is exported because, in some versions of libpcap, if libpcap
* is built with optimizer debugging code (which is *NOT* the default
@@ -201,6 +210,9 @@
#ifdef HAVE_PCAP_FINDALLDEVS
static NORETURN void show_devices_and_exit(void);
#endif
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+static NORETURN void show_remote_devices_and_exit(void);
+#endif
static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *);
@@ -436,7 +448,7 @@
#ifdef HAVE_PCAP_FINDALLDEVS
static void
-show_devices_and_exit (void)
+show_devices_and_exit(void)
{
pcap_if_t *dev, *devlist;
char ebuf[PCAP_ERRBUF_SIZE];
@@ -457,6 +469,30 @@
}
#endif /* HAVE_PCAP_FINDALLDEVS */
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+static void
+show_remote_devices_and_exit(void)
+{
+ pcap_if_t *dev, *devlist;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int i;
+
+ if (pcap_findalldevs_ex(remote_interfaces_source, NULL, &devlist,
+ ebuf) < 0)
+ error("%s", ebuf);
+ for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) {
+ printf("%d.%s", i+1, dev->name);
+ if (dev->description != NULL)
+ printf(" (%s)", dev->description);
+ if (dev->flags != 0)
+ printf(" [%s]", bittok2str(status_flags, "none", dev->flags));
+ printf("\n");
+ }
+ pcap_freealldevs(devlist);
+ exit_tcpdump(0);
+}
+#endif /* HAVE_PCAP_FINDALLDEVS */
+
/*
* Short options.
*
@@ -499,6 +535,12 @@
#define B_FLAG_USAGE
#endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
+#ifdef HAVE_PCAP_FINDALLDEVS
+#define D_FLAG "D"
+#else
+#define D_FLAG
+#endif
+
#ifdef HAVE_PCAP_CREATE
#define I_FLAG "I"
#else /* HAVE_PCAP_CREATE */
@@ -515,10 +557,12 @@
#define J_FLAG
#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
-#ifdef HAVE_PCAP_FINDALLDEVS
-#define D_FLAG "D"
+#ifdef HAVE_PCAP_SETDIRECTION
+#define Q_FLAG "Q:"
+#define Q_FLAG_USAGE " [ -Q in|out|inout ]"
#else
-#define D_FLAG
+#define Q_FLAG
+#define Q_FLAG_USAGE
#endif
#ifdef HAVE_PCAP_DUMP_FLUSH
@@ -527,12 +571,6 @@
#define U_FLAG
#endif
-#ifdef HAVE_PCAP_SETDIRECTION
-#define Q_FLAG "Q:"
-#else
-#define Q_FLAG
-#endif
-
#define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#"
/*
@@ -555,16 +593,20 @@
* component of the entry for the long option, and have a case for that
* option in the switch statement.
*/
-#define OPTION_VERSION 128
-#define OPTION_TSTAMP_PRECISION 129
-#define OPTION_IMMEDIATE_MODE 130
-#define OPTION_PRINT 131
+#define OPTION_VERSION 128
+#define OPTION_TSTAMP_PRECISION 129
+#define OPTION_IMMEDIATE_MODE 130
+#define OPTION_PRINT 131
+#define OPTION_LIST_REMOTE_INTERFACES 132
static const struct option longopts[] = {
#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
{ "buffer-size", required_argument, NULL, 'B' },
#endif
{ "list-interfaces", no_argument, NULL, 'D' },
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ { "list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES },
+#endif
{ "help", no_argument, NULL, 'h' },
{ "interface", required_argument, NULL, 'i' },
#ifdef HAVE_PCAP_CREATE
@@ -603,6 +645,24 @@
{ NULL, 0, NULL, 0 }
};
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+#define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]"
+#else
+#define LIST_REMOTE_INTERFACES_USAGE
+#endif
+
+#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
+#define IMMEDIATE_MODE_USAGE " [ --immediate-mode ]"
+#else
+#define IMMEDIATE_MODE_USAGE ""
+#endif
+
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+#define TIME_STAMP_PRECISION_USAGE " [ --time-stamp-precision precision ]"
+#else
+#define TIME_STAMP_PRECISION_USAGE
+#endif
+
#ifndef _WIN32
/* Drop root privileges and chroot if necessary */
static void
@@ -992,6 +1052,13 @@
}
#endif
+#ifdef HAVE_PCAP_OPEN
+/*
+ * Prefix for rpcap URLs.
+ */
+static char rpcap_prefix[] = "rpcap://";
+#endif
+
static pcap_t *
open_interface(const char *device, netdissect_options *ndo, char *ebuf)
{
@@ -1001,6 +1068,36 @@
char *cp;
#endif
+#ifdef HAVE_PCAP_OPEN
+ /*
+ * Is this an rpcap URL?
+ */
+ if (strncmp(device, rpcap_prefix, sizeof(rpcap_prefix) - 1) == 0) {
+ /*
+ * Yes. Open it with pcap_open().
+ */
+ *ebuf = '\0';
+fprintf(stderr, "Opening %s\n", device);
+ pc = pcap_open(device, ndo->ndo_snaplen,
+ pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL,
+ ebuf);
+ if (pc == NULL) {
+ /*
+ * If this failed with "No such device", that means
+ * the interface doesn't exist; return NULL, so that
+ * the caller can see whether the device name is
+ * actually an interface index.
+ */
+ if (strstr(ebuf, "No such device") != NULL)
+ return (NULL);
+ error("%s", ebuf);
+ }
+ if (*ebuf)
+ warning("%s", ebuf);
+ return (pc);
+ }
+#endif /* HAVE_PCAP_OPEN */
+
#ifdef HAVE_PCAP_CREATE
pc = pcap_create(device, ebuf);
if (pc == NULL) {
@@ -1312,9 +1409,17 @@
++dflag;
break;
+#ifdef HAVE_PCAP_FINDALLDEVS
case 'D':
Dflag++;
break;
+#endif
+
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ case OPTION_LIST_REMOTE_INTERFACES:
+ remote_interfaces_source = optarg;
+ break;
+#endif
case 'L':
Lflag++;
@@ -1621,6 +1726,10 @@
if (Dflag)
show_devices_and_exit();
#endif
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
+ if (remote_interfaces_source != NULL)
+ show_remote_devices_and_exit();
+#endif
switch (ndo->ndo_tflag) {
@@ -2793,29 +2902,21 @@
(void)fprintf(stderr,
"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
(void)fprintf(stderr,
-"\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ] [ --number ]\n");
+"\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n");
+#ifdef HAVE_PCAP_FINDALLDEVS_EX
(void)fprintf(stderr,
-"\t\t[ --print ]");
-#ifdef HAVE_PCAP_SETDIRECTION
- (void)fprintf(stderr,
-" [ -Q in|out|inout ]");
+"\t\t" LIST_REMOTE_INTERFACES_USAGE "\n");
#endif
(void)fprintf(stderr,
-" [ -r file ] [ -s snaplen ]\n");
-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+"\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n");
(void)fprintf(stderr,
-"\t\t[ --time-stamp-precision precision ]\n");
+"\t\t[ -r file ] [ -s snaplen ]" TIME_STAMP_PRECISION_USAGE "\n");
(void)fprintf(stderr,
-"\t\t");
-#endif
-#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
- (void)fprintf(stderr, "[ --immediate-mode ] ");
-#endif
- (void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n");
+"\t\t[ -T type ] [ --version ] [ -V file ] [ -w file ]\n");
(void)fprintf(stderr,
-"\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ]\n");
+"\t\t[ -W filecount ] [ -y datalinktype ]\n");
(void)fprintf(stderr,
-"\t\t[ -Z user ] [ expression ]\n");
+"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
}
/*
* Local Variables: