summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Habets <thomas@habets.pp.se>2010-04-02 13:42:47 +0200
committerThomas Habets <thomas@habets.pp.se>2010-04-02 13:42:47 +0200
commit34ace21f5d654f2eb6dc45ab06b4efe00655bfb5 (patch)
tree2a5d25625fe6c9503a7025ff48ab97f73970ff51
parentdf36995363d6b92d635d353a55ba4b51ce004b5a (diff)
downloadarping-34ace21f5d654f2eb6dc45ab06b4efe00655bfb5.tar.gz
changed ping_recv_unix to use clock_gettime() instead of gettimeofday()
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure71
-rw-r--r--configure.ac1
-rw-r--r--src/arping.c66
4 files changed, 127 insertions, 14 deletions
diff --git a/config.h.in b/config.h.in
index c15430b..d78f33f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -21,6 +21,9 @@
/* Define to 1 if you have the `pcap' library (-lpcap). */
#undef HAVE_LIBPCAP
+/* Define to 1 if you have the `rt' library (-lrt). */
+#undef HAVE_LIBRT
+
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
diff --git a/configure b/configure
index b9bdb6e..2dd4cbf 100755
--- a/configure
+++ b/configure
@@ -3727,6 +3727,77 @@ _ACEOF
fi
+
+{ echo "$as_me:$LINENO: checking for clock_gettime in -lrt" >&5
+echo $ECHO_N "checking for clock_gettime in -lrt... $ECHO_C" >&6; }
+if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_rt_clock_gettime=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_rt_clock_gettime=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_rt_clock_gettime" >&5
+echo "${ECHO_T}$ac_cv_lib_rt_clock_gettime" >&6; }
+if test $ac_cv_lib_rt_clock_gettime = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRT 1
+_ACEOF
+
+ LIBS="-lrt $LIBS"
+
+fi
+
{ echo "$as_me:$LINENO: checking for libnet_name_resolve in -lnet" >&5
echo $ECHO_N "checking for libnet_name_resolve in -lnet... $ECHO_C" >&6; }
if test "${ac_cv_lib_net_libnet_name_resolve+set}" = set; then
diff --git a/configure.ac b/configure.ac
index 2b42253..0f43c28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,6 +18,7 @@ AC_PROG_MAKE_SET
# Checks for libraries.
AC_CHECK_LIB([socket], [socket])
AC_CHECK_LIB([nsl], [gethostbyname])
+AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([net], [libnet_name_resolve],
[AC_MSG_ERROR([libnet 1.0.x found. Arping 2.x requires libnet 1.1.x])])
AC_CHECK_LIB([net], [libnet_init], ,[AC_MSG_ERROR([libnet 1.1.x not found])])
diff --git a/src/arping.c b/src/arping.c
index 7b5e43e..593ff93 100644
--- a/src/arping.c
+++ b/src/arping.c
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
+#include <time.h>
#if HAVE_UNISTD_H
#include <unistd.h>
@@ -830,6 +831,19 @@ fixup_timeval(struct timeval *tv)
}
/**
+ * while negative microseconds, take from whole seconds.
+ * help function for measuring deltas.
+ */
+static void
+fixup_timespec(struct timespec *tv)
+{
+ while (tv->tv_nsec < 0) {
+ tv->tv_sec--;
+ tv->tv_nsec += 1000000000;
+ }
+}
+
+/**
* idiot-proof gettimeofday() wrapper
*/
static void
@@ -843,36 +857,52 @@ gettv(struct timeval *tv)
}
}
+/**
+ * idiot-proof clock_gettime() wrapper
+ */
+static void
+getclock(struct timespec *tv)
+{
+ if (-1 == clock_gettime(CLOCK_MONOTONIC, tv)) {
+ fprintf(stderr, "arping: "
+ "clock_gettime(): %s\n",
+ strerror(errno));
+ sigint(0);
+ }
+}
+
/**
- *
+ * try to receive a packet for 'packetwait' microseconds
*/
static void
-ping_recv_unix(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
+ping_recv_unix(pcap_t *pcap, uint32_t packetwait, pcap_handler func)
{
- struct timeval tv;
- struct timeval endtime;
+ struct timespec tv;
+ struct timespec endtime;
char done = 0;
+ int fd;
- gettv(&tv);
+ getclock(&tv);
endtime.tv_sec = tv.tv_sec + (packetwait / 1000000);
- endtime.tv_usec = tv.tv_usec + (packetwait % 1000000);
- fixup_timeval(&endtime);
-
- int fd;
+ endtime.tv_nsec = tv.tv_nsec + 1000 * (packetwait % 1000000);
+ fixup_timespec(&endtime);
fd = pcap_get_selectable_fd(pcap);
for (;!done;) {
int trydispatch = 0;
- gettv(&tv);
+ getclock(&tv);
tv.tv_sec = endtime.tv_sec - tv.tv_sec;
- tv.tv_usec = endtime.tv_usec - tv.tv_usec;
- fixup_timeval(&tv);
+ tv.tv_nsec = endtime.tv_nsec - tv.tv_nsec;
+ fixup_timespec(&tv);
+ if (verbose) {
+ printf("waid for %d.%09d sec\n", tv.tv_sec, tv.tv_nsec);
+ }
if (tv.tv_sec < 0) {
tv.tv_sec = 0;
- tv.tv_usec = 1;
+ tv.tv_nsec = 1;
done = 1;
}
if (time_to_die) {
@@ -886,7 +916,9 @@ ping_recv_unix(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
p.fd = fd;
p.events = POLLIN | POLLPRI;
- r = poll(&p, 1, tv.tv_sec * 1000 + tv.tv_usec / 1000);
+ /* poll has ms resolution, but has less false
+ positives than select() */
+ r = poll(&p, 1,tv.tv_sec * 1000 + tv.tv_nsec / 1000000);
switch (r) {
case 0: /* timeout */
done = 1;
@@ -1120,6 +1152,12 @@ int main(int argc, char **argv)
}
}
+ if (verbose) {
+ struct timespec ts;
+ clock_getres(CLOCK_MONOTONIC, &ts);
+ printf("clock_getres() = %d %d\n", ts.tv_sec, ts.tv_nsec);
+ }
+
if (display == DOT) {
setvbuf(stdout, NULL, _IONBF, 0);
}