summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/hoststated/check_http.c64
-rw-r--r--usr.sbin/hoststated/check_icmp.c376
-rw-r--r--usr.sbin/hoststated/check_send_expect.c77
-rw-r--r--usr.sbin/hoststated/check_tcp.c25
-rw-r--r--usr.sbin/hoststated/hce.c83
-rw-r--r--usr.sbin/hoststated/hoststated.c23
-rw-r--r--usr.sbin/hoststated/hoststated.h43
-rw-r--r--usr.sbin/relayd/check_icmp.c376
-rw-r--r--usr.sbin/relayd/check_tcp.c25
-rw-r--r--usr.sbin/relayd/hce.c83
-rw-r--r--usr.sbin/relayd/relayd.c23
-rw-r--r--usr.sbin/relayd/relayd.h43
12 files changed, 616 insertions, 625 deletions
diff --git a/usr.sbin/hoststated/check_http.c b/usr.sbin/hoststated/check_http.c
index 4e56f321ca9..d53f5b0b3fa 100644
--- a/usr.sbin/hoststated/check_http.c
+++ b/usr.sbin/hoststated/check_http.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_http.c,v 1.8 2007/01/09 14:11:23 reyk Exp $ */
+/* $OpenBSD: check_http.c,v 1.9 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
*
@@ -19,6 +19,7 @@
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/param.h>
+
#include <net/if.h>
#include <sha1.h>
#include <limits.h>
@@ -28,6 +29,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
+#include <errno.h>
#include "hoststated.h"
@@ -98,8 +100,6 @@ http_read(int s, short event, void *arg)
{
ssize_t br;
char rbuf[SMALL_READ_BUF_SIZE];
- struct timeval tv;
- struct timeval tv_now;
struct ctl_tcp_event *cte = arg;
if (event == EV_TIMEOUT) {
@@ -109,7 +109,14 @@ http_read(int s, short event, void *arg)
return;
}
br = read(s, rbuf, sizeof(rbuf));
- if (br == 0) {
+ if (br == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto retry;
+ cte->host->up = HOST_DOWN;
+ buf_free(cte->buf);
+ hce_notify_done(cte->host, "http_read: read failed");
+ return;
+ } else if (br == 0) {
cte->host->up = HOST_DOWN;
switch (cte->table->check) {
case CHECK_HTTP_CODE:
@@ -123,30 +130,24 @@ http_read(int s, short event, void *arg)
}
buf_free(cte->buf);
hce_notify_done(cte->host, "http_read: connection closed");
- } else if (br == -1) {
- cte->host->up = HOST_DOWN;
- buf_free(cte->buf);
- hce_notify_done(cte->host, "http_read: read failed");
- } else {
- buf_add(cte->buf, rbuf, br);
- bcopy(&cte->table->timeout, &tv, sizeof(tv));
- if (gettimeofday(&tv_now, NULL))
- fatal("http_read: gettimeofday");
- timersub(&tv_now, &cte->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(s, EV_READ|EV_TIMEOUT, http_read, cte, &tv);
+ return;
}
+
+ buf_add(cte->buf, rbuf, br);
+
+ retry:
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, http_read,
+ &cte->tv_start, &cte->table->timeout, cte);
}
void
-send_http_request(struct ctl_tcp_event *cte)
+send_http_request(int s, short event, void *arg)
{
- int bs;
- int pos;
- int len;
- char *req;
- struct timeval tv;
- struct timeval tv_now;
+ struct ctl_tcp_event *cte = (struct ctl_tcp_event *)arg;
+ int bs;
+ int pos;
+ int len;
+ char *req;
switch (cte->table->check) {
case CHECK_HTTP_CODE:
@@ -169,7 +170,9 @@ send_http_request(struct ctl_tcp_event *cte)
*/
do {
bs = write(cte->s, req + pos, len);
- if (bs <= 0) {
+ if (bs == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto retry;
log_warnx("send_http_request: cannot send request");
cte->host->up = HOST_DOWN;
hce_notify_done(cte->host, "send_http_request: write");
@@ -183,10 +186,11 @@ send_http_request(struct ctl_tcp_event *cte)
if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
fatalx("send_http_request: cannot create dynamic buffer");
- bcopy(&cte->table->timeout, &tv, sizeof(tv));
- if (gettimeofday(&tv_now, NULL))
- fatal("send_http_request: gettimeofday");
- timersub(&tv_now, &cte->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(cte->s, EV_READ|EV_TIMEOUT, http_read, cte, &tv);
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, http_read,
+ &cte->tv_start, &cte->table->timeout, cte);
+ return;
+
+ retry:
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, send_http_request,
+ &cte->tv_start, &cte->table->timeout, cte);
}
diff --git a/usr.sbin/hoststated/check_icmp.c b/usr.sbin/hoststated/check_icmp.c
index fb7692eac5e..e44c70c2c1b 100644
--- a/usr.sbin/hoststated/check_icmp.c
+++ b/usr.sbin/hoststated/check_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_icmp.c,v 1.9 2007/01/09 03:32:56 reyk Exp $ */
+/* $OpenBSD: check_icmp.c,v 1.10 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -33,53 +33,86 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
+#include <err.h>
#include "hoststated.h"
-int icmp6_checks_done(struct ctl_icmp_event *);
-int icmp4_checks_done(struct ctl_icmp_event *);
-void send_icmp6(struct ctl_icmp_event *, struct host *);
-void send_icmp4(struct ctl_icmp_event *, struct host *);
-void recv_icmp6(int, short, void *);
-void recv_icmp4(int, short, void *);
+void icmp_setup(struct hoststated *, struct ctl_icmp_event *, int);
+void check_icmp_add(struct ctl_icmp_event *, int, struct timeval *,
+ void (*)(int, short, void *));
+int icmp_checks_done(struct ctl_icmp_event *);
+void icmp_checks_timeout(struct ctl_icmp_event *, const char *);
+void send_icmp(int, short, void *);
+void recv_icmp(int, short, void *);
int in_cksum(u_short *, int);
void
-schedule_icmp(struct ctl_icmp_event *cie, struct table *table)
+icmp_setup(struct hoststated *env, struct ctl_icmp_event *cie, int af)
{
- struct host *host;
+ int proto = IPPROTO_ICMP;
+
+ if (af == AF_INET6)
+ proto = IPPROTO_ICMPV6;
+ if ((cie->s = socket(af, SOCK_RAW, proto)) < 0)
+ err(1, "icmp_init: socket");
+ session_socket_blockmode(cie->s, BM_NONBLOCK);
+ cie->env = env;
+ cie->af = af;
+}
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- host->last_up = host->up;
- host->flags &= ~F_CHECK_DONE;
- if (((struct sockaddr *)&host->ss)->sa_family == AF_INET) {
- send_icmp4(cie, host);
- } else {
- send_icmp6(cie, host);
- }
- }
+void
+icmp_init(struct hoststated *env)
+{
+ icmp_setup(env, &env->icmp_send, AF_INET);
+ icmp_setup(env, &env->icmp_recv, AF_INET);
+ icmp_setup(env, &env->icmp6_send, AF_INET6);
+ icmp_setup(env, &env->icmp6_recv, AF_INET6);
+ env->id = getpid() & 0xffff;
}
void
-check_icmp(struct ctl_icmp_event *cie)
+schedule_icmp(struct hoststated *env, struct host *host)
{
- struct timeval tv;
+ host->last_up = host->up;
+ host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
- if (gettimeofday(&cie->tv_start, NULL))
- fatal("check_icmp: gettimeofday");
+ if (((struct sockaddr *)&host->ss)->sa_family == AF_INET)
+ env->has_icmp = 1;
+ else
+ env->has_icmp6 = 1;
+}
+
+void
+check_icmp_add(struct ctl_icmp_event *cie, int flags, struct timeval *start,
+ void (*fn)(int, short, void *))
+{
+ struct timeval tv;
+
+ if (start != NULL)
+ bcopy(start, &cie->tv_start, sizeof(cie->tv_start));
bcopy(&cie->env->timeout, &tv, sizeof(tv));
- if (cie->has_icmp4)
- event_once(cie->icmp_sock, EV_READ|EV_TIMEOUT,
- recv_icmp4, cie, &tv);
- if (cie->has_icmp6)
- event_once(cie->icmp6_sock, EV_READ|EV_TIMEOUT,
- recv_icmp6, cie, &tv);
+ if (gettimeofday(&cie->tv_start, NULL))
+ fatal("check_icmp_add: gettimeofday");
+ event_del(&cie->ev);
+ event_set(&cie->ev, cie->s, EV_TIMEOUT|flags, fn, cie);
+ event_add(&cie->ev, &tv);
+}
+
+void
+check_icmp(struct hoststated *env, struct timeval *tv)
+{
+ if (env->has_icmp) {
+ check_icmp_add(&env->icmp_recv, EV_READ, tv, recv_icmp);
+ check_icmp_add(&env->icmp_send, EV_WRITE, tv, send_icmp);
+ }
+ if (env->has_icmp6) {
+ check_icmp_add(&env->icmp6_recv, EV_READ, tv, recv_icmp);
+ check_icmp_add(&env->icmp6_send, EV_WRITE, tv, send_icmp);
+ }
}
int
-icmp6_checks_done(struct ctl_icmp_event *cie)
+icmp_checks_done(struct ctl_icmp_event *cie)
{
struct table *table;
struct host *host;
@@ -88,8 +121,7 @@ icmp6_checks_done(struct ctl_icmp_event *cie)
if (table->flags & F_DISABLE || table->check != CHECK_ICMP)
continue;
TAILQ_FOREACH(host, &table->hosts, entry) {
- if (((struct sockaddr *)&host->ss)->sa_family !=
- AF_INET6)
+ if (((struct sockaddr *)&host->ss)->sa_family != cie->af)
continue;
if (!(host->flags & F_CHECK_DONE))
return (0);
@@ -98,8 +130,8 @@ icmp6_checks_done(struct ctl_icmp_event *cie)
return (1);
}
-int
-icmp4_checks_done(struct ctl_icmp_event *cie)
+void
+icmp_checks_timeout(struct ctl_icmp_event *cie, const char *msg)
{
struct table *table;
struct host *host;
@@ -108,220 +140,156 @@ icmp4_checks_done(struct ctl_icmp_event *cie)
if (table->flags & F_DISABLE || table->check != CHECK_ICMP)
continue;
TAILQ_FOREACH(host, &table->hosts, entry) {
- if (((struct sockaddr *)&host->ss)->sa_family !=
- AF_INET)
+ if (((struct sockaddr *)&host->ss)->sa_family != cie->af)
continue;
- if (!(host->flags & F_CHECK_DONE)) {
- return (0);
- }
+ if (!(host->flags & F_CHECK_DONE))
+ host->up = HOST_DOWN;
+ hce_notify_done(host, msg);
}
}
- return (1);
}
void
-send_icmp6(struct ctl_icmp_event *cie, struct host *host)
+send_icmp(int s, short event, void *arg)
{
+ struct ctl_icmp_event *cie = (struct ctl_icmp_event *)arg;
+ struct table *table;
+ struct host *host;
struct sockaddr *to;
- struct icmp6_hdr *icp;
- ssize_t i;
+ struct icmp *icp;
+ struct icmp6_hdr *icp6;
+ ssize_t r;
u_char packet[ICMP_BUF_SIZE];
+ socklen_t slen;
+ int i = 0;
- cie->has_icmp6 = 1;
- to = (struct sockaddr *)&host->ss;
- bzero(&packet, sizeof(packet));
- icp = (struct icmp6_hdr *)packet;
- icp->icmp6_type = ICMP6_ECHO_REQUEST;
- icp->icmp6_code = 0;
- icp->icmp6_seq = 1;
- icp->icmp6_id = getpid() & 0xffff;
-
- memcpy((packet + sizeof(*icp)), &host->id, sizeof(host->id));
-
- i = sendto(cie->icmp6_sock, packet, sizeof(packet), 0, to,
- sizeof(struct sockaddr_in6));
- if (i < 0 || i != sizeof(packet)) {
- host->up = HOST_DOWN;
- hce_notify_done(host, "send_icmp6: cannot send");
+ if (event == EV_TIMEOUT) {
+ icmp_checks_timeout(cie, "send_icmp: timeout");
return;
}
-}
-
-void
-send_icmp4(struct ctl_icmp_event *cie, struct host *host)
-{
- struct sockaddr *to;
- struct icmp *icp;
- ssize_t i;
- u_char packet[ICMP_BUF_SIZE];
- cie->has_icmp4 = 1;
- to = (struct sockaddr *)&host->ss;
bzero(&packet, sizeof(packet));
icp = (struct icmp *)packet;
- icp->icmp_type = ICMP_ECHO;
- icp->icmp_code = 0;
- icp->icmp_seq = htons(1);
- icp->icmp_id = htons(getpid() & 0xffff);
- icp->icmp_cksum = 0;
-
- memcpy(icp->icmp_data, &host->id, sizeof(host->id));
- icp->icmp_cksum = in_cksum((u_short *)icp, sizeof(packet));
-
- i = sendto(cie->icmp_sock, packet, sizeof(packet), 0, to,
- sizeof(struct sockaddr_in));
- if (i < 0 || i != sizeof(packet)) {
- host->up = HOST_DOWN;
- hce_notify_done(host, "send_icmp4: cannot send");
+ icp6 = (struct icmp6_hdr *)packet;
+ if (cie->af == AF_INET) {
+ icp->icmp_type = ICMP_ECHO;
+ icp->icmp_code = 0;
+ icp->icmp_id = htons(cie->env->id);
+ icp->icmp_cksum = 0;
+ slen = sizeof(struct sockaddr_in);
+ } else {
+ icp6->icmp6_type = ICMP6_ECHO_REQUEST;
+ icp6->icmp6_code = 0;
+ icp6->icmp6_cksum = 0;
+ icp6->icmp6_id = htons(cie->env->id);
+ slen = sizeof(struct sockaddr_in6);
}
-}
-void
-recv_icmp6(int s, short event, void *arg)
-{
- struct ctl_icmp_event *cie = arg;
- u_char packet[ICMP_BUF_SIZE];
- socklen_t len;
- struct sockaddr_storage ss;
- struct icmp6_hdr *icp;
- struct host *host;
- struct table *table;
- ssize_t i;
- objid_t id;
- struct timeval tv;
- struct timeval tv_now;
-
- if (event == EV_TIMEOUT) {
- /*
- * mark all hosts which have not responded yet as down.
- */
- TAILQ_FOREACH(table, &cie->env->tables, entry) {
- if (table->check != CHECK_ICMP ||
- table->flags & F_DISABLE)
+ TAILQ_FOREACH(table, &cie->env->tables, entry) {
+ if (table->check != CHECK_ICMP || table->flags & F_DISABLE)
+ continue;
+ TAILQ_FOREACH(host, &table->hosts, entry) {
+ if (host->flags & (F_DISABLE | F_CHECK_SENT))
continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- if (((struct sockaddr *)&host->ss)->sa_family
- != AF_INET6)
- continue;
- if (!(host->flags & F_CHECK_DONE)) {
- host->up = HOST_DOWN;
- }
+ if (((struct sockaddr *)&host->ss)->sa_family != cie->af)
+ continue;
+ i++;
+ to = (struct sockaddr *)&host->ss;
+ if (cie->af == AF_INET) {
+ icp->icmp_seq = htons(i);
+ icp->icmp_cksum = 0;
+ memcpy(icp->icmp_data, &host->id,
+ sizeof(host->id));
+ icp->icmp_cksum = in_cksum((u_short *)icp,
+ sizeof(packet));
+ } else {
+ icp6->icmp6_seq = htons(i);
+ icp6->icmp6_cksum = 0;
+ memcpy(packet + sizeof(*icp6), &host->id,
+ sizeof(host->id));
+ icp6->icmp6_cksum = in_cksum((u_short *)icp6,
+ sizeof(packet));
}
+
+ r = sendto(s, packet, sizeof(packet), 0, to, slen);
+ if (r == -1) {
+ if (errno == EAGAIN && errno == EINTR)
+ goto retry;
+ host->flags |= F_CHECK_SENT|F_CHECK_DONE;
+ host->up = HOST_DOWN;
+ } else if (r != sizeof(packet))
+ goto retry;
+ host->flags |= F_CHECK_SENT;
}
- return;
- }
- bzero(&packet, sizeof(packet));
- bzero(&ss, sizeof(ss));
- len = sizeof(struct sockaddr_in6);
- i = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &len);
- if (i < 0 || i != sizeof(packet)) {
- log_warn("recv_icmp6: did not receive valid ping");
- return;
}
- icp = (struct icmp6_hdr *)(packet);
- memcpy(&id, (packet + sizeof(*icp)), sizeof(id));
- host = host_find(cie->env, id);
- if (host == NULL)
- log_warn("recv_icmp6: ping for unknown host received");
- if (bcmp(&ss, &host->ss, len)) {
- log_warnx("recv_icmp6: forged icmp packet ?");
- return;
- }
- if (icp->icmp6_id != (getpid() & 0xffff)) {
- log_warnx("recv_icmp6: did not receive valid ident");
- host->up = HOST_DOWN;
- } else
- host->up = HOST_UP;
- hce_notify_done(host, "recv_icmp6: final");
- if (icmp6_checks_done(cie))
- return;
- if (gettimeofday(&tv_now, NULL))
- fatal("recv_icmp6: gettimeofday");
- bcopy(&cie->env->timeout, &tv, sizeof(tv));
- timersub(&tv_now, &cie->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(cie->icmp6_sock, EV_READ|EV_TIMEOUT, recv_icmp6, cie, &tv);
+
+ return;
+
+ retry:
+ event_again(&cie->ev, s, EV_TIMEOUT|EV_WRITE, send_icmp,
+ &cie->tv_start, &cie->env->timeout, cie);
}
void
-recv_icmp4(int s, short event, void *arg)
+recv_icmp(int s, short event, void *arg)
{
- socklen_t len;
- struct icmp *icp;
- struct ctl_icmp_event *cie = arg;
+ struct ctl_icmp_event *cie = (struct ctl_icmp_event *)arg;
u_char packet[ICMP_BUF_SIZE];
+ socklen_t slen;
+ struct sockaddr_storage ss;
+ struct icmp *icp;
+ struct icmp6_hdr *icp6;
+ u_int16_t icpid;
struct host *host;
- struct table *table;
- ssize_t i;
+ ssize_t r;
objid_t id;
- struct timeval tv;
- struct timeval tv_now;
- struct sockaddr_storage ss;
if (event == EV_TIMEOUT) {
- /*
- * mark all hosts which have not responded yet as down.
- */
- TAILQ_FOREACH(table, &cie->env->tables, entry) {
- if (table->check != CHECK_ICMP ||
- table->flags & F_DISABLE)
- continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- if (((struct sockaddr *)&host->ss)->sa_family
- != AF_INET)
- continue;
- if (!(host->flags & F_CHECK_DONE)) {
- host->up = HOST_DOWN;
- }
- }
- }
+ icmp_checks_timeout(cie, NULL);
return;
}
- len = sizeof(struct sockaddr_in);
bzero(&packet, sizeof(packet));
bzero(&ss, sizeof(ss));
- i = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &len);
- if (i < 0 || i != sizeof(packet)) {
- log_warn("recv_icmp4: did not receive valid ping");
- return;
+
+ r = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &slen);
+ if (r == -1 || r != ICMP_BUF_SIZE) {
+ if (r == -1 && errno != EAGAIN && errno != EINTR)
+ log_debug("recv_icmp: receive error");
+ goto retry;
}
- icp = (struct icmp *)(packet + sizeof(struct ip));
- memcpy(&id, icp->icmp_data, sizeof(id));
+ if (cie->af == AF_INET) {
+ icp = (struct icmp *)(packet + sizeof(struct ip));
+ icpid = ntohs(icp->icmp_id);
+ memcpy(&id, icp->icmp_data, sizeof(id));
+ } else {
+ icp6 = (struct icmp6_hdr *)packet;
+ icpid = ntohs(icp6->icmp6_id);
+ memcpy(&id, packet + sizeof(*icp6), sizeof(id));
+ }
+ if (icpid != cie->env->id)
+ goto retry;
host = host_find(cie->env, id);
if (host == NULL) {
- log_warnx("recv_icmp4: received ping for unknown host");
- return;
+ log_warn("recv_icmp: ping for unknown host received");
+ goto retry;
}
- if (bcmp(&ss, &host->ss, len)) {
- log_warnx("recv_icmp4: forged icmp packet ?");
- return;
+ if (bcmp(&ss, &host->ss, slen)) {
+ log_warnx("recv_icmp: forged icmp packet?");
+ goto retry;
}
- if (ntohs(icp->icmp_id) != (getpid() & 0xffff)) {
- log_warnx("recv_icmp4: did not receive valid ident");
- host->up = HOST_DOWN;
- } else
- host->up = HOST_UP;
+ host->up = HOST_UP;
host->flags |= F_CHECK_DONE;
- if (icmp4_checks_done(cie)) {
- hce_notify_done(host, "recv_icmp4: all done");
- return;
- }
- hce_notify_done(host, "recv_icmp4: host");
+ hce_notify_done(host, "recv_icmp: done");
- if (gettimeofday(&tv_now, NULL))
- fatal("recv_icmp4: gettimeofday");
+ if (icmp_checks_done(cie))
+ return;
- bcopy(&cie->env->timeout, &tv, sizeof(tv));
- timersub(&tv_now, &cie->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(cie->icmp_sock, EV_READ|EV_TIMEOUT, recv_icmp4, cie, &tv);
+ retry:
+ event_again(&cie->ev, s, EV_TIMEOUT|EV_READ, recv_icmp,
+ &cie->tv_start, &cie->env->timeout, cie);
}
/* in_cksum from ping.c --
diff --git a/usr.sbin/hoststated/check_send_expect.c b/usr.sbin/hoststated/check_send_expect.c
index 528dd8b1fc1..81c9519b567 100644
--- a/usr.sbin/hoststated/check_send_expect.c
+++ b/usr.sbin/hoststated/check_send_expect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_send_expect.c,v 1.3 2007/01/09 00:45:32 deraadt Exp $ */
+/* $OpenBSD: check_send_expect.c,v 1.4 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
*
@@ -19,6 +19,7 @@
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/param.h>
+
#include <net/if.h>
#include <limits.h>
#include <event.h>
@@ -28,6 +29,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <fnmatch.h>
+#include <errno.h>
#include "hoststated.h"
@@ -49,7 +51,7 @@ se_validate(struct ctl_tcp_event *cte)
if (fnmatch(cte->table->exbuf, cte->buf->buf, 0) == 0)
cte->host->up = HOST_UP;
else
- cte->host->up = HOST_DOWN;
+ cte->host->up = HOST_UNKNOWN;
/*
* go back to original position.
@@ -62,8 +64,6 @@ se_read(int s, short event, void *arg)
{
ssize_t br;
char rbuf[SMALL_READ_BUF_SIZE];
- struct timeval tv;
- struct timeval tv_now;
struct ctl_tcp_event *cte = arg;
if (event == EV_TIMEOUT) {
@@ -72,42 +72,44 @@ se_read(int s, short event, void *arg)
hce_notify_done(cte->host, "se_read: timeout");
return;
}
+
br = read(s, rbuf, sizeof(rbuf));
- log_debug("se_read: %d bytes read", br);
- if (br == 0) {
+ if (br == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto retry;
+ cte->host->up = HOST_DOWN;
+ buf_free(cte->buf);
+ hce_notify_done(cte->host, "se_read: read failed");
+ return;
+ } else if (br == 0) {
cte->host->up = HOST_DOWN;
se_validate(cte);
buf_free(cte->buf);
hce_notify_done(cte->host, "se_read: connection closed");
- } else if (br == -1) {
- cte->host->up = HOST_DOWN;
+ return;
+ }
+
+ buf_add(cte->buf, rbuf, br);
+ se_validate(cte);
+ if (cte->host->up == HOST_UP) {
buf_free(cte->buf);
- hce_notify_done(cte->host, "se_read: read failed");
- } else {
- buf_add(cte->buf, rbuf, br);
- bcopy(&cte->table->timeout, &tv, sizeof(tv));
- if (gettimeofday(&tv_now, NULL))
- fatal("se_read: gettimeofday");
- timersub(&tv_now, &cte->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- se_validate(cte);
- if (cte->host->up == HOST_UP) {
- buf_free(cte->buf);
- hce_notify_done(cte->host, NULL);
- } else
- event_once(s, EV_READ|EV_TIMEOUT, se_read, cte, &tv);
+ hce_notify_done(cte->host, "se_read: done");
+ return;
}
+
+ retry:
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, se_read,
+ &cte->tv_start, &cte->table->timeout, cte);
}
void
-start_send_expect(struct ctl_tcp_event *cte)
+start_send_expect(int s, short event, void *arg)
{
- int bs;
- int pos;
- int len;
- char *req;
- struct timeval tv;
- struct timeval tv_now;
+ struct ctl_tcp_event *cte = (struct ctl_tcp_event *)arg;
+ int bs;
+ int pos;
+ int len;
+ char *req;
req = cte->table->sendbuf;
pos = 0;
@@ -115,7 +117,9 @@ start_send_expect(struct ctl_tcp_event *cte)
if (len) {
do {
bs = write(cte->s, req + pos, len);
- if (bs <= 0) {
+ if (bs == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto retry;
log_warnx("send_se_data: cannot send");
cte->host->up = HOST_DOWN;
hce_notify_done(cte->host,
@@ -130,12 +134,11 @@ start_send_expect(struct ctl_tcp_event *cte)
if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
fatalx("send_se_data: cannot create dynamic buffer");
- log_debug("start_send_expect: reading");
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, se_read,
+ &cte->tv_start, &cte->table->timeout, cte);
+ return;
- bcopy(&cte->table->timeout, &tv, sizeof(tv));
- if (gettimeofday(&tv_now, NULL))
- fatal("start_send_expect: gettimeofday");
- timersub(&tv_now, &cte->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(cte->s, EV_READ|EV_TIMEOUT, se_read, cte, &tv);
+ retry:
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, start_send_expect,
+ &cte->tv_start, &cte->table->timeout, cte);
}
diff --git a/usr.sbin/hoststated/check_tcp.c b/usr.sbin/hoststated/check_tcp.c
index 86b8244093f..fc365c18d9d 100644
--- a/usr.sbin/hoststated/check_tcp.c
+++ b/usr.sbin/hoststated/check_tcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_tcp.c,v 1.8 2007/01/09 00:45:32 deraadt Exp $ */
+/* $OpenBSD: check_tcp.c,v 1.9 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -71,17 +71,16 @@ check_tcp(struct ctl_tcp_event *cte)
if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
goto bad;
+ bcopy(&cte->table->timeout, &tv, sizeof(tv));
if (connect(s, (struct sockaddr *)&cte->host->ss, len) == -1) {
if (errno != EINPROGRESS)
goto bad;
- } else {
+ } else
cte->host->up = HOST_UP;
- tcp_host_up(s, cte);
- return;
- }
- bcopy(&cte->table->timeout, &tv, sizeof(tv));
- event_once(s, EV_TIMEOUT|EV_WRITE, tcp_write, cte, &tv);
+ event_set(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_write, cte);
+ event_add(&cte->ev, &tv);
return;
+
bad:
close(s);
cte->host->up = HOST_DOWN;
@@ -102,7 +101,7 @@ tcp_write(int s, short event, void *arg)
len = sizeof(err);
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len))
fatal("tcp_write: getsockopt");
- if (err)
+ if (err != 0)
cte->host->up = HOST_DOWN;
else
cte->host->up = HOST_UP;
@@ -123,16 +122,18 @@ tcp_host_up(int s, struct ctl_tcp_event *cte)
switch (cte->table->check) {
case CHECK_TCP:
close(s);
- hce_notify_done(cte->host, "tcp_write: success");
+ hce_notify_done(cte->host, "tcp_host_up: success");
break;
case CHECK_HTTP_CODE:
case CHECK_HTTP_DIGEST:
- send_http_request(cte);
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, send_http_request,
+ &cte->tv_start, &cte->table->timeout, cte);
break;
case CHECK_SEND_EXPECT:
- start_send_expect(cte);
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, start_send_expect,
+ &cte->tv_start, &cte->table->timeout, cte);
break;
default:
- fatalx("tcp_write: unhandled check type");
+ fatalx("tcp_host_up: unhandled check type");
}
}
diff --git a/usr.sbin/hoststated/hce.c b/usr.sbin/hoststated/hce.c
index c951b5ba8bb..012a5dbf63f 100644
--- a/usr.sbin/hoststated/hce.c
+++ b/usr.sbin/hoststated/hce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hce.c,v 1.9 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: hce.c,v 1.10 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -82,12 +82,6 @@ hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
env = x_env;
- /* this is needed for icmp tests */
- if ((env->icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
- err(1, "socket");
- if ((env->icmp6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
- err(1, "socket");
-
if ((pw = getpwnam(HOSTSTATED_USER)) == NULL)
fatal("hce: getpwnam");
@@ -99,15 +93,14 @@ hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
setproctitle("host check engine");
hoststated_process = PROC_HCE;
+ /* this is needed for icmp tests */
+ icmp_init(env);
+
if (setgroups(1, &pw->pw_gid) ||
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
fatal("hce: can't drop privileges");
- env->cie.icmp_sock = env->icmp_sock;
- env->cie.icmp6_sock = env->icmp6_sock;
- env->cie.env = env;
-
event_init();
signal_set(&ev_sigint, SIGINT, hce_sig_handler, NULL);
@@ -137,11 +130,10 @@ hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
ibuf_main->handler, ibuf_main);
event_add(&ibuf_main->ev, NULL);
- evtimer_set(&env->ev, hce_launch_checks, NULL);
- bcopy(&env->interval, &tv, sizeof(tv));
+ evtimer_set(&env->ev, hce_launch_checks, env);
+ bzero(&tv, sizeof(tv));
evtimer_add(&env->ev, &tv);
- hce_launch_checks(0, 0, NULL);
event_dispatch();
hce_shutdown();
@@ -154,32 +146,52 @@ hce_launch_checks(int fd, short event, void *arg)
{
struct host *host;
struct table *table;
+ struct timeval tv;
+
+ log_debug("hce_launch_checks: scheduled");
+
+ /*
+ * notify pfe checks are done and schedule next check
+ */
+ imsg_compose(ibuf_pfe, IMSG_SYNC, 0, 0, NULL, 0);
+ TAILQ_FOREACH(table, &env->tables, entry) {
+ TAILQ_FOREACH(host, &table->hosts, entry) {
+ host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
+ event_del(&host->cte.ev);
+ }
+ }
+
+ if (gettimeofday(&tv, NULL))
+ fatal("hce_launch_checks: gettimeofday");
TAILQ_FOREACH(table, &env->tables, entry) {
if (table->flags & F_DISABLE)
continue;
if (table->check == CHECK_NOCHECK)
fatalx("hce_launch_checks: unknown check type");
- if (table->check == CHECK_ICMP) {
- schedule_icmp(&env->cie, table);
- continue;
- }
- /*
- * tcp type checks follow
- */
+
TAILQ_FOREACH(host, &table->hosts, entry) {
if (host->flags & F_DISABLE)
continue;
+ if (table->check == CHECK_ICMP) {
+ schedule_icmp(env, host);
+ continue;
+ }
+
+ /* Any other TCP-style checks */
bzero(&host->cte, sizeof(host->cte));
host->last_up = host->up;
host->cte.host = host;
host->cte.table = table;
- if (gettimeofday(&host->cte.tv_start, NULL))
- fatal("hce_launch_checks: gettimeofday");
+ bcopy(&tv, &host->cte.tv_start,
+ sizeof(host->cte.tv_start));
check_tcp(&host->cte);
}
}
- check_icmp(&env->cie);
+ check_icmp(env, &tv);
+
+ bcopy(&env->interval, &tv, sizeof(tv));
+ evtimer_add(&env->ev, &tv);
}
int
@@ -205,35 +217,16 @@ void
hce_notify_done(struct host *host, const char *msg)
{
struct ctl_status st;
- struct timeval tv;
- struct table *table;
st.id = host->id;
st.up = host->up;
- host->flags |= F_CHECK_DONE;
+ host->flags |= (F_CHECK_SENT|F_CHECK_DONE);
if (msg)
- log_debug("hce_notify_done: %s", msg);
+ log_debug("hce_notify_done: %s (%s)", host->name, msg);
if (host->up != host->last_up) {
imsg_compose(ibuf_pfe, IMSG_HOST_STATUS, 0, 0, &st, sizeof(st));
host->last_up = host->up;
}
- /*
- * check if everything is done, I see no other way than going
- * through the tree for every host that calls this function.
- */
- if (hce_checks_done()) {
- /*
- * notify pfe checks are done and schedule next check
- */
- imsg_compose(ibuf_pfe, IMSG_SYNC, 0, 0, NULL, 0);
- TAILQ_FOREACH(table, &env->tables, entry) {
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->flags &= ~F_CHECK_DONE;
- }
- bcopy(&env->interval, &tv, sizeof(tv));
- evtimer_add(&env->ev, &tv);
- bzero(&st, sizeof(st));
- }
}
void
diff --git a/usr.sbin/hoststated/hoststated.c b/usr.sbin/hoststated/hoststated.c
index cbb72231380..771f8c7ddc6 100644
--- a/usr.sbin/hoststated/hoststated.c
+++ b/usr.sbin/hoststated/hoststated.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hoststated.c,v 1.9 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: hoststated.c,v 1.10 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -410,3 +410,24 @@ service_findbyname(struct hoststated *env, const char *name)
return (service);
return (NULL);
}
+
+void
+event_again(struct event *ev, int fd, short event, void (*fn)(int, short, void *),
+ struct timeval *start, struct timeval *end, void *arg)
+{
+ struct timeval tv_next, tv_now, tv;
+
+ if (gettimeofday(&tv_now, NULL))
+ fatal("event_again: gettimeofday");
+
+ bcopy(end, &tv_next, sizeof(tv_next));
+ timersub(&tv_now, start, &tv_now);
+ timersub(&tv_next, &tv_now, &tv_next);
+
+ bzero(&tv, sizeof(tv));
+ if (timercmp(&tv_next, &tv, >))
+ bcopy(&tv_next, &tv, sizeof(tv));
+
+ event_set(ev, fd, event, fn, arg);
+ event_add(ev, &tv);
+}
diff --git a/usr.sbin/hoststated/hoststated.h b/usr.sbin/hoststated/hoststated.h
index 0102c4a1566..f629ddf266d 100644
--- a/usr.sbin/hoststated/hoststated.h
+++ b/usr.sbin/hoststated/hoststated.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hoststated.h,v 1.13 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: hoststated.h,v 1.14 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -126,21 +126,20 @@ struct ctl_id {
struct ctl_icmp_event {
struct hoststated *env;
- int icmp_sock;
- int icmp6_sock;
- int has_icmp4;
- int has_icmp6;
+ int s;
+ int af;
int last_up;
struct event ev;
struct timeval tv_start;
};
struct ctl_tcp_event {
- int s;
- struct buf *buf;
- struct host *host;
- struct table *table;
- struct timeval tv_start;
+ int s;
+ struct buf *buf;
+ struct host *host;
+ struct table *table;
+ struct timeval tv_start;
+ struct event ev;
};
struct address {
@@ -156,6 +155,7 @@ TAILQ_HEAD(addresslist, address);
#define F_CHECK_DONE 0x02 /* reused for host */
#define F_USED 0x04
#define F_ACTIVE_RULESET 0x04 /* reused for service */
+#define F_CHECK_SENT 0x04 /* reused for host */
#define F_DOWN 0x08
#define F_ADD 0x10
#define F_DEL 0x20
@@ -228,8 +228,6 @@ enum {
struct hoststated {
u_int8_t opts;
struct pfdata *pf;
- int icmp_sock;
- int icmp6_sock;
int tablecount;
int servicecount;
struct timeval interval;
@@ -238,7 +236,14 @@ struct hoststated {
struct event ev;
struct tablelist tables;
struct servicelist services;
- struct ctl_icmp_event cie;
+ u_int16_t id;
+
+ int has_icmp;
+ int has_icmp6;
+ struct ctl_icmp_event icmp_send;
+ struct ctl_icmp_event icmp_recv;
+ struct ctl_icmp_event icmp6_send;
+ struct ctl_icmp_event icmp6_recv;
};
#define HOSTSTATED_OPT_VERBOSE 0x01
@@ -334,17 +339,18 @@ pid_t hce(struct hoststated *, int [2], int [2], int [2]);
void hce_notify_done(struct host *, const char *);
/* check_icmp.c */
-void schedule_icmp(struct ctl_icmp_event *, struct table *);
-void check_icmp(struct ctl_icmp_event *);
+void icmp_init(struct hoststated *);
+void schedule_icmp(struct hoststated *, struct host *);
+void check_icmp(struct hoststated *, struct timeval *);
/* check_tcp.c */
void check_tcp(struct ctl_tcp_event *);
/* check_http.c */
-void send_http_request(struct ctl_tcp_event *);
+void send_http_request(int, short, void *);
/* check_send_expect.c */
-void start_send_expect(struct ctl_tcp_event *);
+void start_send_expect(int, short, void *);
/* hoststated.c */
struct host *host_find(struct hoststated *, objid_t);
@@ -353,3 +359,6 @@ struct service *service_find(struct hoststated *, objid_t);
struct host *host_findbyname(struct hoststated *, const char *);
struct table *table_findbyname(struct hoststated *, const char *);
struct service *service_findbyname(struct hoststated *, const char *);
+void event_again(struct event *, int, short,
+ void (*)(int, short, void *),
+ struct timeval *, struct timeval *, void *);
diff --git a/usr.sbin/relayd/check_icmp.c b/usr.sbin/relayd/check_icmp.c
index fb7692eac5e..e44c70c2c1b 100644
--- a/usr.sbin/relayd/check_icmp.c
+++ b/usr.sbin/relayd/check_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_icmp.c,v 1.9 2007/01/09 03:32:56 reyk Exp $ */
+/* $OpenBSD: check_icmp.c,v 1.10 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -33,53 +33,86 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
+#include <err.h>
#include "hoststated.h"
-int icmp6_checks_done(struct ctl_icmp_event *);
-int icmp4_checks_done(struct ctl_icmp_event *);
-void send_icmp6(struct ctl_icmp_event *, struct host *);
-void send_icmp4(struct ctl_icmp_event *, struct host *);
-void recv_icmp6(int, short, void *);
-void recv_icmp4(int, short, void *);
+void icmp_setup(struct hoststated *, struct ctl_icmp_event *, int);
+void check_icmp_add(struct ctl_icmp_event *, int, struct timeval *,
+ void (*)(int, short, void *));
+int icmp_checks_done(struct ctl_icmp_event *);
+void icmp_checks_timeout(struct ctl_icmp_event *, const char *);
+void send_icmp(int, short, void *);
+void recv_icmp(int, short, void *);
int in_cksum(u_short *, int);
void
-schedule_icmp(struct ctl_icmp_event *cie, struct table *table)
+icmp_setup(struct hoststated *env, struct ctl_icmp_event *cie, int af)
{
- struct host *host;
+ int proto = IPPROTO_ICMP;
+
+ if (af == AF_INET6)
+ proto = IPPROTO_ICMPV6;
+ if ((cie->s = socket(af, SOCK_RAW, proto)) < 0)
+ err(1, "icmp_init: socket");
+ session_socket_blockmode(cie->s, BM_NONBLOCK);
+ cie->env = env;
+ cie->af = af;
+}
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- host->last_up = host->up;
- host->flags &= ~F_CHECK_DONE;
- if (((struct sockaddr *)&host->ss)->sa_family == AF_INET) {
- send_icmp4(cie, host);
- } else {
- send_icmp6(cie, host);
- }
- }
+void
+icmp_init(struct hoststated *env)
+{
+ icmp_setup(env, &env->icmp_send, AF_INET);
+ icmp_setup(env, &env->icmp_recv, AF_INET);
+ icmp_setup(env, &env->icmp6_send, AF_INET6);
+ icmp_setup(env, &env->icmp6_recv, AF_INET6);
+ env->id = getpid() & 0xffff;
}
void
-check_icmp(struct ctl_icmp_event *cie)
+schedule_icmp(struct hoststated *env, struct host *host)
{
- struct timeval tv;
+ host->last_up = host->up;
+ host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
- if (gettimeofday(&cie->tv_start, NULL))
- fatal("check_icmp: gettimeofday");
+ if (((struct sockaddr *)&host->ss)->sa_family == AF_INET)
+ env->has_icmp = 1;
+ else
+ env->has_icmp6 = 1;
+}
+
+void
+check_icmp_add(struct ctl_icmp_event *cie, int flags, struct timeval *start,
+ void (*fn)(int, short, void *))
+{
+ struct timeval tv;
+
+ if (start != NULL)
+ bcopy(start, &cie->tv_start, sizeof(cie->tv_start));
bcopy(&cie->env->timeout, &tv, sizeof(tv));
- if (cie->has_icmp4)
- event_once(cie->icmp_sock, EV_READ|EV_TIMEOUT,
- recv_icmp4, cie, &tv);
- if (cie->has_icmp6)
- event_once(cie->icmp6_sock, EV_READ|EV_TIMEOUT,
- recv_icmp6, cie, &tv);
+ if (gettimeofday(&cie->tv_start, NULL))
+ fatal("check_icmp_add: gettimeofday");
+ event_del(&cie->ev);
+ event_set(&cie->ev, cie->s, EV_TIMEOUT|flags, fn, cie);
+ event_add(&cie->ev, &tv);
+}
+
+void
+check_icmp(struct hoststated *env, struct timeval *tv)
+{
+ if (env->has_icmp) {
+ check_icmp_add(&env->icmp_recv, EV_READ, tv, recv_icmp);
+ check_icmp_add(&env->icmp_send, EV_WRITE, tv, send_icmp);
+ }
+ if (env->has_icmp6) {
+ check_icmp_add(&env->icmp6_recv, EV_READ, tv, recv_icmp);
+ check_icmp_add(&env->icmp6_send, EV_WRITE, tv, send_icmp);
+ }
}
int
-icmp6_checks_done(struct ctl_icmp_event *cie)
+icmp_checks_done(struct ctl_icmp_event *cie)
{
struct table *table;
struct host *host;
@@ -88,8 +121,7 @@ icmp6_checks_done(struct ctl_icmp_event *cie)
if (table->flags & F_DISABLE || table->check != CHECK_ICMP)
continue;
TAILQ_FOREACH(host, &table->hosts, entry) {
- if (((struct sockaddr *)&host->ss)->sa_family !=
- AF_INET6)
+ if (((struct sockaddr *)&host->ss)->sa_family != cie->af)
continue;
if (!(host->flags & F_CHECK_DONE))
return (0);
@@ -98,8 +130,8 @@ icmp6_checks_done(struct ctl_icmp_event *cie)
return (1);
}
-int
-icmp4_checks_done(struct ctl_icmp_event *cie)
+void
+icmp_checks_timeout(struct ctl_icmp_event *cie, const char *msg)
{
struct table *table;
struct host *host;
@@ -108,220 +140,156 @@ icmp4_checks_done(struct ctl_icmp_event *cie)
if (table->flags & F_DISABLE || table->check != CHECK_ICMP)
continue;
TAILQ_FOREACH(host, &table->hosts, entry) {
- if (((struct sockaddr *)&host->ss)->sa_family !=
- AF_INET)
+ if (((struct sockaddr *)&host->ss)->sa_family != cie->af)
continue;
- if (!(host->flags & F_CHECK_DONE)) {
- return (0);
- }
+ if (!(host->flags & F_CHECK_DONE))
+ host->up = HOST_DOWN;
+ hce_notify_done(host, msg);
}
}
- return (1);
}
void
-send_icmp6(struct ctl_icmp_event *cie, struct host *host)
+send_icmp(int s, short event, void *arg)
{
+ struct ctl_icmp_event *cie = (struct ctl_icmp_event *)arg;
+ struct table *table;
+ struct host *host;
struct sockaddr *to;
- struct icmp6_hdr *icp;
- ssize_t i;
+ struct icmp *icp;
+ struct icmp6_hdr *icp6;
+ ssize_t r;
u_char packet[ICMP_BUF_SIZE];
+ socklen_t slen;
+ int i = 0;
- cie->has_icmp6 = 1;
- to = (struct sockaddr *)&host->ss;
- bzero(&packet, sizeof(packet));
- icp = (struct icmp6_hdr *)packet;
- icp->icmp6_type = ICMP6_ECHO_REQUEST;
- icp->icmp6_code = 0;
- icp->icmp6_seq = 1;
- icp->icmp6_id = getpid() & 0xffff;
-
- memcpy((packet + sizeof(*icp)), &host->id, sizeof(host->id));
-
- i = sendto(cie->icmp6_sock, packet, sizeof(packet), 0, to,
- sizeof(struct sockaddr_in6));
- if (i < 0 || i != sizeof(packet)) {
- host->up = HOST_DOWN;
- hce_notify_done(host, "send_icmp6: cannot send");
+ if (event == EV_TIMEOUT) {
+ icmp_checks_timeout(cie, "send_icmp: timeout");
return;
}
-}
-
-void
-send_icmp4(struct ctl_icmp_event *cie, struct host *host)
-{
- struct sockaddr *to;
- struct icmp *icp;
- ssize_t i;
- u_char packet[ICMP_BUF_SIZE];
- cie->has_icmp4 = 1;
- to = (struct sockaddr *)&host->ss;
bzero(&packet, sizeof(packet));
icp = (struct icmp *)packet;
- icp->icmp_type = ICMP_ECHO;
- icp->icmp_code = 0;
- icp->icmp_seq = htons(1);
- icp->icmp_id = htons(getpid() & 0xffff);
- icp->icmp_cksum = 0;
-
- memcpy(icp->icmp_data, &host->id, sizeof(host->id));
- icp->icmp_cksum = in_cksum((u_short *)icp, sizeof(packet));
-
- i = sendto(cie->icmp_sock, packet, sizeof(packet), 0, to,
- sizeof(struct sockaddr_in));
- if (i < 0 || i != sizeof(packet)) {
- host->up = HOST_DOWN;
- hce_notify_done(host, "send_icmp4: cannot send");
+ icp6 = (struct icmp6_hdr *)packet;
+ if (cie->af == AF_INET) {
+ icp->icmp_type = ICMP_ECHO;
+ icp->icmp_code = 0;
+ icp->icmp_id = htons(cie->env->id);
+ icp->icmp_cksum = 0;
+ slen = sizeof(struct sockaddr_in);
+ } else {
+ icp6->icmp6_type = ICMP6_ECHO_REQUEST;
+ icp6->icmp6_code = 0;
+ icp6->icmp6_cksum = 0;
+ icp6->icmp6_id = htons(cie->env->id);
+ slen = sizeof(struct sockaddr_in6);
}
-}
-void
-recv_icmp6(int s, short event, void *arg)
-{
- struct ctl_icmp_event *cie = arg;
- u_char packet[ICMP_BUF_SIZE];
- socklen_t len;
- struct sockaddr_storage ss;
- struct icmp6_hdr *icp;
- struct host *host;
- struct table *table;
- ssize_t i;
- objid_t id;
- struct timeval tv;
- struct timeval tv_now;
-
- if (event == EV_TIMEOUT) {
- /*
- * mark all hosts which have not responded yet as down.
- */
- TAILQ_FOREACH(table, &cie->env->tables, entry) {
- if (table->check != CHECK_ICMP ||
- table->flags & F_DISABLE)
+ TAILQ_FOREACH(table, &cie->env->tables, entry) {
+ if (table->check != CHECK_ICMP || table->flags & F_DISABLE)
+ continue;
+ TAILQ_FOREACH(host, &table->hosts, entry) {
+ if (host->flags & (F_DISABLE | F_CHECK_SENT))
continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- if (((struct sockaddr *)&host->ss)->sa_family
- != AF_INET6)
- continue;
- if (!(host->flags & F_CHECK_DONE)) {
- host->up = HOST_DOWN;
- }
+ if (((struct sockaddr *)&host->ss)->sa_family != cie->af)
+ continue;
+ i++;
+ to = (struct sockaddr *)&host->ss;
+ if (cie->af == AF_INET) {
+ icp->icmp_seq = htons(i);
+ icp->icmp_cksum = 0;
+ memcpy(icp->icmp_data, &host->id,
+ sizeof(host->id));
+ icp->icmp_cksum = in_cksum((u_short *)icp,
+ sizeof(packet));
+ } else {
+ icp6->icmp6_seq = htons(i);
+ icp6->icmp6_cksum = 0;
+ memcpy(packet + sizeof(*icp6), &host->id,
+ sizeof(host->id));
+ icp6->icmp6_cksum = in_cksum((u_short *)icp6,
+ sizeof(packet));
}
+
+ r = sendto(s, packet, sizeof(packet), 0, to, slen);
+ if (r == -1) {
+ if (errno == EAGAIN && errno == EINTR)
+ goto retry;
+ host->flags |= F_CHECK_SENT|F_CHECK_DONE;
+ host->up = HOST_DOWN;
+ } else if (r != sizeof(packet))
+ goto retry;
+ host->flags |= F_CHECK_SENT;
}
- return;
- }
- bzero(&packet, sizeof(packet));
- bzero(&ss, sizeof(ss));
- len = sizeof(struct sockaddr_in6);
- i = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &len);
- if (i < 0 || i != sizeof(packet)) {
- log_warn("recv_icmp6: did not receive valid ping");
- return;
}
- icp = (struct icmp6_hdr *)(packet);
- memcpy(&id, (packet + sizeof(*icp)), sizeof(id));
- host = host_find(cie->env, id);
- if (host == NULL)
- log_warn("recv_icmp6: ping for unknown host received");
- if (bcmp(&ss, &host->ss, len)) {
- log_warnx("recv_icmp6: forged icmp packet ?");
- return;
- }
- if (icp->icmp6_id != (getpid() & 0xffff)) {
- log_warnx("recv_icmp6: did not receive valid ident");
- host->up = HOST_DOWN;
- } else
- host->up = HOST_UP;
- hce_notify_done(host, "recv_icmp6: final");
- if (icmp6_checks_done(cie))
- return;
- if (gettimeofday(&tv_now, NULL))
- fatal("recv_icmp6: gettimeofday");
- bcopy(&cie->env->timeout, &tv, sizeof(tv));
- timersub(&tv_now, &cie->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(cie->icmp6_sock, EV_READ|EV_TIMEOUT, recv_icmp6, cie, &tv);
+
+ return;
+
+ retry:
+ event_again(&cie->ev, s, EV_TIMEOUT|EV_WRITE, send_icmp,
+ &cie->tv_start, &cie->env->timeout, cie);
}
void
-recv_icmp4(int s, short event, void *arg)
+recv_icmp(int s, short event, void *arg)
{
- socklen_t len;
- struct icmp *icp;
- struct ctl_icmp_event *cie = arg;
+ struct ctl_icmp_event *cie = (struct ctl_icmp_event *)arg;
u_char packet[ICMP_BUF_SIZE];
+ socklen_t slen;
+ struct sockaddr_storage ss;
+ struct icmp *icp;
+ struct icmp6_hdr *icp6;
+ u_int16_t icpid;
struct host *host;
- struct table *table;
- ssize_t i;
+ ssize_t r;
objid_t id;
- struct timeval tv;
- struct timeval tv_now;
- struct sockaddr_storage ss;
if (event == EV_TIMEOUT) {
- /*
- * mark all hosts which have not responded yet as down.
- */
- TAILQ_FOREACH(table, &cie->env->tables, entry) {
- if (table->check != CHECK_ICMP ||
- table->flags & F_DISABLE)
- continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- if (((struct sockaddr *)&host->ss)->sa_family
- != AF_INET)
- continue;
- if (!(host->flags & F_CHECK_DONE)) {
- host->up = HOST_DOWN;
- }
- }
- }
+ icmp_checks_timeout(cie, NULL);
return;
}
- len = sizeof(struct sockaddr_in);
bzero(&packet, sizeof(packet));
bzero(&ss, sizeof(ss));
- i = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &len);
- if (i < 0 || i != sizeof(packet)) {
- log_warn("recv_icmp4: did not receive valid ping");
- return;
+
+ r = recvfrom(s, packet, sizeof(packet), 0, (struct sockaddr *)&ss, &slen);
+ if (r == -1 || r != ICMP_BUF_SIZE) {
+ if (r == -1 && errno != EAGAIN && errno != EINTR)
+ log_debug("recv_icmp: receive error");
+ goto retry;
}
- icp = (struct icmp *)(packet + sizeof(struct ip));
- memcpy(&id, icp->icmp_data, sizeof(id));
+ if (cie->af == AF_INET) {
+ icp = (struct icmp *)(packet + sizeof(struct ip));
+ icpid = ntohs(icp->icmp_id);
+ memcpy(&id, icp->icmp_data, sizeof(id));
+ } else {
+ icp6 = (struct icmp6_hdr *)packet;
+ icpid = ntohs(icp6->icmp6_id);
+ memcpy(&id, packet + sizeof(*icp6), sizeof(id));
+ }
+ if (icpid != cie->env->id)
+ goto retry;
host = host_find(cie->env, id);
if (host == NULL) {
- log_warnx("recv_icmp4: received ping for unknown host");
- return;
+ log_warn("recv_icmp: ping for unknown host received");
+ goto retry;
}
- if (bcmp(&ss, &host->ss, len)) {
- log_warnx("recv_icmp4: forged icmp packet ?");
- return;
+ if (bcmp(&ss, &host->ss, slen)) {
+ log_warnx("recv_icmp: forged icmp packet?");
+ goto retry;
}
- if (ntohs(icp->icmp_id) != (getpid() & 0xffff)) {
- log_warnx("recv_icmp4: did not receive valid ident");
- host->up = HOST_DOWN;
- } else
- host->up = HOST_UP;
+ host->up = HOST_UP;
host->flags |= F_CHECK_DONE;
- if (icmp4_checks_done(cie)) {
- hce_notify_done(host, "recv_icmp4: all done");
- return;
- }
- hce_notify_done(host, "recv_icmp4: host");
+ hce_notify_done(host, "recv_icmp: done");
- if (gettimeofday(&tv_now, NULL))
- fatal("recv_icmp4: gettimeofday");
+ if (icmp_checks_done(cie))
+ return;
- bcopy(&cie->env->timeout, &tv, sizeof(tv));
- timersub(&tv_now, &cie->tv_start, &tv_now);
- timersub(&tv, &tv_now, &tv);
- event_once(cie->icmp_sock, EV_READ|EV_TIMEOUT, recv_icmp4, cie, &tv);
+ retry:
+ event_again(&cie->ev, s, EV_TIMEOUT|EV_READ, recv_icmp,
+ &cie->tv_start, &cie->env->timeout, cie);
}
/* in_cksum from ping.c --
diff --git a/usr.sbin/relayd/check_tcp.c b/usr.sbin/relayd/check_tcp.c
index 86b8244093f..fc365c18d9d 100644
--- a/usr.sbin/relayd/check_tcp.c
+++ b/usr.sbin/relayd/check_tcp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: check_tcp.c,v 1.8 2007/01/09 00:45:32 deraadt Exp $ */
+/* $OpenBSD: check_tcp.c,v 1.9 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -71,17 +71,16 @@ check_tcp(struct ctl_tcp_event *cte)
if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
goto bad;
+ bcopy(&cte->table->timeout, &tv, sizeof(tv));
if (connect(s, (struct sockaddr *)&cte->host->ss, len) == -1) {
if (errno != EINPROGRESS)
goto bad;
- } else {
+ } else
cte->host->up = HOST_UP;
- tcp_host_up(s, cte);
- return;
- }
- bcopy(&cte->table->timeout, &tv, sizeof(tv));
- event_once(s, EV_TIMEOUT|EV_WRITE, tcp_write, cte, &tv);
+ event_set(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_write, cte);
+ event_add(&cte->ev, &tv);
return;
+
bad:
close(s);
cte->host->up = HOST_DOWN;
@@ -102,7 +101,7 @@ tcp_write(int s, short event, void *arg)
len = sizeof(err);
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len))
fatal("tcp_write: getsockopt");
- if (err)
+ if (err != 0)
cte->host->up = HOST_DOWN;
else
cte->host->up = HOST_UP;
@@ -123,16 +122,18 @@ tcp_host_up(int s, struct ctl_tcp_event *cte)
switch (cte->table->check) {
case CHECK_TCP:
close(s);
- hce_notify_done(cte->host, "tcp_write: success");
+ hce_notify_done(cte->host, "tcp_host_up: success");
break;
case CHECK_HTTP_CODE:
case CHECK_HTTP_DIGEST:
- send_http_request(cte);
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, send_http_request,
+ &cte->tv_start, &cte->table->timeout, cte);
break;
case CHECK_SEND_EXPECT:
- start_send_expect(cte);
+ event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, start_send_expect,
+ &cte->tv_start, &cte->table->timeout, cte);
break;
default:
- fatalx("tcp_write: unhandled check type");
+ fatalx("tcp_host_up: unhandled check type");
}
}
diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c
index c951b5ba8bb..012a5dbf63f 100644
--- a/usr.sbin/relayd/hce.c
+++ b/usr.sbin/relayd/hce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hce.c,v 1.9 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: hce.c,v 1.10 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -82,12 +82,6 @@ hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
env = x_env;
- /* this is needed for icmp tests */
- if ((env->icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
- err(1, "socket");
- if ((env->icmp6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
- err(1, "socket");
-
if ((pw = getpwnam(HOSTSTATED_USER)) == NULL)
fatal("hce: getpwnam");
@@ -99,15 +93,14 @@ hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
setproctitle("host check engine");
hoststated_process = PROC_HCE;
+ /* this is needed for icmp tests */
+ icmp_init(env);
+
if (setgroups(1, &pw->pw_gid) ||
setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
fatal("hce: can't drop privileges");
- env->cie.icmp_sock = env->icmp_sock;
- env->cie.icmp6_sock = env->icmp6_sock;
- env->cie.env = env;
-
event_init();
signal_set(&ev_sigint, SIGINT, hce_sig_handler, NULL);
@@ -137,11 +130,10 @@ hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
ibuf_main->handler, ibuf_main);
event_add(&ibuf_main->ev, NULL);
- evtimer_set(&env->ev, hce_launch_checks, NULL);
- bcopy(&env->interval, &tv, sizeof(tv));
+ evtimer_set(&env->ev, hce_launch_checks, env);
+ bzero(&tv, sizeof(tv));
evtimer_add(&env->ev, &tv);
- hce_launch_checks(0, 0, NULL);
event_dispatch();
hce_shutdown();
@@ -154,32 +146,52 @@ hce_launch_checks(int fd, short event, void *arg)
{
struct host *host;
struct table *table;
+ struct timeval tv;
+
+ log_debug("hce_launch_checks: scheduled");
+
+ /*
+ * notify pfe checks are done and schedule next check
+ */
+ imsg_compose(ibuf_pfe, IMSG_SYNC, 0, 0, NULL, 0);
+ TAILQ_FOREACH(table, &env->tables, entry) {
+ TAILQ_FOREACH(host, &table->hosts, entry) {
+ host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
+ event_del(&host->cte.ev);
+ }
+ }
+
+ if (gettimeofday(&tv, NULL))
+ fatal("hce_launch_checks: gettimeofday");
TAILQ_FOREACH(table, &env->tables, entry) {
if (table->flags & F_DISABLE)
continue;
if (table->check == CHECK_NOCHECK)
fatalx("hce_launch_checks: unknown check type");
- if (table->check == CHECK_ICMP) {
- schedule_icmp(&env->cie, table);
- continue;
- }
- /*
- * tcp type checks follow
- */
+
TAILQ_FOREACH(host, &table->hosts, entry) {
if (host->flags & F_DISABLE)
continue;
+ if (table->check == CHECK_ICMP) {
+ schedule_icmp(env, host);
+ continue;
+ }
+
+ /* Any other TCP-style checks */
bzero(&host->cte, sizeof(host->cte));
host->last_up = host->up;
host->cte.host = host;
host->cte.table = table;
- if (gettimeofday(&host->cte.tv_start, NULL))
- fatal("hce_launch_checks: gettimeofday");
+ bcopy(&tv, &host->cte.tv_start,
+ sizeof(host->cte.tv_start));
check_tcp(&host->cte);
}
}
- check_icmp(&env->cie);
+ check_icmp(env, &tv);
+
+ bcopy(&env->interval, &tv, sizeof(tv));
+ evtimer_add(&env->ev, &tv);
}
int
@@ -205,35 +217,16 @@ void
hce_notify_done(struct host *host, const char *msg)
{
struct ctl_status st;
- struct timeval tv;
- struct table *table;
st.id = host->id;
st.up = host->up;
- host->flags |= F_CHECK_DONE;
+ host->flags |= (F_CHECK_SENT|F_CHECK_DONE);
if (msg)
- log_debug("hce_notify_done: %s", msg);
+ log_debug("hce_notify_done: %s (%s)", host->name, msg);
if (host->up != host->last_up) {
imsg_compose(ibuf_pfe, IMSG_HOST_STATUS, 0, 0, &st, sizeof(st));
host->last_up = host->up;
}
- /*
- * check if everything is done, I see no other way than going
- * through the tree for every host that calls this function.
- */
- if (hce_checks_done()) {
- /*
- * notify pfe checks are done and schedule next check
- */
- imsg_compose(ibuf_pfe, IMSG_SYNC, 0, 0, NULL, 0);
- TAILQ_FOREACH(table, &env->tables, entry) {
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->flags &= ~F_CHECK_DONE;
- }
- bcopy(&env->interval, &tv, sizeof(tv));
- evtimer_add(&env->ev, &tv);
- bzero(&st, sizeof(st));
- }
}
void
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c
index 1507f4d19fb..2062ad5e03b 100644
--- a/usr.sbin/relayd/relayd.c
+++ b/usr.sbin/relayd/relayd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.c,v 1.9 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: relayd.c,v 1.10 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -410,3 +410,24 @@ service_findbyname(struct hoststated *env, const char *name)
return (service);
return (NULL);
}
+
+void
+event_again(struct event *ev, int fd, short event, void (*fn)(int, short, void *),
+ struct timeval *start, struct timeval *end, void *arg)
+{
+ struct timeval tv_next, tv_now, tv;
+
+ if (gettimeofday(&tv_now, NULL))
+ fatal("event_again: gettimeofday");
+
+ bcopy(end, &tv_next, sizeof(tv_next));
+ timersub(&tv_now, start, &tv_now);
+ timersub(&tv_next, &tv_now, &tv_next);
+
+ bzero(&tv, sizeof(tv));
+ if (timercmp(&tv_next, &tv, >))
+ bcopy(&tv_next, &tv, sizeof(tv));
+
+ event_set(ev, fd, event, fn, arg);
+ event_add(ev, &tv);
+}
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index a21a3a4bd7f..dc801ea20c9 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.13 2007/01/09 13:50:11 pyr Exp $ */
+/* $OpenBSD: relayd.h,v 1.14 2007/01/11 18:05:08 reyk Exp $ */
/*
* Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -126,21 +126,20 @@ struct ctl_id {
struct ctl_icmp_event {
struct hoststated *env;
- int icmp_sock;
- int icmp6_sock;
- int has_icmp4;
- int has_icmp6;
+ int s;
+ int af;
int last_up;
struct event ev;
struct timeval tv_start;
};
struct ctl_tcp_event {
- int s;
- struct buf *buf;
- struct host *host;
- struct table *table;
- struct timeval tv_start;
+ int s;
+ struct buf *buf;
+ struct host *host;
+ struct table *table;
+ struct timeval tv_start;
+ struct event ev;
};
struct address {
@@ -156,6 +155,7 @@ TAILQ_HEAD(addresslist, address);
#define F_CHECK_DONE 0x02 /* reused for host */
#define F_USED 0x04
#define F_ACTIVE_RULESET 0x04 /* reused for service */
+#define F_CHECK_SENT 0x04 /* reused for host */
#define F_DOWN 0x08
#define F_ADD 0x10
#define F_DEL 0x20
@@ -228,8 +228,6 @@ enum {
struct hoststated {
u_int8_t opts;
struct pfdata *pf;
- int icmp_sock;
- int icmp6_sock;
int tablecount;
int servicecount;
struct timeval interval;
@@ -238,7 +236,14 @@ struct hoststated {
struct event ev;
struct tablelist tables;
struct servicelist services;
- struct ctl_icmp_event cie;
+ u_int16_t id;
+
+ int has_icmp;
+ int has_icmp6;
+ struct ctl_icmp_event icmp_send;
+ struct ctl_icmp_event icmp_recv;
+ struct ctl_icmp_event icmp6_send;
+ struct ctl_icmp_event icmp6_recv;
};
#define HOSTSTATED_OPT_VERBOSE 0x01
@@ -334,17 +339,18 @@ pid_t hce(struct hoststated *, int [2], int [2], int [2]);
void hce_notify_done(struct host *, const char *);
/* check_icmp.c */
-void schedule_icmp(struct ctl_icmp_event *, struct table *);
-void check_icmp(struct ctl_icmp_event *);
+void icmp_init(struct hoststated *);
+void schedule_icmp(struct hoststated *, struct host *);
+void check_icmp(struct hoststated *, struct timeval *);
/* check_tcp.c */
void check_tcp(struct ctl_tcp_event *);
/* check_http.c */
-void send_http_request(struct ctl_tcp_event *);
+void send_http_request(int, short, void *);
/* check_send_expect.c */
-void start_send_expect(struct ctl_tcp_event *);
+void start_send_expect(int, short, void *);
/* hoststated.c */
struct host *host_find(struct hoststated *, objid_t);
@@ -353,3 +359,6 @@ struct service *service_find(struct hoststated *, objid_t);
struct host *host_findbyname(struct hoststated *, const char *);
struct table *table_findbyname(struct hoststated *, const char *);
struct service *service_findbyname(struct hoststated *, const char *);
+void event_again(struct event *, int, short,
+ void (*)(int, short, void *),
+ struct timeval *, struct timeval *, void *);