diff options
author | Thomas Habets <thomas@habets.pp.se> | 2010-04-02 13:42:47 +0200 |
---|---|---|
committer | Thomas Habets <thomas@habets.pp.se> | 2010-04-02 13:42:47 +0200 |
commit | 34ace21f5d654f2eb6dc45ab06b4efe00655bfb5 (patch) | |
tree | 2a5d25625fe6c9503a7025ff48ab97f73970ff51 | |
parent | df36995363d6b92d635d353a55ba4b51ce004b5a (diff) | |
download | arping-34ace21f5d654f2eb6dc45ab06b4efe00655bfb5.tar.gz |
changed ping_recv_unix to use clock_gettime() instead of gettimeofday()
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 71 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/arping.c | 66 |
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 @@ -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); } |