summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h.in6
-rwxr-xr-xconfigure189
-rw-r--r--configure.ac25
-rw-r--r--src/arping.c56
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
diff --git a/configure b/configure
index b9bdb6e..9dc2afd 100755
--- a/configure
+++ b/configure
@@ -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:
+ */