diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-03-04 21:46:00 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-03-04 21:46:00 +0200 |
commit | b4f3a0766b322ab70d98372773e22afd6ebfdb30 (patch) | |
tree | f6a308340866505b751d7bab4b04cb7440f3b825 | |
parent | e80868b1650e14ae167a15e08ff9083e9e7462b3 (diff) | |
download | ping903-b4f3a0766b322ab70d98372773e22afd6ebfdb30.tar.gz ping903-b4f3a0766b322ab70d98372773e22afd6ebfdb30.tar.bz2 |
Protect sequence number lookups and updates.
* src/ping903.h (host_stat): New member: "dup_count".
* src/pinger.c (hostping_extract_stat): Extract dup_count.
(hostping_reset): Initialize dup_count.
(get_hostping_stat): Store dup_count as "dup".
(seqno_mutex): New variable.
(hostping_from_seqno): Fix eventual null pointer dereference.
Return NULL on duplicate reply. Lock seqidx while updating it.
(send_echo): Reorganize. Lock seqidx during updates.
-rw-r--r-- | src/ping903.h | 2 | ||||
-rw-r--r-- | src/pinger.c | 96 |
2 files changed, 58 insertions, 40 deletions
diff --git a/src/ping903.h b/src/ping903.h index 1390152..ccf62b7 100644 --- a/src/ping903.h +++ b/src/ping903.h @@ -108,6 +108,7 @@ struct host_stat { struct timeval stop_tv; unsigned long xmit_count; unsigned long recv_count; + unsigned long dup_count; double tmin; /* minimum round trip time */ double tmax; /* maximum round trip time */ double avg; @@ -131,6 +132,7 @@ typedef struct hostping { struct timeval recv_tv; unsigned long xmit_count; unsigned long recv_count; + unsigned long dup_count; double tmin; /* minimum round trip time */ double tmax; /* maximum round trip time */ double tsum; /* sum of all times, for doing average */ diff --git a/src/pinger.c b/src/pinger.c index 4ab54f3..2291a48 100644 --- a/src/pinger.c +++ b/src/pinger.c @@ -270,6 +270,7 @@ hostping_extract_stat(HOSTPING *host, struct host_stat *st) sizeof(host->stat_last.stop_tv)); st->xmit_count = host->xmit_count; st->recv_count = host->recv_count; + st->dup_count = host->dup_count; st->tmin = host->tmin; st->tmax = host->tmax; if (host->recv_count > 0) { @@ -300,6 +301,7 @@ hostping_reset(HOSTPING *host) hostping_commit(host); host->xmit_count = 0; host->recv_count = 0; + host->dup_count = 0; host->tmin = HOSTPING_TMIN_INIT; host->tmax = 0; host->tsum = 0; @@ -393,6 +395,9 @@ get_hostping_stat(HOSTPING *host, struct json_value **retval) if (!(v = json_new_number(st->recv_count)) || json_object_set(obj, "recv", v)) goto err; + if (!(v = json_new_number(st->dup_count)) + || json_object_set(obj, "dup", v)) + goto err; if (!(v = json_new_number((double) 100 * (st->xmit_count - st->recv_count) / st->xmit_count)) @@ -943,14 +948,16 @@ struct seqidx { static struct seqidx *seqidx; static unsigned short next_seqno; +static pthread_mutex_t seqno_mutex = PTHREAD_MUTEX_INITIALIZER; + static int -seqno_alloc(HOSTPING *addr, struct timeval *tv) +seqno_alloc(HOSTPING *host, 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].host = host; seqidx[n].replied = 0; next_seqno = (n + 1) % MOD_SEQNO; return n; @@ -964,11 +971,21 @@ seqno_alloc(HOSTPING *addr, struct timeval *tv) 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); + HOSTPING *host; + + pthread_mutex_lock(&seqno_mutex); + host = seqidx[seq].host; + if (host) { + hostping_lock(host); + if (seqidx[seq].replied) { + host->dup_count++; + info("%s:%d: DUP!", host->name, seq); + host = NULL; + } + seqidx[seq].replied++; + } else + fatal("no host found for sequence number %d", seq); + pthread_mutex_unlock(&seqno_mutex); return host; } @@ -1102,41 +1119,42 @@ send_echo(HOSTPING *host, unsigned char *ping_buffer) ssize_t n; int seqno; + pthread_mutex_lock(&seqno_mutex); 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; - } + pthread_mutex_unlock(&seqno_mutex); - if (verbose > 2) - info("sending %zu bytes to %s, icmp_seq=%d", buflen, host->name, - seqno); - icmp_generic_encode(ping_buffer, buflen, ICMP_ECHO, ping_ident, seqno); - - hostping_lock(host); - n = sendto(ping_fd, (char *) ping_buffer, buflen, 0, - host->addr, host->addrlen); - if (n < 0) { - error("%s: sendto: %s", host->name, strerror(errno)); + if (seqno >= 0) { + 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; + + if (verbose > 2) + info("sending %zu 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 { + if (host->xmit_count == 0) + host->start_tv = host->xmit_tv; + host->xmit_count++; + xmit_total++; + if (n != buflen) + error("ping: wrote %s %zu chars, ret=%ld\n", + host->name, buflen, n); + } } else { - if (host->xmit_count == 0) - host->start_tv = host->xmit_tv; - host->xmit_count++; - xmit_total++; - if (n != buflen) - error("ping: wrote %s %zu chars, ret=%ld\n", - host->name, buflen, n); + error("can't allocate sequence number for %s", host->name); } hostping_unlock(host); } @@ -1307,9 +1325,7 @@ p903_receiver(void *p) if (host->recv_count == ping_count) hostping_commit(host); hostping_unlock(host); - } else - fatal("no host found for sequence number %d", - icmp->icmp_seq); + } } } |