summaryrefslogtreecommitdiff
path: root/src/arping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arping.c')
-rw-r--r--src/arping.c196
1 files changed, 88 insertions, 108 deletions
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);
}