aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-02-22 16:07:13 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-02-22 16:07:13 +0200
commit6097958d5c2652ec6e98d813e1627d5cb822da19 (patch)
treeb195aa773bd0ba139466798594d2dbf9e9c7ec2d
parent69bc53b8aa9ce26329603ac25f7cfb5d028845dc (diff)
downloadping903-6097958d5c2652ec6e98d813e1627d5cb822da19.tar.gz
ping903-6097958d5c2652ec6e98d813e1627d5cb822da19.tar.bz2
Reorganize host array and functions
-rw-r--r--src/config.c13
-rw-r--r--src/ping903.h9
-rw-r--r--src/pinger.c714
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)

Return to:

Send suggestions and report system problems to the System administrator.