summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--caputils/capture-pcap-util-unix.c64
-rw-r--r--caputils/capture-pcap-util.h8
-rw-r--r--dumpcap.c15
3 files changed, 68 insertions, 19 deletions
diff --git a/caputils/capture-pcap-util-unix.c b/caputils/capture-pcap-util-unix.c
index 8aae100c33..33047317d5 100644
--- a/caputils/capture-pcap-util-unix.c
+++ b/caputils/capture-pcap-util-unix.c
@@ -26,11 +26,13 @@
#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_FINDALLDEVS
-
#include <pcap.h>
-#else /* HAVE_PCAP_FINDALLDEVS */
+#ifdef __APPLE__
+#include <dlfcn.h>
+#endif
+
+#ifndef HAVE_PCAP_FINDALLDEVS
#include <stdlib.h>
#include <string.h>
@@ -60,8 +62,6 @@ struct rtentry;
# include <sys/sockio.h>
#endif
-#include "caputils/capture-pcap-util.h"
-
#endif /* HAVE_PCAP_FINDALLDEVS */
#ifdef HAVE_LIBCAP
@@ -334,6 +334,60 @@ cant_get_if_list_error_message(const char *err_str)
return g_strdup_printf("Can't get list of interfaces: %s", err_str);
}
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+/*
+ * Request high-resolution time stamps.
+ *
+ * We don't check for errors - if this fails, we just live with boring old
+ * microsecond-resolution time stamps. The only errors pcap_set_tstamp_precision()
+ * is documenting as returning are PCAP_ERROR_TSTAMP_PRECISION_NOTSUP, which just
+ * means we can't do nanosecond precision on this adapter, in which case we
+ * just live with whatever resolution we get by default, and
+ * PCAP_ERROR_ACTIVATED, which shouldn't happen as we shouldn't call this
+ * after we've activated the pcap_t.
+ */
+void
+request_high_resolution_timestamp(pcap_t *pcap_h)
+{
+#ifdef __APPLE__
+ /*
+ * On OS X, if you build with a newer SDK, pcap_set_tstamp_precision()
+ * is available, so the code will be built with it.
+ *
+ * However, if you then try to run on an older release that
+ * doesn't have pcap_set_tstamp_precision(), the dynamic linker
+ * will fail, as it won't find pcap_set_tstamp_precision().
+ *
+ * libpcap doesn't use OS X "weak linking" for new routines,
+ * so we can't just check whether a pointer to
+ * pcap_set_tstamp_precision() is null and, if it is, not
+ * call it. We have to, instead, use dlopen() to load
+ * libpcap, and dlsym() to find a pointer to pcap_set_tstamp_precision(),
+ * and if we find the pointer, call it.
+ */
+ static gboolean initialized = FALSE;
+ static void *libpcap_handle;
+ static int (*p_pcap_set_tstamp_precision)(pcap_t *, int);
+
+ if (!initialized) {
+ p_pcap_set_tstamp_precision =
+ (int (*)(pcap_t *, int))
+ dlsym(RTLD_NEXT, "pcap_set_tstamp_precision");
+ initialized = TRUE;
+ }
+ if (p_pcap_set_tstamp_precision != NULL)
+ (*p_pcap_set_tstamp_precision)(pcap_h, PCAP_TSTAMP_PRECISION_NANO);
+#else /* __APPLE__ */
+ /*
+ * On other UN*Xes we require that we be run on an OS version
+ * with a libpcap equal to or later than the version with which
+ * we were built.
+ */
+ pcap_set_tstamp_precision(pcap_h, PCAP_TSTAMP_PRECISION_NANO);
+#endif /* __APPLE__ */
+}
+#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
+
/*
* Get the versions of libpcap, libpcap, and libnl with which we were
* compiled, and append them to a GString.
diff --git a/caputils/capture-pcap-util.h b/caputils/capture-pcap-util.h
index 617bcc82e5..079e3fabd7 100644
--- a/caputils/capture-pcap-util.h
+++ b/caputils/capture-pcap-util.h
@@ -50,12 +50,16 @@ GList *get_remote_interface_list(const char *hostname, const char *port,
const char *linktype_val_to_name(int dlt);
int linktype_name_to_val(const char *linktype);
-#endif /* HAVE_LIBPCAP */
-
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
/*
* Get the versions of capture libraries with which we were compiled,
* and append them to a GString.
*/
+void request_high_resolution_timestamp(pcap_t *pcap_h);
+#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
+
+#endif /* HAVE_LIBPCAP */
+
extern void get_compiled_caplibs_version(GString *str);
/*
diff --git a/dumpcap.c b/dumpcap.c
index b64aec5ec4..9c2bff364b 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -730,18 +730,9 @@ open_capture_device(capture_options *capture_opts
* that reads pcap files recognizes the nanosecond-
* resolution pcap file magic number.
*/
- if (capture_opts->use_pcapng) {
- /*
- * The only errors this is documenting as returning
- * are PCAP_ERROR_TSTAMP_PRECISION_NOTSUP, which just
- * means we can't do nanosecond precision on this adapter,
- * in which case we just live with whatever resolution
- * we get by default, and PCAP_ERROR_ACTIVATED, which
- * can't happen as we haven't activated the pcap_t yet.
- */
- pcap_set_tstamp_precision(pcap_h, PCAP_TSTAMP_PRECISION_NANO);
- }
-#endif
+ if (capture_opts->use_pcapng)
+ request_high_resolution_timestamp(pcap_h);
+#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"buffersize %d.", interface_opts->buffer_size);