aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2020-03-11 16:01:32 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2020-03-11 16:01:32 +0200
commitb8175c413c2c6eb85d8e52cb5fade398ce61f46a (patch)
treec995d1cac3af845231a72285683edba58d857315
parent99434a37b31ac9a6f5cf9ba5b773da2c4775124b (diff)
downloadping903-b8175c413c2c6eb85d8e52cb5fade398ce61f46a.tar.gz
ping903-b8175c413c2c6eb85d8e52cb5fade398ce61f46a.tar.bz2
Improve diagnostics of invalid replies. Revise log verbosity settings.
-rw-r--r--doc/ping903.811
-rw-r--r--src/pinger.c137
2 files changed, 114 insertions, 34 deletions
diff --git a/doc/ping903.8 b/doc/ping903.8
index bde1f51..9349fca 100644
--- a/doc/ping903.8
+++ b/doc/ping903.8
@@ -15,3 +15,3 @@
.\" along with Ping903. If not, see <http://www.gnu.org/licenses/>.
-.TH PING903 8 "March 10, 2020" "PING903" "System Administration"
+.TH PING903 8 "March 11, 2020" "PING903" "System Administration"
.SH NAME
@@ -141,3 +141,10 @@ Print program version, copyright information, and exit.
.B \-v
-Turn on additional logging.
+Turn on additional logging. This option can be given several times to
+request more verbose output. If given single \fB\-v\fR option, the
+program prints at the end of each probe the total number of echo
+requests sent and replies received. Two options (\fB\-vv\fR), enable
+additional diagnostics of invalid echo replies. Three options enable
+logging of each received echo reply, and four options enable verbose
+logging of each echo request sent. Notice that three or more
+\fB\-v\fR options can produce huge amount of logs.
.SH BUGS
diff --git a/src/pinger.c b/src/pinger.c
index 8bb1090..53fedfa 100644
--- a/src/pinger.c
+++ b/src/pinger.c
@@ -41,5 +41,9 @@
+/* Time in seconds between two subsequent probes. */
unsigned long probe_interval = 60;
+/* Time between two subsequent echo requests within the same probe. */
unsigned long ping_interval = 1;
+/* Number of echo requests per probe */
unsigned long ping_count = 10;
+/* Number of unanswered echo requests after which the host is declared dead. */
unsigned long ping_tolerance = 3;
@@ -238,3 +242,2 @@ static int check_host(char const *name);
static int update_add(UPDATE_TYPE t, void *data);
-static void update_commit(void);
@@ -967,4 +970,6 @@ static int send_p;
-static unsigned xmit_total;
-static unsigned recv_total;
+static unsigned long probe_num; /* Ordinal number of the current probe. */
+/* Totals for the current probe: */
+static unsigned xmit_total; /* Number of requests transmitted. */
+static unsigned recv_total; /* Number of replies received. */
@@ -976,21 +981,35 @@ static unsigned char *data_buffer;
+/* Ping identifier (for the icmp_id member of struct icmp) */
static int ping_ident;
+/* Constants for sequence number database management */
+
+/* Max. time in seconds after which a sequence database entry can be reused. */
#define MAX_PING_TIMEOUT 10
+
enum {
- MAX_SEQNO = USHRT_MAX,
- MOD_SEQNO = MAX_SEQNO + 1
+ MAX_SEQNO = USHRT_MAX, /* Max. value for the sequence number */
+ MOD_SEQNO = MAX_SEQNO + 1 /* Modulus for computing next sequence
+ number. */
};
+/* Sequence number index entry. */
struct seqidx {
- HOSTPING *host;
- struct timeval tv;
- int ping_num;
+ HOSTPING *host; /* Associated host. */
+ struct timeval tv; /* Time the echo was sent. */
+ unsigned long probe_num; /* Number of the probe within which the
+ echo was sent. */
+ int ping_num; /* Number of echo request within the probe. */
};
-static struct seqidx *seqidx;
-static unsigned short next_seqno;
+static struct seqidx *seqidx; /* Sequence number database. */
+static unsigned short next_seqno; /* Next sequence number. */
+/* Protect simultaneous access to seqidx. */
static pthread_mutex_t seqno_mutex = PTHREAD_MUTEX_INITIALIZER;
+/* Allocate and return the sequence number for the given host and
+ * transmission time.
+ * Return negative value if the number cannot be allocated.
+ */
static int
@@ -1003,2 +1022,3 @@ seqno_alloc(HOSTPING *host, struct timeval *tv)
seqidx[n].host = host;
+ seqidx[n].probe_num = probe_num;
seqidx[n].ping_num = host->xmit_count;
@@ -1013,2 +1033,72 @@ seqno_alloc(HOSTPING *host, struct timeval *tv)
+/* Check the validity of the echo reply SEQ. Return 0 if the reply is
+ * valid, -1 otherwise.
+ * This function is called when both the seqidx array and the HOSTPING
+ * structure associated with SEQ are locked.
+ */
+static int
+check_reply(int seq)
+{
+ int n = seqidx[seq].ping_num;
+ HOSTPING *host = seqidx[seq].host;
+
+ if (seqidx[seq].probe_num != probe_num) {
+ /* Case 1.
+ * A latecomer reply, which arrived after its probe round
+ * was committed (see hostping_commit).
+ */
+ if (verbose > 1)
+ info("%s: reply for discarded echo request #%d, "
+ "seqno %d; probe_num=%lu, current=%lu",
+ host->name, n, seq, seqidx[seq].probe_num,
+ probe_num);
+ } else if (host->xmit_count == 0) {
+ /* Case 2.
+ * A reply came while no echo requests were transmitted yet.
+ */
+ info("%s: stray reply #%d, seqno %d; probe_num=%lu",
+ host->name, n, seq, probe_num);
+ } else if (n >= 0 && n < ping_count) {
+ if (n > host->xmit_count) {
+ /* Case 3.
+ * Similar to 2, except that some echoes were sent.
+ */
+ error("%s: phantom reply #%d, seqno %d; xmit_count=%lu",
+ host->name, n, seq, host->xmit_count);
+ } else if (++host->nreply[n] > 1) {
+ /* Case 4.
+ * Duplicate reply.
+ */
+ host->dup_count++;
+ info("%s: duplicate reply for echo #%d, seqno %d",
+ host->name, n, seq);
+ } else if (host->recv_count == host->xmit_count) {
+ /* Case 5.
+ * Similar to 2 and 3.
+ * Each echo request was replied to, and yet another
+ * reply arrived, which is not a duplicate.
+ */
+ error("%s: unexpected reply #%d, seqno %d; "
+ "xmit_count=recv_count=%lu",
+ host->name, n, seq, host->xmit_count);
+ }
+ /* Case 6.
+ * This is a valid reply.
+ */
+ return 0;
+ } else {
+ /* Case 7.
+ * A reply with impossible echo request number.
+ * This one should not happen indeed.
+ */
+ error("%s: reply for unregistered echo #%d, seqno %d",
+ host->name, n, seq);
+ }
+ return -1;
+}
+
+/* Given an echo sequence number, return the locked HOSTPING structure
+ * associated with this echo request, or NULL if the reply is
+ * invalid.
+ */
static HOSTPING *
@@ -1021,25 +1111,7 @@ hostping_from_seqno(int seq)
if (host) {
- int n;
- HOSTPING *orig = host;
-
hostping_lock(host);
- n = seqidx[seq].ping_num;
- if (n >= 0 && n < ping_count) {
- if (++host->nreply[n] > 1) {
- host->dup_count++;
- info("%s: duplicate reply for echo #%d, seqno %d",
- host->name, n, seq);
- host = NULL;
- } else if (host->recv_count == host->xmit_count) {
- error("%s: unexpected reply #%d, seqno %d",
- host->name, n, seq);
- host = NULL;
- }
- } else {
- error("%s: duplicate reply for unregistered echo #%d, seqno %d",
- host->name, n, seq);
+ if (check_reply(seq)) {
+ hostping_unlock(host);
host = NULL;
}
- if (!host)
- hostping_unlock(orig);
} else
@@ -1194,3 +1266,3 @@ send_echo(HOSTPING *host, unsigned char *ping_buffer)
- if (verbose > 2)
+ if (verbose > 3)
info("sending %zu bytes to %s, icmp_seq=%d",
@@ -1380,3 +1452,3 @@ p903_receiver(void *p)
- if (verbose > 1)
+ if (verbose > 2)
log_echo((struct sockaddr *)&addr, addrlen,
@@ -1482,2 +1554,3 @@ p903_scheduler(void *p)
+ probe_num++;
send_p = 1;

Return to:

Send suggestions and report system problems to the System administrator.