aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-03-04 21:46:00 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-03-04 21:46:00 +0200
commitb4f3a0766b322ab70d98372773e22afd6ebfdb30 (patch)
treef6a308340866505b751d7bab4b04cb7440f3b825
parente80868b1650e14ae167a15e08ff9083e9e7462b3 (diff)
downloadping903-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.h2
-rw-r--r--src/pinger.c96
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);
+ }
}
}

Return to:

Send suggestions and report system problems to the System administrator.