diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-02-22 16:07:13 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-02-22 16:07:13 +0200 |
commit | 6097958d5c2652ec6e98d813e1627d5cb822da19 (patch) | |
tree | b195aa773bd0ba139466798594d2dbf9e9c7ec2d | |
parent | 69bc53b8aa9ce26329603ac25f7cfb5d028845dc (diff) | |
download | ping903-6097958d5c2652ec6e98d813e1627d5cb822da19.tar.gz ping903-6097958d5c2652ec6e98d813e1627d5cb822da19.tar.bz2 |
Reorganize host array and functions
-rw-r--r-- | src/config.c | 13 | ||||
-rw-r--r-- | src/ping903.h | 9 | ||||
-rw-r--r-- | src/pinger.c | 714 |
3 files changed, 371 insertions, 365 deletions
diff --git a/src/config.c b/src/config.c index 838984d..e8b2f36 100644 --- a/src/config.c +++ b/src/config.c @@ -109,18 +109,7 @@ cf_ip_list(int mode, union cf_callback_arg *arg, void *data) ret = CF_RET_FAIL; continue; } - if (hostaddr_count == hostaddr_max) { - hostaddr = e2nrealloc(hostaddr, - &hostaddr_max, - sizeof(hostaddr[0])); - } - memset(&hostaddr[hostaddr_count], 0, sizeof(hostaddr[0])); - hostaddr[hostaddr_count].name = estrdup(p); - hostaddr[hostaddr_count].addr = emalloc(res->ai_addrlen); - memcpy(hostaddr[hostaddr_count].addr, res->ai_addr, res->ai_addrlen); - hostaddr[hostaddr_count].addrlen = res->ai_addrlen; - pthread_mutex_init(&hostaddr[hostaddr_count].mutex, NULL); - hostaddr_count++; + hostping_add(p, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } fclose(fp); diff --git a/src/ping903.h b/src/ping903.h index 57fc22a..07a7f9f 100644 --- a/src/ping903.h +++ b/src/ping903.h @@ -58,6 +58,7 @@ enum { int readconfig(char const *file); int cf_trusted_ip(int mode, union cf_callback_arg *arg, void *data); int cf_syslog_facility(int mode, union cf_callback_arg *arg, void *data); +void hostping_add(char const *name, struct sockaddr *addr, socklen_t addrlen); char *get_remote_ip(struct MHD_Connection *conn); @@ -85,7 +86,7 @@ static inline int host_stat_is_valid(struct host_stat const *hs) { return hs->status == HOST_STAT_VALID || hs->status == HOST_STAT_PENDING; } -typedef struct hostaddr { +typedef struct hostping { char *name; struct sockaddr *addr; socklen_t addrlen; @@ -105,7 +106,7 @@ typedef struct hostaddr { /* Last probe statistics */ struct host_stat stat_last; -} HOSTADDR; +} HOSTPING; extern int verbose; extern int fatal_signals[]; @@ -118,12 +119,8 @@ extern unsigned long ping_interval; extern unsigned long ping_count; extern unsigned long ping_tolerance; extern size_t data_length; -extern HOSTADDR *hostaddr; -extern size_t hostaddr_count; -extern size_t hostaddr_max; struct json_value *config_to_json(void); -int get_host_stat(HOSTADDR *host, struct json_value **); int get_hostname_stat(char const *name, struct json_value **retval); int get_ipaddr_stat(struct sockaddr *sa, int salen, struct json_value **retval); int get_all_host_stat(struct json_value **); diff --git a/src/pinger.c b/src/pinger.c index 1e91180..c131d5a 100644 --- a/src/pinger.c +++ b/src/pinger.c @@ -40,250 +40,42 @@ unsigned long probe_interval = 60; unsigned long ping_interval = 1; unsigned long ping_count = 10; unsigned long ping_tolerance = 3; - -HOSTADDR *hostaddr; -size_t hostaddr_count; -size_t hostaddr_max; - -static int ping_fd; - -static pthread_mutex_t sendq_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t sendq_cond = PTHREAD_COND_INITIALIZER; -static int send_p; - -static unsigned xmit_total; -static unsigned recv_total; - -#define ICMP_HEADER_LEN (offsetof(struct icmp, icmp_data)) -#define PING_DATALEN (64 - ICMP_HEADER_LEN) - -size_t data_length = PING_DATALEN; -static unsigned char *data_buffer; - -static int ping_ident; - -#define MAX_PING_TIMEOUT 10 -enum { - MAX_SEQNO = USHRT_MAX, - MOD_SEQNO = MAX_SEQNO + 1 -}; - -struct seqidx { - HOSTADDR *host; - struct timeval tv; - int replied; -}; - -static struct seqidx *seqidx; -unsigned short next_seqno; - -static int -seqno_alloc(HOSTADDR *addr, struct timeval *tv) -{ - int n = next_seqno; - do { - if (tv->tv_sec - seqidx[n].tv.tv_sec > MAX_PING_TIMEOUT) { - memcpy(&seqidx[n].tv, tv, sizeof(*tv)); - seqidx[n].host = addr; - seqidx[n].replied = 0; - next_seqno = (n + 1) % MOD_SEQNO; - return n; - } - n = (n + 1) % MOD_SEQNO; - } while (n != next_seqno); - error("no free sequence numbers"); - return -1; -} - -static inline void -hostaddr_lock(HOSTADDR *host) -{ - pthread_mutex_lock(&host->mutex); -} - -static inline void -hostaddr_unlock(HOSTADDR *host) -{ - pthread_mutex_unlock(&host->mutex); -} - -static HOSTADDR * -hostaddr_from_seqno(int seq) -{ - HOSTADDR *host = seqidx[seq].host; - if (seqidx[seq].replied) - info("%s:%d: DUP!", host->name, seq); - seqidx[seq].replied++; - hostaddr_lock(host); - return host; -} - -void -p903_init(void) -{ - struct protoent *proto; - int i; - - if (hostaddr_count == 0) { - fatal("no host IPs configured, nothing to do?"); - exit(1); - } - - proto = getprotobyname("icmp"); - if (!proto) { - fatal("no entry for icmp in the system protocol database"); - exit(1); - } - ping_fd = socket(AF_INET, SOCK_RAW, proto->p_proto); - if (ping_fd < 0) { - fatal("can't create ICMP socket: %s", strerror(errno)); - exit(1); - } - - ping_ident = getpid() & 0xffff; - - data_buffer = emalloc(data_length); - for (i = 0; i < data_length; i++) - data_buffer[i] = i; - - seqidx = calloc(MAX_SEQNO + 1, sizeof(seqidx[0])); - if (!seqidx) - emalloc_die(); -} -static unsigned short -icmp_cksum(unsigned char * addr, int len) -{ - register int sum = 0; - unsigned short answer = 0; - unsigned short *wp; - - for (wp = (unsigned short *) addr; len > 1; wp++, len -= 2) - sum += *wp; - - /* Take in an odd byte if present */ - if (len == 1) { - *(unsigned char *) & answer = *(unsigned char *) wp; - sum += answer; - } - - sum = (sum >> 16) + (sum & 0xffff); /* add high 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return answer; -} - -static int -icmp_generic_encode(unsigned char * buffer, size_t bufsize, int type, - int ident, int seqno) +static double +nabs(double a) { - struct icmp *icmp; - - if (bufsize < ICMP_MINLEN) - return -1; - icmp = (struct icmp *) buffer; - icmp->icmp_type = type; - icmp->icmp_code = 0; - icmp->icmp_cksum = 0; - icmp->icmp_seq = htons(seqno); - icmp->icmp_id = htons(ident); - - icmp->icmp_cksum = icmp_cksum(buffer, bufsize); - return 0; + return (a < 0) ? -a : a; } -static int -icmp_generic_decode(unsigned char * buffer, size_t bufsize, - struct ip **ipp, struct icmp ** icmpp) +static double +nsqrt(double a, double prec) { - size_t hlen; - unsigned short cksum; - struct ip *ip; - struct icmp *icmp; - - /* IP header */ - ip = (struct ip *) buffer; - hlen = ip->ip_hl << 2; - if (bufsize < hlen + ICMP_MINLEN) - return -1; - - /* ICMP header */ - icmp = (struct icmp *) (buffer + hlen); - - /* Prepare return values */ - *ipp = ip; - *icmpp = icmp; + double x0, x1; - /* Recompute checksum */ - cksum = icmp->icmp_cksum; - icmp->icmp_cksum = 0; - icmp->icmp_cksum = icmp_cksum((unsigned char *) icmp, bufsize - hlen); - if (icmp->icmp_cksum != cksum) - return 1; - icmp->icmp_seq = ntohs(icmp->icmp_seq); - icmp->icmp_id = ntohs(icmp->icmp_id); - - return 0; + if (a < 0) + return 0; + if (a < prec) + return 0; + x1 = a / 2; + do { + x0 = x1; + x1 = (x0 + a / x0) / 2; + } while (nabs(x1 - x0) > prec); + return x1; } -static void -send_echo(HOSTADDR *host, unsigned char *ping_buffer) +static inline int +timeval_is_null(struct timeval const *tv) { - struct icmp *icmp = (struct icmp *) ping_buffer; - size_t buflen; - ssize_t n; - int seqno; - - hostaddr_lock(host); - gettimeofday(&host->xmit_tv, NULL); - hostaddr_unlock(host); - - memcpy(icmp->icmp_data, &host->xmit_tv, sizeof(host->xmit_tv)); - if (data_buffer) - memcpy(icmp->icmp_data + sizeof(host->xmit_tv), data_buffer, - data_length - sizeof(host->xmit_tv)); - - buflen = ICMP_HEADER_LEN + data_length; - - seqno = seqno_alloc(host, &host->xmit_tv); - if (seqno == -1) { - //FIXME - return; - } - - if (verbose > 2) - info("sending %d bytes to %s, icmp_seq=%d", buflen, host->name, - seqno); - icmp_generic_encode(ping_buffer, buflen, ICMP_ECHO, ping_ident, seqno); - - n = sendto(ping_fd, (char *) ping_buffer, buflen, 0, - host->addr, host->addrlen); - if (n < 0) { - error("%s: sendto: %s", host->name, strerror(errno)); - } else { - hostaddr_lock(host); - if (host->xmit_count == 0) - host->start_tv = host->xmit_tv; - host->xmit_count++; - hostaddr_unlock(host); - xmit_total++; - if (n != buflen) - error("ping: wrote %s %d chars, ret=%d\n", - host->name, buflen, n); - } + return tv->tv_sec == 0 && tv->tv_usec == 0; } -static void -start_probe(void) +static inline double +timeval_to_double(struct timeval const *tv) { - pthread_mutex_lock(&sendq_mutex); - send_p = 1; - pthread_cond_broadcast(&sendq_cond); - pthread_mutex_unlock(&sendq_mutex); + return (double)tv->tv_sec + (double)tv->tv_usec / 1000000; } - -static void host_stat_commit(HOSTADDR *host); - + enum { NANOSEC_IN_SEC = 1000000000 }; static inline void @@ -304,98 +96,42 @@ timespec_incr(struct timespec *a, struct timespec const *b) struct timespec t = *a; timespec_add(&t, b, a); } + +static HOSTPING *hostping; +static size_t hostping_count; +static size_t hostping_max; -void * -p903_sender(void *p) +void +hostping_add(char const *name, struct sockaddr *addr, socklen_t addrlen) { - size_t i; - unsigned char *ping_buffer; - struct pollfd pfd; - int n; - unsigned send_count = 0; - double d; - struct timespec delay; - - pfd.fd = ping_fd; - pfd.events = POLLOUT; - - ping_buffer = emalloc(sizeof(struct icmp) + data_length); - - d = (double) ping_interval / hostaddr_count; - delay.tv_sec = (int) d; - delay.tv_nsec = (d - delay.tv_sec) * NANOSEC_IN_SEC; - - pthread_mutex_lock(&sendq_mutex); - while (1) { - struct timespec ts; - - if (!send_p) { - while (!send_p) - pthread_cond_wait(&sendq_cond, &sendq_mutex); - send_count = 0; - } - clock_gettime(CLOCK_MONOTONIC, &ts); - for (i = 0; i < hostaddr_count; i++) { - struct timespec nts; - clock_gettime(CLOCK_MONOTONIC, &nts); - timespec_incr(&nts, &delay); - n = poll(&pfd, 1, -1); - if (n == 1) { - send_echo(&hostaddr[i], ping_buffer); - } else if (n == -1) { - fatal("poll: %s", strerror(errno)); - exit(1); - } - if (i < hostaddr_count - 1) - clock_nanosleep(CLOCK_MONOTONIC, - TIMER_ABSTIME, &nts, - NULL); - } - send_count++; - if (send_count == ping_count) - send_p = 0; - else { - ts.tv_sec += ping_interval; - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, - NULL); - } + if (hostping_count == hostping_max) { + hostping = e2nrealloc(hostping, + &hostping_max, + sizeof(hostping[0])); } - pthread_mutex_unlock(&sendq_mutex); - return NULL; -} - -static double -nabs(double a) -{ - return (a < 0) ? -a : a; + memset(&hostping[hostping_count], 0, sizeof(hostping[0])); + hostping[hostping_count].name = estrdup(name); + hostping[hostping_count].addr = emalloc(addrlen); + memcpy(hostping[hostping_count].addr, addr, addrlen); + hostping[hostping_count].addrlen =addrlen; + pthread_mutex_init(&hostping[hostping_count].mutex, NULL); + hostping_count++; } -static double -nsqrt(double a, double prec) +static inline void +hostping_lock(HOSTPING *host) { - double x0, x1; - - if (a < 0) - return 0; - if (a < prec) - return 0; - x1 = a / 2; - do { - x0 = x1; - x1 = (x0 + a / x0) / 2; - } - while (nabs(x1 - x0) > prec); - return x1; + pthread_mutex_lock(&host->mutex); } -static inline int -timeval_is_null(struct timeval const *tv) +static inline void +hostping_unlock(HOSTPING *host) { - return tv->tv_sec == 0 && tv->tv_usec == 0; + pthread_mutex_unlock(&host->mutex); } static void -hostaddr_extract_stat(HOSTADDR *host, struct host_stat *st) +hostping_extract_stat(HOSTPING *host, struct host_stat *st) { memcpy(&st->start_tv, &host->start_tv, sizeof(host->stat_last.start_tv)); @@ -418,21 +154,21 @@ hostaddr_extract_stat(HOSTADDR *host, struct host_stat *st) } static void -host_stat_commit(HOSTADDR *host) +hostping_commit(HOSTPING *host) { if (host->stat_last.status != HOST_STAT_VALID) { - hostaddr_extract_stat(host, &host->stat_last); + hostping_extract_stat(host, &host->stat_last); host->stat_last.status = HOST_STAT_VALID; } } /* Reset runtime statistics counters */ static void -host_reset(HOSTADDR *host) +hostping_reset(HOSTPING *host) { - hostaddr_lock(host); + hostping_lock(host); if (host->xmit_count > 0) - host_stat_commit(host); + hostping_commit(host); host->xmit_count = 0; host->recv_count = 0; host->tmin = 999999999.0; @@ -451,17 +187,11 @@ host_reset(HOSTADDR *host) case HOST_STAT_INVALID: break; } - hostaddr_unlock(host); -} - -static inline double -timeval_to_double(struct timeval const *tv) -{ - return (double)tv->tv_sec + (double)tv->tv_usec / 1000000; + hostping_unlock(host); } -int -get_host_stat(HOSTADDR *host, struct json_value **retval) +static int +get_hostping_stat(HOSTPING *host, struct json_value **retval) { struct json_value *obj, *v; struct host_stat const *st; @@ -474,7 +204,8 @@ get_host_stat(HOSTADDR *host, struct json_value **retval) }; int validity; double ts; - + + hostping_lock(host); if (!(obj = json_new_object())) goto err; @@ -487,7 +218,7 @@ get_host_stat(HOSTADDR *host, struct json_value **retval) validity = 1; } else if (host->stat_last.status == HOST_STAT_INIT && host->xmit_count > ping_tolerance) { - hostaddr_extract_stat(host, &stbuf); + hostping_extract_stat(host, &stbuf); stbuf.status = HOST_STAT_PENDING; st = &stbuf; validity = 1; @@ -559,10 +290,13 @@ get_host_stat(HOSTADDR *host, struct json_value **retval) goto err; } + hostping_unlock(host); + *retval = obj; return 0; err: + hostping_unlock(host); error("out of memory when formatting statistics for %s", host->name); json_value_free(v); json_value_free(obj); @@ -575,9 +309,9 @@ get_hostname_stat(char const *name, struct json_value **retval) { size_t i; - for (i = 0; i < hostaddr_count; i++) { - if (strcmp(hostaddr[i].name, name) == 0) - return get_host_stat(&hostaddr[i], retval); + for (i = 0; i < hostping_count; i++) { + if (strcmp(hostping[i].name, name) == 0) + return get_hostping_stat(&hostping[i], retval); } *retval = NULL; return 0; @@ -588,10 +322,10 @@ get_ipaddr_stat(struct sockaddr *sa, int salen, struct json_value **retval) { size_t i; - for (i = 0; i < hostaddr_count; i++) { - if (hostaddr[i].addrlen == salen - && memcmp(hostaddr[i].addr, sa, salen) == 0) - return get_host_stat(&hostaddr[i], retval); + for (i = 0; i < hostping_count; i++) { + if (hostping[i].addrlen == salen + && memcmp(hostping[i].addr, sa, salen) == 0) + return get_hostping_stat(&hostping[i], retval); } *retval = NULL; return 0; @@ -605,9 +339,9 @@ get_all_host_stat(struct json_value **retval) if (!(ar = json_new_array())) goto err; - for (i = 0; i < hostaddr_count; i++) { + for (i = 0; i < hostping_count; i++) { struct json_value *v; - if (get_host_stat(&hostaddr[i], &v)) + if (get_hostping_stat(&hostping[i], &v)) goto err; if (json_array_append(ar, v)) { json_value_free(v); @@ -632,19 +366,19 @@ get_host_matches(struct addrinfo **aip, struct json_value **retval) if (!(ar = json_new_array())) goto err; - for (i = 0; i < hostaddr_count; i++) { + for (i = 0; i < hostping_count; i++) { struct addrinfo *prev = NULL, *p; if (!ai) break; p = ai; while (p) { struct addrinfo *next = p->ai_next; - if (p->ai_addrlen == hostaddr[i].addrlen - && memcmp(hostaddr[i].addr, p->ai_addr, - hostaddr[i].addrlen) == 0) { + if (p->ai_addrlen == hostping[i].addrlen + && memcmp(hostping[i].addr, p->ai_addr, + hostping[i].addrlen) == 0) { struct json_value *jv; - jv = json_new_string(hostaddr[i].name); + jv = json_new_string(hostping[i].name); if (!jv) goto err; if (json_array_append(ar, jv)) { @@ -683,7 +417,293 @@ err: json_value_free(ar); return ret; } + +static int ping_fd; + +static pthread_mutex_t sendq_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t sendq_cond = PTHREAD_COND_INITIALIZER; +static int send_p; +static unsigned xmit_total; +static unsigned recv_total; + +#define ICMP_HEADER_LEN (offsetof(struct icmp, icmp_data)) +#define PING_DATALEN (64 - ICMP_HEADER_LEN) + +size_t data_length = PING_DATALEN; +static unsigned char *data_buffer; + +static int ping_ident; + +#define MAX_PING_TIMEOUT 10 +enum { + MAX_SEQNO = USHRT_MAX, + MOD_SEQNO = MAX_SEQNO + 1 +}; + +struct seqidx { + HOSTPING *host; + struct timeval tv; + int replied; +}; + +static struct seqidx *seqidx; +unsigned short next_seqno; + +static int +seqno_alloc(HOSTPING *addr, struct timeval *tv) +{ + int n = next_seqno; + do { + if (tv->tv_sec - seqidx[n].tv.tv_sec > MAX_PING_TIMEOUT) { + memcpy(&seqidx[n].tv, tv, sizeof(*tv)); + seqidx[n].host = addr; + seqidx[n].replied = 0; + next_seqno = (n + 1) % MOD_SEQNO; + return n; + } + n = (n + 1) % MOD_SEQNO; + } while (n != next_seqno); + error("no free sequence numbers"); + return -1; +} + +static HOSTPING * +hostping_from_seqno(int seq) +{ + HOSTPING *host = seqidx[seq].host; + if (seqidx[seq].replied) + info("%s:%d: DUP!", host->name, seq); + seqidx[seq].replied++; + hostping_lock(host); + return host; +} + +void +p903_init(void) +{ + struct protoent *proto; + int i; + + if (hostping_count == 0) { + fatal("no host IPs configured, nothing to do?"); + exit(1); + } + + proto = getprotobyname("icmp"); + if (!proto) { + fatal("no entry for icmp in the system protocol database"); + exit(1); + } + ping_fd = socket(AF_INET, SOCK_RAW, proto->p_proto); + if (ping_fd < 0) { + fatal("can't create ICMP socket: %s", strerror(errno)); + exit(1); + } + + ping_ident = getpid() & 0xffff; + + data_buffer = emalloc(data_length); + for (i = 0; i < data_length; i++) + data_buffer[i] = i; + + seqidx = calloc(MAX_SEQNO + 1, sizeof(seqidx[0])); + if (!seqidx) + emalloc_die(); +} + +static unsigned short +icmp_cksum(unsigned char * addr, int len) +{ + register int sum = 0; + unsigned short answer = 0; + unsigned short *wp; + + for (wp = (unsigned short *) addr; len > 1; wp++, len -= 2) + sum += *wp; + + /* Take in an odd byte if present */ + if (len == 1) { + *(unsigned char *) & answer = *(unsigned char *) wp; + sum += answer; + } + + sum = (sum >> 16) + (sum & 0xffff); /* add high 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return answer; +} + +static int +icmp_generic_encode(unsigned char * buffer, size_t bufsize, int type, + int ident, int seqno) +{ + struct icmp *icmp; + + if (bufsize < ICMP_MINLEN) + return -1; + icmp = (struct icmp *) buffer; + icmp->icmp_type = type; + icmp->icmp_code = 0; + icmp->icmp_cksum = 0; + icmp->icmp_seq = htons(seqno); + icmp->icmp_id = htons(ident); + + icmp->icmp_cksum = icmp_cksum(buffer, bufsize); + return 0; +} + +static int +icmp_generic_decode(unsigned char * buffer, size_t bufsize, + struct ip **ipp, struct icmp ** icmpp) +{ + size_t hlen; + unsigned short cksum; + struct ip *ip; + struct icmp *icmp; + + /* IP header */ + ip = (struct ip *) buffer; + hlen = ip->ip_hl << 2; + if (bufsize < hlen + ICMP_MINLEN) + return -1; + + /* ICMP header */ + icmp = (struct icmp *) (buffer + hlen); + + /* Prepare return values */ + *ipp = ip; + *icmpp = icmp; + + /* Recompute checksum */ + cksum = icmp->icmp_cksum; + icmp->icmp_cksum = 0; + icmp->icmp_cksum = icmp_cksum((unsigned char *) icmp, bufsize - hlen); + if (icmp->icmp_cksum != cksum) + return 1; + icmp->icmp_seq = ntohs(icmp->icmp_seq); + icmp->icmp_id = ntohs(icmp->icmp_id); + + return 0; +} + +static void +send_echo(HOSTPING *host, unsigned char *ping_buffer) +{ + struct icmp *icmp = (struct icmp *) ping_buffer; + size_t buflen; + ssize_t n; + int seqno; + + hostping_lock(host); + gettimeofday(&host->xmit_tv, NULL); + hostping_unlock(host); + + memcpy(icmp->icmp_data, &host->xmit_tv, sizeof(host->xmit_tv)); + if (data_buffer) + memcpy(icmp->icmp_data + sizeof(host->xmit_tv), data_buffer, + data_length - sizeof(host->xmit_tv)); + + buflen = ICMP_HEADER_LEN + data_length; + + seqno = seqno_alloc(host, &host->xmit_tv); + if (seqno == -1) { + //FIXME + return; + } + + if (verbose > 2) + info("sending %d bytes to %s, icmp_seq=%d", buflen, host->name, + seqno); + icmp_generic_encode(ping_buffer, buflen, ICMP_ECHO, ping_ident, seqno); + + n = sendto(ping_fd, (char *) ping_buffer, buflen, 0, + host->addr, host->addrlen); + if (n < 0) { + error("%s: sendto: %s", host->name, strerror(errno)); + } else { + hostping_lock(host); + if (host->xmit_count == 0) + host->start_tv = host->xmit_tv; + host->xmit_count++; + hostping_unlock(host); + xmit_total++; + if (n != buflen) + error("ping: wrote %s %d chars, ret=%d\n", + host->name, buflen, n); + } +} + +static void +start_probe(void) +{ + pthread_mutex_lock(&sendq_mutex); + send_p = 1; + pthread_cond_broadcast(&sendq_cond); + pthread_mutex_unlock(&sendq_mutex); +} + +static void hostping_commit(HOSTPING *host); + +void * +p903_sender(void *p) +{ + size_t i; + unsigned char *ping_buffer; + struct pollfd pfd; + int n; + unsigned send_count = 0; + double d; + struct timespec delay; + + pfd.fd = ping_fd; + pfd.events = POLLOUT; + + ping_buffer = emalloc(sizeof(struct icmp) + data_length); + + d = (double) ping_interval / hostping_count; + delay.tv_sec = (int) d; + delay.tv_nsec = (d - delay.tv_sec) * NANOSEC_IN_SEC; + + pthread_mutex_lock(&sendq_mutex); + while (1) { + struct timespec ts; + + if (!send_p) { + while (!send_p) + pthread_cond_wait(&sendq_cond, &sendq_mutex); + send_count = 0; + } + clock_gettime(CLOCK_MONOTONIC, &ts); + for (i = 0; i < hostping_count; i++) { + struct timespec nts; + clock_gettime(CLOCK_MONOTONIC, &nts); + timespec_incr(&nts, &delay); + n = poll(&pfd, 1, -1); + if (n == 1) { + send_echo(&hostping[i], ping_buffer); + } else if (n == -1) { + fatal("poll: %s", strerror(errno)); + exit(1); + } + if (i < hostping_count - 1) + clock_nanosleep(CLOCK_MONOTONIC, + TIMER_ABSTIME, &nts, + NULL); + } + send_count++; + if (send_count == ping_count) + send_p = 0; + else { + ts.tv_sec += ping_interval; + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, + NULL); + } + } + pthread_mutex_unlock(&sendq_mutex); + return NULL; +} + static void log_echo(struct sockaddr *addr, socklen_t addrlen, struct icmp *icmp, struct ip *ip, @@ -716,7 +736,7 @@ p903_receiver(void *p) int rc; struct icmp *icmp; struct ip *ip; - HOSTADDR *host; + HOSTPING *host; n = recvfrom(ping_fd, ping_buffer, buflen, 0, (struct sockaddr *) &addr, &addrlen); @@ -759,7 +779,7 @@ p903_receiver(void *p) continue; } - host = hostaddr_from_seqno(icmp->icmp_seq); + host = hostping_from_seqno(icmp->icmp_seq); if (host) { struct timeval tv_orig, tv_diff, *tp; double rtt; @@ -786,8 +806,8 @@ p903_receiver(void *p) log_echo((struct sockaddr *)&addr, addrlen, icmp, ip, n, rtt); if (host->recv_count == ping_count) - host_stat_commit(host); - hostaddr_unlock(host); + hostping_commit(host); + hostping_unlock(host); } else fatal("no host found for sequence number %d", icmp->icmp_seq); @@ -801,8 +821,8 @@ p903_scheduler(void *p) size_t i; /* Reset all statistics */ - for (i = 0; i < hostaddr_count; i++) - host_reset(hostaddr + i); + for (i = 0; i < hostping_count; i++) + hostping_reset(hostping + i); start_probe(); sleep(probe_interval); if (verbose) |