summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Habets <thomas@habets.pp.se>2010-04-02 14:08:05 +0200
committerThomas Habets <thomas@habets.pp.se>2010-04-02 14:08:05 +0200
commitf4f67c07d395b9d15ad8fdd283adacbf37c6a618 (patch)
tree6e3c20c11a063951795ae8038bf58feb483c64b0
parentdf36995363d6b92d635d353a55ba4b51ce004b5a (diff)
parent01f3f9638923a9ef14e183b8ac6dde0f367f7d9f (diff)
downloadarping-f4f67c07d395b9d15ad8fdd283adacbf37c6a618.tar.gz
Merge branch 'clock_gettime' into arping-2.x
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure71
-rw-r--r--configure.ac1
-rw-r--r--src/arping.c196
4 files changed, 163 insertions, 108 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..d537c60 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>
@@ -109,7 +110,7 @@ static const char *version = VERSION; /* from autoconf */
static libnet_t *libnet = 0;
-static struct timeval lastpacketsent;
+static struct timespec lastpacketsent;
uint32_t srcip, dstip;
@@ -228,6 +229,21 @@ static void sigint(int i)
}
/**
+ * idiot-proof clock_gettime() wrapper
+ */
+static void
+getclock(struct timespec *ts)
+{
+ if (-1 == clock_gettime(CLOCK_MONOTONIC, ts)) {
+ fprintf(stderr,
+ "arping: clock_gettime(): %s\n",
+ strerror(errno));
+ sigint(0);
+ }
+}
+
+
+/**
*
*/
static void
@@ -387,44 +403,44 @@ static int get_mac_addr(const char *in,
}
/**
- * as always, the answer is 42
- *
- * in this case the question is how many bytes buf needs to be.
- * Assuming a 33 byte max %d
+ * max size of buffer is intsize + 1 + intsize + 4 = 70 bytes or so
*
* Still, I'm using at least 128bytes below
*
* (because snprintf() sadly isn't as portable, that's why)
*/
-static char *tv2str(const struct timeval *tv, const struct timeval *tv2,
+static char *ts2str(const struct timespec *tv, const struct timespec *tv2,
char *buf)
{
double f,f2;
int exp = 0;
- f = tv->tv_sec + (double)tv->tv_usec / 1000000;
- f2 = tv2->tv_sec + (double)tv2->tv_usec / 1000000;
- f = (f2 - f) * 1000000;
+ f = tv->tv_sec + (double)tv->tv_nsec / 1000000000;
+ f2 = tv2->tv_sec + (double)tv2->tv_nsec / 1000000000;
+ f = (f2 - f) * 1000000000;
while (f > 1000) {
- exp+= 3;
+ exp += 3;
f /= 1000;
}
switch (exp) {
case 0:
- sprintf(buf, "%.3f usec", f);
+ sprintf(buf, "%.3f nsec", f);
break;
case 3:
- sprintf(buf, "%.3f msec", f);
+ sprintf(buf, "%.3f usec", f);
break;
case 6:
- sprintf(buf, "%.3f sec", f);
+ sprintf(buf, "%.3f msec", f);
break;
case 9:
+ sprintf(buf, "%.3f sec", f);
+ break;
+ case 12:
sprintf(buf, "%.3f sec", f*1000);
break;
default:
/* huh, uh, huhuh */
- sprintf(buf, "%.3fe%d sec", f, exp-6);
+ sprintf(buf, "%.3fe%d sec", f, exp-9);
}
return buf;
}
@@ -492,25 +508,17 @@ pingmac_send(uint8_t *srcmac, uint8_t *dstmac,
sigint(0);
}
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",
- lastpacketsent.tv_sec,
- lastpacketsent.tv_usec);
+ getclock(&lastpacketsent);
+ printf("arping: sending packet at time %d.%09d\n",
+ lastpacketsent.tv_sec,
+ lastpacketsent.tv_nsec);
}
if (-1 == (c = libnet_write(libnet))) {
fprintf(stderr, "arping: libnet_write(): %s\n",
libnet_geterror(libnet));
sigint(0);
}
- if (-1 == gettimeofday(&lastpacketsent, NULL)) {
- fprintf(stderr, "arping: gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
- }
+ getclock(&lastpacketsent);
numsent++;
}
@@ -556,25 +564,17 @@ pingip_send(uint8_t *srcmac, uint8_t *dstmac,
sigint(0);
}
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",
- lastpacketsent.tv_sec,
- lastpacketsent.tv_usec);
+ getclock(&lastpacketsent);
+ printf("arping: sending packet at time %d.%09d\n",
+ lastpacketsent.tv_sec,
+ lastpacketsent.tv_nsec);
}
if (-1 == libnet_write(libnet)) {
fprintf(stderr, "arping: libnet_write(): %s\n",
libnet_geterror(libnet));
sigint(0);
}
- if (-1 == gettimeofday(&lastpacketsent, NULL)) {
- fprintf(stderr, "arping: gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
- }
+ getclock(&lastpacketsent);
numsent++;
}
@@ -589,18 +589,15 @@ pingip_recv(const char *unused, struct pcap_pkthdr *h,
{
struct libnet_802_3_hdr *heth;
struct libnet_arp_hdr *harp;
- struct timeval arrival;
+ struct timespec arrival;
int c;
if(verbose>2) {
printf("arping: received response for ip ping\n");
}
- if (-1 == gettimeofday(&arrival, NULL)) {
- fprintf(stderr, "arping: gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
- }
+ getclock(&arrival);
+
heth = (void*)packet;
harp = (void*)((char*)heth + LIBNET_ETH_H);
@@ -637,8 +634,8 @@ pingip_recv(const char *unused, struct pcap_pkthdr *h,
printf("/%u", numsent-1);
}
printf(" time=%s",
- tv2str(&lastpacketsent,
- &arrival,buf));
+ ts2str(&lastpacketsent,
+ &arrival,buf));
break; }
case QUIET:
break;
@@ -697,18 +694,14 @@ pingmac_recv(const char *unused, struct pcap_pkthdr *h,
struct libnet_802_3_hdr *heth;
struct libnet_ipv4_hdr *hip;
struct libnet_icmpv4_hdr *hicmp;
- struct timeval arrival;
+ struct timespec arrival;
int c;
if(verbose>2) {
printf("arping: received response for mac ping\n");
}
- if (-1 == gettimeofday(&arrival, NULL)) {
- fprintf(stderr, "arping: gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
- }
+ getclock(&arrival);
heth = (void*)packet;
hip = (void*)((char*)heth + LIBNET_ETH_H);
@@ -737,8 +730,8 @@ pingmac_recv(const char *unused, struct pcap_pkthdr *h,
(c<5)?':':')');
}
printf(": icmp_seq=%d time=%s",
- htons(hicmp->icmp_seq),tv2str(&lastpacketsent,
- &arrival,buf));
+ htons(hicmp->icmp_seq),ts2str(&lastpacketsent,
+ &arrival,buf));
break; }
case RAW:
printf("%s",
@@ -777,37 +770,28 @@ pingmac_recv(const char *unused, struct pcap_pkthdr *h,
static void
ping_recv_win32(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
{
- struct timeval tv,tv2;
+ struct timespec tv,tv2;
char done = 0;
/* windows won't let us do select() */
- if (-1 == gettimeofday(&tv2,NULL)) {
- fprintf(stderr, "arping: gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
- }
+ getclock(&tv2);
+
while (!done && !time_to_die) {
struct pcap_pkthdr *pkt_header;
u_char *pkt_data;
if (pcap_next_ex(pcap, &pkt_header, &pkt_data) == 1) {
func(pcap, pkt_header, pkt_data);
}
- if (-1 == gettimeofday(&tv,NULL)) {
- fprintf(stderr, "arping: "
- "gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
- }
+ getclock(&tv);
+
/*
- * setup next timeval, not very exact
+ * setup next timespec, not very exact
*/
tv.tv_sec = (packetwait / 1000000)
- (tv.tv_sec - tv2.tv_sec);
- tv.tv_usec = (packetwait % 1000000)
- - (tv.tv_usec - tv2.tv_usec);
- while (tv.tv_usec < 0) {
- tv.tv_sec--;
- tv.tv_usec += 1000000;
- }
+ tv.tv_nsec = (packetwait % 1000000)
+ - (tv.tv_nsec - tv2.tv_nsec);
+ fixup_timespec(&tv);
+
usleep(10);
if (tv.tv_sec < 0) {
done=1;
@@ -817,62 +801,50 @@ ping_recv_win32(pcap_t *pcap,uint32_t packetwait, pcap_handler func)
#endif
/**
- * while negative microseconds, take from whole seconds.
+ * while negative nanoseconds, take from whole seconds.
* help function for measuring deltas.
*/
static void
-fixup_timeval(struct timeval *tv)
+fixup_timespec(struct timespec *tv)
{
- while (tv->tv_usec < 0) {
+ while (tv->tv_nsec < 0) {
tv->tv_sec--;
- tv->tv_usec += 1000000;
- }
-}
-
-/**
- * idiot-proof gettimeofday() wrapper
- */
-static void
-gettv(struct timeval *tv)
-{
- if (-1 == gettimeofday(tv,NULL)) {
- fprintf(stderr, "arping: "
- "gettimeofday(): %s\n",
- strerror(errno));
- sigint(0);
+ tv->tv_nsec += 1000000000;
}
}
-
/**
- *
+ * 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("listen for replies 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 +858,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 +1094,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);
}