diff options
-rw-r--r-- | config.h.in | 6 | ||||
-rwxr-xr-x | configure | 189 | ||||
-rw-r--r-- | configure.ac | 25 | ||||
-rw-r--r-- | src/arping.c | 56 |
4 files changed, 265 insertions, 11 deletions
diff --git a/config.h.in b/config.h.in index c15430b..b3015a0 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,9 @@ /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H +/* Monotonic clock */ +#undef HAVE_CLOCK_MONOTONIC + /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY @@ -78,6 +81,9 @@ /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H +/* Define to 1 if you have the <time.h> header file. */ +#undef HAVE_TIME_H + /* Define to 1 if you have the <unistd.h> header file. */ #undef HAVE_UNISTD_H @@ -709,6 +709,8 @@ CPP GREP EGREP LIBOBJS +HAVE_CLOCK_MONOTONIC_TRUE +HAVE_CLOCK_MONOTONIC_FALSE LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias @@ -3944,6 +3946,89 @@ echo "$as_me: error: libpcap not found" >&2;} { (exit 1); exit 1; }; } fi +{ echo "$as_me:$LINENO: checking for library containing clock_gettime" >&5 +echo $ECHO_N "checking for library containing clock_gettime... $ECHO_C" >&6; } +if test "${ac_cv_search_clock_gettime+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$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 +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + 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_search_clock_gettime=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext + if test "${ac_cv_search_clock_gettime+set}" = set; then + break +fi +done +if test "${ac_cv_search_clock_gettime+set}" = set; then + : +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_search_clock_gettime" >&5 +echo "${ECHO_T}$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + # Checks for header files. ac_ext=c @@ -4593,11 +4678,13 @@ done + for ac_header in \ arpa/inet.h \ netinet/in.h \ stdlib.h \ sys/socket.h \ +time.h \ sys/time.h \ sys/types.h \ stdint.h \ @@ -5941,6 +6028,91 @@ esac ;; esac + + + +# check for CLOCK_MONOTONIC +{ echo "$as_me:$LINENO: checking for CLOCK_MONOTONIC" >&5 +echo $ECHO_N "checking for CLOCK_MONOTONIC... $ECHO_C" >&6; } +if test "${ac_cv_have_clock_monotonic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <time.h> +int main() { +struct timespec ts; +exit(!!clock_gettime(CLOCK_MONOTONIC, &ts)); +} + +_ACEOF +rm -f 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>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (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_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_clock_monotonic="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) + ac_cv_have_clock_monotonic="no" + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_have_clock_monotonic" >&5 +echo "${ECHO_T}$ac_cv_have_clock_monotonic" >&6; } + if test x$ac_cv_have_clock_monotonic = xyes; then + HAVE_CLOCK_MONOTONIC_TRUE= + HAVE_CLOCK_MONOTONIC_FALSE='#' +else + HAVE_CLOCK_MONOTONIC_TRUE='#' + HAVE_CLOCK_MONOTONIC_FALSE= +fi + +if test x$ac_cv_have_clock_monotonic = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CLOCK_MONOTONIC 1 +_ACEOF + +fi + ac_config_files="$ac_config_files Makefile" ac_config_files="$ac_config_files src/Makefile" @@ -6064,6 +6236,13 @@ echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${HAVE_CLOCK_MONOTONIC_TRUE}" && test -z "${HAVE_CLOCK_MONOTONIC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_CLOCK_MONOTONIC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_CLOCK_MONOTONIC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files @@ -6692,10 +6871,12 @@ CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LIBOBJS!$LIBOBJS$ac_delim +HAVE_CLOCK_MONOTONIC_TRUE!$HAVE_CLOCK_MONOTONIC_TRUE$ac_delim +HAVE_CLOCK_MONOTONIC_FALSE!$HAVE_CLOCK_MONOTONIC_FALSE$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 95; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -6714,7 +6895,7 @@ fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g @@ -6727,8 +6908,6 @@ N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS <conf$$subs.sed rm -f conf$$subs.sed cat >>$CONFIG_STATUS <<_ACEOF -:end -s/|#_!!_#|//g CEOF$ac_eof _ACEOF @@ -6982,7 +7161,7 @@ s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack -" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed 's/|#_!!_#|//g' >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && diff --git a/configure.ac b/configure.ac index 2b42253..e653723 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,7 @@ 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])]) AC_CHECK_LIB([pcap], [pcap_open_live], ,[AC_MSG_ERROR([libpcap not found])]) +AC_SEARCH_LIBS([clock_gettime], [rt]) # Checks for header files. AC_HEADER_STDC @@ -30,6 +31,7 @@ arpa/inet.h \ netinet/in.h \ stdlib.h \ sys/socket.h \ +time.h \ sys/time.h \ sys/types.h \ stdint.h \ @@ -70,6 +72,29 @@ case "$target_os" in AC_LIBOBJ([findif_other]) ;; esac + + + +# check for CLOCK_MONOTONIC +AC_CACHE_CHECK([for CLOCK_MONOTONIC], + ac_cv_have_clock_monotonic, [ + AC_TRY_RUN( + [ +#include <time.h> +int main() { +struct timespec ts; +exit(!!clock_gettime(CLOCK_MONOTONIC, &ts)); +} + ], + [ ac_cv_have_clock_monotonic="yes" ], + [ ac_cv_have_clock_monotonic="no" ] + ) +]) +AM_CONDITIONAL(HAVE_CLOCK_MONOTONIC, test x$ac_cv_have_clock_monotonic = xyes) +if test x$ac_cv_have_clock_monotonic = xyes; then + AC_DEFINE([HAVE_CLOCK_MONOTONIC], [1], [Monotonic clock]) +fi + AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([doc/Makefile]) diff --git a/src/arping.c b/src/arping.c index 0057b41..5d17426 100644 --- a/src/arping.c +++ b/src/arping.c @@ -51,6 +51,10 @@ #include <inttypes.h> #endif +#if HAVE_TIME_H +#include <time.h> +#endif + #if HAVE_SYS_TIME_H #include <sys/time.h> #endif @@ -493,13 +497,13 @@ pingmac_send(uint8_t *srcmac, uint8_t *dstmac, libnet_geterror(libnet)); sigint(0); } - if(verbose>1) { + if (verbose > 1) { if (-1 == gettimeofday(&lastpacketsent, NULL)) { fprintf(stderr, "arping: gettimeofday(): %s\n", strerror(errno)); sigint(0); } - printf("arping: sending packet at time %d %d\n", + printf("arping: sending packet at time %d.%.6d\n", (int)lastpacketsent.tv_sec, (int)lastpacketsent.tv_usec); } @@ -845,6 +849,22 @@ gettv(struct timeval *tv) } } +/** + * get monotonic clock if available, gettimeofday() if not + */ +void +getclock(struct timeval *tv) +{ +#if HAVE_CLOCK_MONOTONIC + struct timespec ts; + if (!clock_gettime(CLOCK_MONOTONIC, &ts)) { + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + return; + } +#endif + gettv(tv); +} /** * @@ -855,28 +875,46 @@ ping_recv_unix(pcap_t *pcap,uint32_t packetwait, pcap_handler func) struct timeval tv; struct timeval 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; - 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); + + /* if time has passed, do one last check and then we're done. + * this also triggers if not using monotonic clock and time + * is set forwards */ if (tv.tv_sec < 0) { tv.tv_sec = 0; tv.tv_usec = 1; done = 1; } + + /* if wait-for-packet time is longer than full period, + * we're obviously not using a monotonic clock and the system + * time has been changed. + * we don't know how far we're into the waiting, so just end + * it here */ + if ((tv.tv_sec > packetwait / 1000000) + || ((tv.tv_sec == packetwait / 1000000) + && (tv.tv_usec > packetwait % 1000000))) { + tv.tv_sec = 0; + tv.tv_usec = 1; + done = 1; + } + + /* check for sigint */ if (time_to_die) { return; } @@ -1396,3 +1434,9 @@ int main(int argc, char **argv) return !numrecvd; } } +/* ---- Emacs Variables ---- + * Local Variables: + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ |