diff options
author | Thomas Habets <thomas@habets.pp.se> | 2010-04-02 14:08:05 +0200 |
---|---|---|
committer | Thomas Habets <thomas@habets.pp.se> | 2010-04-02 14:08:05 +0200 |
commit | f4f67c07d395b9d15ad8fdd283adacbf37c6a618 (patch) | |
tree | 6e3c20c11a063951795ae8038bf58feb483c64b0 /src/arping.c | |
parent | df36995363d6b92d635d353a55ba4b51ce004b5a (diff) | |
parent | 01f3f9638923a9ef14e183b8ac6dde0f367f7d9f (diff) | |
download | arping-f4f67c07d395b9d15ad8fdd283adacbf37c6a618.tar.gz |
Merge branch 'clock_gettime' into arping-2.x
Diffstat (limited to 'src/arping.c')
-rw-r--r-- | src/arping.c | 196 |
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); } |