summaryrefslogtreecommitdiff
path: root/usr.sbin/hoststated/check_send_expect.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2007-01-08 13:37:27 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2007-01-08 13:37:27 +0000
commit87fbc4eb6f54a862defb1e20204b629668404f69 (patch)
tree2fd2ce8e3d02b9dedbefafc24d27c2a3cdd73286 /usr.sbin/hoststated/check_send_expect.c
parent405b2cea000c3c2e09d4f486aff444c6fca41e8a (diff)
add a generic send/expect check using regular expression (see
regex(3)). this allows to define additional checks for other TCP protocols. From Pierre-Yves Ritschard (pyr at spootnik dot org)
Diffstat (limited to 'usr.sbin/hoststated/check_send_expect.c')
-rw-r--r--usr.sbin/hoststated/check_send_expect.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/usr.sbin/hoststated/check_send_expect.c b/usr.sbin/hoststated/check_send_expect.c
new file mode 100644
index 00000000000..0a1aa4c7db7
--- /dev/null
+++ b/usr.sbin/hoststated/check_send_expect.c
@@ -0,0 +1,141 @@
+/* $OpenBSD: check_send_expect.c,v 1.1 2007/01/08 13:37:26 reyk Exp $ */
+/*
+ * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <net/if.h>
+#include <limits.h>
+#include <event.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <regex.h>
+
+#include "hostated.h"
+
+void se_validate(struct ctl_tcp_event *);
+void se_read(int, short, void *);
+
+void
+se_validate(struct ctl_tcp_event *cte)
+{
+ u_char *b;
+
+ /*
+ * ensure string is nul-terminated.
+ */
+ b = buf_reserve(cte->buf, 1);
+ if (b == NULL)
+ fatal("out of memory");
+ *b = '\0';
+ if (regexec(&cte->table->regx, cte->buf->buf, 0, NULL, 0) == 0)
+ cte->host->up = HOST_UP;
+ else
+ cte->host->up = HOST_DOWN;
+
+ /*
+ * go back to original position.
+ */
+ cte->buf->wpos--;
+}
+
+void
+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) {
+ cte->host->up = HOST_DOWN;
+ buf_free(cte->buf);
+ 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) {
+ 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;
+ 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);
+ }
+}
+
+void
+start_send_expect(struct ctl_tcp_event *cte)
+{
+ int bs;
+ int pos;
+ int len;
+ char *req;
+ struct timeval tv;
+ struct timeval tv_now;
+
+ req = cte->table->sendbuf;
+ pos = 0;
+ len = strlen(req);
+ if (len) {
+ do {
+ bs = write(cte->s, req + pos, len);
+ if (bs <= 0) {
+ log_warnx("send_se_data: cannot send");
+ cte->host->up = HOST_DOWN;
+ hce_notify_done(cte->host,
+ "start_send_expect: write");
+ return;
+ }
+ pos += bs;
+ len -= bs;
+ } while (len > 0);
+ }
+
+ 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");
+
+ 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);
+}