diff options
43 files changed, 568 insertions, 53 deletions
diff --git a/usr.sbin/hostated/Makefile b/usr.sbin/hostated/Makefile index c04e70f3036..16a06450a62 100644 --- a/usr.sbin/hostated/Makefile +++ b/usr.sbin/hostated/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.1 2006/12/16 11:45:07 reyk Exp $ +# $OpenBSD: Makefile,v 1.2 2007/01/08 13:37:26 reyk Exp $ PROG= hostated -SRCS= parse.y log.c control.c buffer.c imsg.c hostated.c \ - pfe.c pfe_filter.c hce.c check_icmp.c check_tcp.c check_http.c +SRCS= parse.y log.c control.c buffer.c imsg.c hostated.c \ + pfe.c pfe_filter.c hce.c \ + check_icmp.c check_tcp.c check_http.c check_send_expect.c MAN= hostated.8 hostated.conf.5 LDADD= -levent diff --git a/usr.sbin/hostated/buffer.c b/usr.sbin/hostated/buffer.c index 3abe27b1e62..547d65ed859 100644 --- a/usr.sbin/hostated/buffer.c +++ b/usr.sbin/hostated/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.1 2006/12/16 11:45:07 reyk Exp $ */ +/* $OpenBSD: buffer.c,v 1.2 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -29,6 +29,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/check_http.c b/usr.sbin/hostated/check_http.c index b081c1ce2fa..899a240f7dc 100644 --- a/usr.sbin/hostated/check_http.c +++ b/usr.sbin/hostated/check_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: check_http.c,v 1.4 2006/12/25 19:05:41 reyk Exp $ */ +/* $OpenBSD: check_http.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> * @@ -28,6 +28,7 @@ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/check_icmp.c b/usr.sbin/hostated/check_icmp.c index 2880d4f5e84..ae18a97cc88 100644 --- a/usr.sbin/hostated/check_icmp.c +++ b/usr.sbin/hostated/check_icmp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: check_icmp.c,v 1.5 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: check_icmp.c,v 1.6 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -33,6 +33,7 @@ #include <unistd.h> #include <string.h> #include <stdlib.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/check_send_expect.c b/usr.sbin/hostated/check_send_expect.c new file mode 100644 index 00000000000..0a1aa4c7db7 --- /dev/null +++ b/usr.sbin/hostated/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); +} diff --git a/usr.sbin/hostated/check_tcp.c b/usr.sbin/hostated/check_tcp.c index 93cf8dd7041..888edb8da31 100644 --- a/usr.sbin/hostated/check_tcp.c +++ b/usr.sbin/hostated/check_tcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: check_tcp.c,v 1.4 2006/12/25 19:05:41 reyk Exp $ */ +/* $OpenBSD: check_tcp.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -29,6 +29,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <regex.h> #include "hostated.h" @@ -118,6 +119,8 @@ tcp_write(int s, short event, void *arg) void tcp_host_up(int s, struct ctl_tcp_event *cte) { + cte->s = s; + switch (cte->table->check) { case CHECK_TCP: close(s); @@ -127,6 +130,9 @@ tcp_host_up(int s, struct ctl_tcp_event *cte) case CHECK_HTTP_DIGEST: send_http_request(cte); break; + case CHECK_SEND_EXPECT: + start_send_expect(cte); + break; default: fatalx("tcp_write: unhandled check type"); } diff --git a/usr.sbin/hostated/control.c b/usr.sbin/hostated/control.c index 4f58a7654e3..1266b9fd21f 100644 --- a/usr.sbin/hostated/control.c +++ b/usr.sbin/hostated/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.4 2006/12/16 18:50:33 reyk Exp $ */ +/* $OpenBSD: control.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <signal.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/hce.c b/usr.sbin/hostated/hce.c index 6b291036e17..21cfe8a91aa 100644 --- a/usr.sbin/hostated/hce.c +++ b/usr.sbin/hostated/hce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hce.c,v 1.4 2006/12/25 18:12:14 reyk Exp $ */ +/* $OpenBSD: hce.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -35,6 +35,7 @@ #include <unistd.h> #include <err.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/hostated.c b/usr.sbin/hostated/hostated.c index e1adfb3628a..8d2abc6e7cc 100644 --- a/usr.sbin/hostated/hostated.c +++ b/usr.sbin/hostated/hostated.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostated.c,v 1.5 2006/12/25 18:40:38 reyk Exp $ */ +/* $OpenBSD: hostated.c,v 1.6 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -32,6 +32,7 @@ #include <signal.h> #include <unistd.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/hostated.conf.5 b/usr.sbin/hostated/hostated.conf.5 index f0985ede244..31c8cbc3f1d 100644 --- a/usr.sbin/hostated/hostated.conf.5 +++ b/usr.sbin/hostated/hostated.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: hostated.conf.5,v 1.8 2007/01/03 09:42:30 reyk Exp $ +.\" $OpenBSD: hostated.conf.5,v 1.9 2007/01/08 13:37:26 reyk Exp $ .\" .\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> .\" @@ -115,6 +115,21 @@ a9993e36476816aba3e25717850c26c9cd0d89d Ping hosts in this table to determine whether they are up or not. This method will automatically use ICMP or ICMPV6 depending on the address family of each host. +.It Ic check send Ar data Ic expect Ar regexp +For each host in the table, a TCP connection is established on the +port specified, then +.Ar data +is sent. +Incoming data is then read and is expected to match against +.Ar regexp. +If +.Ar data +is an empty string or +.Ic nothing +then nothing is sent on the connection and data is immediately +read. +This can be useful with protocols that output a banner like +SMTP, NNTP and FTP. .It Ic check tcp Use a simple TCP connect to check that hosts are up. .It Ic disable diff --git a/usr.sbin/hostated/hostated.h b/usr.sbin/hostated/hostated.h index 03338b90519..75ca9878c92 100644 --- a/usr.sbin/hostated/hostated.h +++ b/usr.sbin/hostated/hostated.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hostated.h,v 1.8 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: hostated.h,v 1.9 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -190,8 +190,11 @@ struct table { struct timeval timeout; char name[TABLE_NAME_SIZE]; char path[MAXPATHLEN]; + char sendbuf[64]; + char exbuf[64]; char digest[41]; /* length of sha1 digest * 2 */ struct hostlist hosts; + regex_t regx; TAILQ_ENTRY(table) entry; }; TAILQ_HEAD(tablelist, table); @@ -201,6 +204,7 @@ TAILQ_HEAD(tablelist, table); #define CHECK_TCP 2 #define CHECK_HTTP_CODE 3 #define CHECK_HTTP_DIGEST 4 +#define CHECK_SEND_EXPECT 5 struct service { objid_t id; @@ -339,6 +343,9 @@ void check_tcp(struct ctl_tcp_event *); /* check_http.c */ void send_http_request(struct ctl_tcp_event *); +/* check_send_expect.c */ +void start_send_expect(struct ctl_tcp_event *); + /* hostated.c */ struct host *host_find(struct hostated *, objid_t); struct table *table_find(struct hostated *, objid_t); diff --git a/usr.sbin/hostated/imsg.c b/usr.sbin/hostated/imsg.c index feafd8700c1..13f136176a8 100644 --- a/usr.sbin/hostated/imsg.c +++ b/usr.sbin/hostated/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.1 2006/12/16 11:45:07 reyk Exp $ */ +/* $OpenBSD: imsg.c,v 1.2 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/parse.y b/usr.sbin/hostated/parse.y index c50e5708cfa..3cb95466a72 100644 --- a/usr.sbin/hostated/parse.y +++ b/usr.sbin/hostated/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.8 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.9 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -40,6 +40,7 @@ #include <stdio.h> #include <netdb.h> #include <string.h> +#include <regex.h> #include "hostated.h" @@ -101,6 +102,7 @@ typedef struct { %token CHECK HTTP HTTPS TCP ICMP EXTERNAL %token TIMEOUT CODE DIGEST PORT TAG INTERFACE %token VIRTUAL IP INTERVAL DISABLE STICKYADDR +%token SEND EXPECT NOTHING %token ERROR %token <v.string> STRING %type <v.string> interface @@ -141,6 +143,20 @@ varset : STRING '=' STRING { } ; +sendbuf : NOTHING { + bzero(table->sendbuf, sizeof(table->sendbuf)); + } + | STRING { + if (strlcpy(table->sendbuf, $1, sizeof(table->sendbuf)) + >= sizeof(table->sendbuf)) { + yyerror("yyparse: send buffer truncated"); + free($1); + YYERROR; + } + free($1); + } + ; + main : INTERVAL number { conf->interval = $2; } | TIMEOUT timeout { bcopy(&$2, &conf->timeout, sizeof(struct timeval)); @@ -361,7 +377,7 @@ tableoptsl : host { YYERROR; } if (strlcpy(table->digest, $5, - sizeof(table->digest)) >= sizeof (table->digest)) { + sizeof(table->digest)) >= sizeof(table->digest)) { yyerror("http digest truncated"); free($3); free($5); @@ -370,6 +386,21 @@ tableoptsl : host { free($3); free($5); } + | CHECK SEND sendbuf EXPECT STRING { + int ret; + char ebuf[32]; + + table->check = CHECK_SEND_EXPECT; + ret = regcomp(&table->regx, $5, REG_EXTENDED|REG_NOSUB); + if (ret != 0) { + regerror(ret, &table->regx, ebuf, sizeof(ebuf)); + yyerror("cannot compile expect regexp: %s", + ebuf); + free($5); + YYERROR; + } + free($5); + } | REAL PORT number { if ($3 < 1 || $3 >= USHRT_MAX) { yyerror("invalid port number: %d", $3); @@ -471,6 +502,7 @@ lookup(char *s) { "code", CODE }, { "digest", DIGEST }, { "disable", DISABLE }, + { "expect", EXPECT }, { "external", EXTERNAL }, { "host", HOST }, { "http", HTTP }, @@ -479,8 +511,10 @@ lookup(char *s) { "interface", INTERFACE }, { "interval", INTERVAL }, { "ip", IP }, + { "nothing", NOTHING }, { "port", PORT }, { "real", REAL }, + { "send", SEND }, { "service", SERVICE }, { "sticky-address", STICKYADDR }, { "table", TABLE }, @@ -528,7 +562,13 @@ lgetc(FILE *f) while ((c = getc(f)) == '\\') { next = getc(f); - if (next != '\n') { + if (next == 'n') { + c = '\n'; + break; + } else if (next == 'r') { + c = '\r'; + break; + } else if (next != '\n') { c = next; break; } diff --git a/usr.sbin/hostated/pfe.c b/usr.sbin/hostated/pfe.c index a4575ad17bd..18bf664347f 100644 --- a/usr.sbin/hostated/pfe.c +++ b/usr.sbin/hostated/pfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe.c,v 1.3 2006/12/16 18:50:33 reyk Exp $ */ +/* $OpenBSD: pfe.c,v 1.4 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hostated/pfe_filter.c b/usr.sbin/hostated/pfe_filter.c index 53f52c06e2a..dba7980325e 100644 --- a/usr.sbin/hostated/pfe_filter.c +++ b/usr.sbin/hostated/pfe_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe_filter.c,v 1.4 2007/01/05 16:39:23 reyk Exp $ */ +/* $OpenBSD: pfe_filter.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -34,6 +34,7 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/Makefile b/usr.sbin/hoststated/Makefile index c04e70f3036..16a06450a62 100644 --- a/usr.sbin/hoststated/Makefile +++ b/usr.sbin/hoststated/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.1 2006/12/16 11:45:07 reyk Exp $ +# $OpenBSD: Makefile,v 1.2 2007/01/08 13:37:26 reyk Exp $ PROG= hostated -SRCS= parse.y log.c control.c buffer.c imsg.c hostated.c \ - pfe.c pfe_filter.c hce.c check_icmp.c check_tcp.c check_http.c +SRCS= parse.y log.c control.c buffer.c imsg.c hostated.c \ + pfe.c pfe_filter.c hce.c \ + check_icmp.c check_tcp.c check_http.c check_send_expect.c MAN= hostated.8 hostated.conf.5 LDADD= -levent diff --git a/usr.sbin/hoststated/buffer.c b/usr.sbin/hoststated/buffer.c index 3abe27b1e62..547d65ed859 100644 --- a/usr.sbin/hoststated/buffer.c +++ b/usr.sbin/hoststated/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.1 2006/12/16 11:45:07 reyk Exp $ */ +/* $OpenBSD: buffer.c,v 1.2 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -29,6 +29,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/check_http.c b/usr.sbin/hoststated/check_http.c index b081c1ce2fa..899a240f7dc 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.4 2006/12/25 19:05:41 reyk Exp $ */ +/* $OpenBSD: check_http.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> * @@ -28,6 +28,7 @@ #include <stdlib.h> #include <unistd.h> #include <fcntl.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/check_icmp.c b/usr.sbin/hoststated/check_icmp.c index 2880d4f5e84..ae18a97cc88 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.5 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: check_icmp.c,v 1.6 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -33,6 +33,7 @@ #include <unistd.h> #include <string.h> #include <stdlib.h> +#include <regex.h> #include "hostated.h" 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); +} diff --git a/usr.sbin/hoststated/check_tcp.c b/usr.sbin/hoststated/check_tcp.c index 93cf8dd7041..888edb8da31 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.4 2006/12/25 19:05:41 reyk Exp $ */ +/* $OpenBSD: check_tcp.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -29,6 +29,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <regex.h> #include "hostated.h" @@ -118,6 +119,8 @@ tcp_write(int s, short event, void *arg) void tcp_host_up(int s, struct ctl_tcp_event *cte) { + cte->s = s; + switch (cte->table->check) { case CHECK_TCP: close(s); @@ -127,6 +130,9 @@ tcp_host_up(int s, struct ctl_tcp_event *cte) case CHECK_HTTP_DIGEST: send_http_request(cte); break; + case CHECK_SEND_EXPECT: + start_send_expect(cte); + break; default: fatalx("tcp_write: unhandled check type"); } diff --git a/usr.sbin/hoststated/control.c b/usr.sbin/hoststated/control.c index 4f58a7654e3..1266b9fd21f 100644 --- a/usr.sbin/hoststated/control.c +++ b/usr.sbin/hoststated/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.4 2006/12/16 18:50:33 reyk Exp $ */ +/* $OpenBSD: control.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <signal.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/hce.c b/usr.sbin/hoststated/hce.c index 6b291036e17..21cfe8a91aa 100644 --- a/usr.sbin/hoststated/hce.c +++ b/usr.sbin/hoststated/hce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hce.c,v 1.4 2006/12/25 18:12:14 reyk Exp $ */ +/* $OpenBSD: hce.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -35,6 +35,7 @@ #include <unistd.h> #include <err.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/hoststated.c b/usr.sbin/hoststated/hoststated.c index d1d8419c785..18d7a33bf71 100644 --- a/usr.sbin/hoststated/hoststated.c +++ b/usr.sbin/hoststated/hoststated.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hoststated.c,v 1.5 2006/12/25 18:40:38 reyk Exp $ */ +/* $OpenBSD: hoststated.c,v 1.6 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -32,6 +32,7 @@ #include <signal.h> #include <unistd.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/hoststated.conf.5 b/usr.sbin/hoststated/hoststated.conf.5 index 3a5e9a671a5..74d3b3d102a 100644 --- a/usr.sbin/hoststated/hoststated.conf.5 +++ b/usr.sbin/hoststated/hoststated.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: hoststated.conf.5,v 1.8 2007/01/03 09:42:30 reyk Exp $ +.\" $OpenBSD: hoststated.conf.5,v 1.9 2007/01/08 13:37:26 reyk Exp $ .\" .\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> .\" @@ -115,6 +115,21 @@ a9993e36476816aba3e25717850c26c9cd0d89d Ping hosts in this table to determine whether they are up or not. This method will automatically use ICMP or ICMPV6 depending on the address family of each host. +.It Ic check send Ar data Ic expect Ar regexp +For each host in the table, a TCP connection is established on the +port specified, then +.Ar data +is sent. +Incoming data is then read and is expected to match against +.Ar regexp. +If +.Ar data +is an empty string or +.Ic nothing +then nothing is sent on the connection and data is immediately +read. +This can be useful with protocols that output a banner like +SMTP, NNTP and FTP. .It Ic check tcp Use a simple TCP connect to check that hosts are up. .It Ic disable diff --git a/usr.sbin/hoststated/hoststated.h b/usr.sbin/hoststated/hoststated.h index f0d6839c4f5..f2555aa6270 100644 --- a/usr.sbin/hoststated/hoststated.h +++ b/usr.sbin/hoststated/hoststated.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hoststated.h,v 1.8 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: hoststated.h,v 1.9 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -190,8 +190,11 @@ struct table { struct timeval timeout; char name[TABLE_NAME_SIZE]; char path[MAXPATHLEN]; + char sendbuf[64]; + char exbuf[64]; char digest[41]; /* length of sha1 digest * 2 */ struct hostlist hosts; + regex_t regx; TAILQ_ENTRY(table) entry; }; TAILQ_HEAD(tablelist, table); @@ -201,6 +204,7 @@ TAILQ_HEAD(tablelist, table); #define CHECK_TCP 2 #define CHECK_HTTP_CODE 3 #define CHECK_HTTP_DIGEST 4 +#define CHECK_SEND_EXPECT 5 struct service { objid_t id; @@ -339,6 +343,9 @@ void check_tcp(struct ctl_tcp_event *); /* check_http.c */ void send_http_request(struct ctl_tcp_event *); +/* check_send_expect.c */ +void start_send_expect(struct ctl_tcp_event *); + /* hostated.c */ struct host *host_find(struct hostated *, objid_t); struct table *table_find(struct hostated *, objid_t); diff --git a/usr.sbin/hoststated/imsg.c b/usr.sbin/hoststated/imsg.c index feafd8700c1..13f136176a8 100644 --- a/usr.sbin/hoststated/imsg.c +++ b/usr.sbin/hoststated/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.1 2006/12/16 11:45:07 reyk Exp $ */ +/* $OpenBSD: imsg.c,v 1.2 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/parse.y b/usr.sbin/hoststated/parse.y index c50e5708cfa..3cb95466a72 100644 --- a/usr.sbin/hoststated/parse.y +++ b/usr.sbin/hoststated/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.8 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.9 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -40,6 +40,7 @@ #include <stdio.h> #include <netdb.h> #include <string.h> +#include <regex.h> #include "hostated.h" @@ -101,6 +102,7 @@ typedef struct { %token CHECK HTTP HTTPS TCP ICMP EXTERNAL %token TIMEOUT CODE DIGEST PORT TAG INTERFACE %token VIRTUAL IP INTERVAL DISABLE STICKYADDR +%token SEND EXPECT NOTHING %token ERROR %token <v.string> STRING %type <v.string> interface @@ -141,6 +143,20 @@ varset : STRING '=' STRING { } ; +sendbuf : NOTHING { + bzero(table->sendbuf, sizeof(table->sendbuf)); + } + | STRING { + if (strlcpy(table->sendbuf, $1, sizeof(table->sendbuf)) + >= sizeof(table->sendbuf)) { + yyerror("yyparse: send buffer truncated"); + free($1); + YYERROR; + } + free($1); + } + ; + main : INTERVAL number { conf->interval = $2; } | TIMEOUT timeout { bcopy(&$2, &conf->timeout, sizeof(struct timeval)); @@ -361,7 +377,7 @@ tableoptsl : host { YYERROR; } if (strlcpy(table->digest, $5, - sizeof(table->digest)) >= sizeof (table->digest)) { + sizeof(table->digest)) >= sizeof(table->digest)) { yyerror("http digest truncated"); free($3); free($5); @@ -370,6 +386,21 @@ tableoptsl : host { free($3); free($5); } + | CHECK SEND sendbuf EXPECT STRING { + int ret; + char ebuf[32]; + + table->check = CHECK_SEND_EXPECT; + ret = regcomp(&table->regx, $5, REG_EXTENDED|REG_NOSUB); + if (ret != 0) { + regerror(ret, &table->regx, ebuf, sizeof(ebuf)); + yyerror("cannot compile expect regexp: %s", + ebuf); + free($5); + YYERROR; + } + free($5); + } | REAL PORT number { if ($3 < 1 || $3 >= USHRT_MAX) { yyerror("invalid port number: %d", $3); @@ -471,6 +502,7 @@ lookup(char *s) { "code", CODE }, { "digest", DIGEST }, { "disable", DISABLE }, + { "expect", EXPECT }, { "external", EXTERNAL }, { "host", HOST }, { "http", HTTP }, @@ -479,8 +511,10 @@ lookup(char *s) { "interface", INTERFACE }, { "interval", INTERVAL }, { "ip", IP }, + { "nothing", NOTHING }, { "port", PORT }, { "real", REAL }, + { "send", SEND }, { "service", SERVICE }, { "sticky-address", STICKYADDR }, { "table", TABLE }, @@ -528,7 +562,13 @@ lgetc(FILE *f) while ((c = getc(f)) == '\\') { next = getc(f); - if (next != '\n') { + if (next == 'n') { + c = '\n'; + break; + } else if (next == 'r') { + c = '\r'; + break; + } else if (next != '\n') { c = next; break; } diff --git a/usr.sbin/hoststated/pfe.c b/usr.sbin/hoststated/pfe.c index a4575ad17bd..18bf664347f 100644 --- a/usr.sbin/hoststated/pfe.c +++ b/usr.sbin/hoststated/pfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe.c,v 1.3 2006/12/16 18:50:33 reyk Exp $ */ +/* $OpenBSD: pfe.c,v 1.4 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/hoststated/pfe_filter.c b/usr.sbin/hoststated/pfe_filter.c index 53f52c06e2a..dba7980325e 100644 --- a/usr.sbin/hoststated/pfe_filter.c +++ b/usr.sbin/hoststated/pfe_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe_filter.c,v 1.4 2007/01/05 16:39:23 reyk Exp $ */ +/* $OpenBSD: pfe_filter.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -34,6 +34,7 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/Makefile b/usr.sbin/relayd/Makefile index c04e70f3036..16a06450a62 100644 --- a/usr.sbin/relayd/Makefile +++ b/usr.sbin/relayd/Makefile @@ -1,8 +1,9 @@ -# $OpenBSD: Makefile,v 1.1 2006/12/16 11:45:07 reyk Exp $ +# $OpenBSD: Makefile,v 1.2 2007/01/08 13:37:26 reyk Exp $ PROG= hostated -SRCS= parse.y log.c control.c buffer.c imsg.c hostated.c \ - pfe.c pfe_filter.c hce.c check_icmp.c check_tcp.c check_http.c +SRCS= parse.y log.c control.c buffer.c imsg.c hostated.c \ + pfe.c pfe_filter.c hce.c \ + check_icmp.c check_tcp.c check_http.c check_send_expect.c MAN= hostated.8 hostated.conf.5 LDADD= -levent diff --git a/usr.sbin/relayd/buffer.c b/usr.sbin/relayd/buffer.c index 3abe27b1e62..547d65ed859 100644 --- a/usr.sbin/relayd/buffer.c +++ b/usr.sbin/relayd/buffer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: buffer.c,v 1.1 2006/12/16 11:45:07 reyk Exp $ */ +/* $OpenBSD: buffer.c,v 1.2 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -29,6 +29,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/check_icmp.c b/usr.sbin/relayd/check_icmp.c index 2880d4f5e84..ae18a97cc88 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.5 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: check_icmp.c,v 1.6 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -33,6 +33,7 @@ #include <unistd.h> #include <string.h> #include <stdlib.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/check_tcp.c b/usr.sbin/relayd/check_tcp.c index 93cf8dd7041..888edb8da31 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.4 2006/12/25 19:05:41 reyk Exp $ */ +/* $OpenBSD: check_tcp.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -29,6 +29,7 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <regex.h> #include "hostated.h" @@ -118,6 +119,8 @@ tcp_write(int s, short event, void *arg) void tcp_host_up(int s, struct ctl_tcp_event *cte) { + cte->s = s; + switch (cte->table->check) { case CHECK_TCP: close(s); @@ -127,6 +130,9 @@ tcp_host_up(int s, struct ctl_tcp_event *cte) case CHECK_HTTP_DIGEST: send_http_request(cte); break; + case CHECK_SEND_EXPECT: + start_send_expect(cte); + break; default: fatalx("tcp_write: unhandled check type"); } diff --git a/usr.sbin/relayd/control.c b/usr.sbin/relayd/control.c index 4f58a7654e3..1266b9fd21f 100644 --- a/usr.sbin/relayd/control.c +++ b/usr.sbin/relayd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.4 2006/12/16 18:50:33 reyk Exp $ */ +/* $OpenBSD: control.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <signal.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/hce.c b/usr.sbin/relayd/hce.c index 6b291036e17..21cfe8a91aa 100644 --- a/usr.sbin/relayd/hce.c +++ b/usr.sbin/relayd/hce.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hce.c,v 1.4 2006/12/25 18:12:14 reyk Exp $ */ +/* $OpenBSD: hce.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -35,6 +35,7 @@ #include <unistd.h> #include <err.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/imsg.c b/usr.sbin/relayd/imsg.c index feafd8700c1..13f136176a8 100644 --- a/usr.sbin/relayd/imsg.c +++ b/usr.sbin/relayd/imsg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: imsg.c,v 1.1 2006/12/16 11:45:07 reyk Exp $ */ +/* $OpenBSD: imsg.c,v 1.2 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/parse.y b/usr.sbin/relayd/parse.y index c50e5708cfa..3cb95466a72 100644 --- a/usr.sbin/relayd/parse.y +++ b/usr.sbin/relayd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.8 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.9 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -40,6 +40,7 @@ #include <stdio.h> #include <netdb.h> #include <string.h> +#include <regex.h> #include "hostated.h" @@ -101,6 +102,7 @@ typedef struct { %token CHECK HTTP HTTPS TCP ICMP EXTERNAL %token TIMEOUT CODE DIGEST PORT TAG INTERFACE %token VIRTUAL IP INTERVAL DISABLE STICKYADDR +%token SEND EXPECT NOTHING %token ERROR %token <v.string> STRING %type <v.string> interface @@ -141,6 +143,20 @@ varset : STRING '=' STRING { } ; +sendbuf : NOTHING { + bzero(table->sendbuf, sizeof(table->sendbuf)); + } + | STRING { + if (strlcpy(table->sendbuf, $1, sizeof(table->sendbuf)) + >= sizeof(table->sendbuf)) { + yyerror("yyparse: send buffer truncated"); + free($1); + YYERROR; + } + free($1); + } + ; + main : INTERVAL number { conf->interval = $2; } | TIMEOUT timeout { bcopy(&$2, &conf->timeout, sizeof(struct timeval)); @@ -361,7 +377,7 @@ tableoptsl : host { YYERROR; } if (strlcpy(table->digest, $5, - sizeof(table->digest)) >= sizeof (table->digest)) { + sizeof(table->digest)) >= sizeof(table->digest)) { yyerror("http digest truncated"); free($3); free($5); @@ -370,6 +386,21 @@ tableoptsl : host { free($3); free($5); } + | CHECK SEND sendbuf EXPECT STRING { + int ret; + char ebuf[32]; + + table->check = CHECK_SEND_EXPECT; + ret = regcomp(&table->regx, $5, REG_EXTENDED|REG_NOSUB); + if (ret != 0) { + regerror(ret, &table->regx, ebuf, sizeof(ebuf)); + yyerror("cannot compile expect regexp: %s", + ebuf); + free($5); + YYERROR; + } + free($5); + } | REAL PORT number { if ($3 < 1 || $3 >= USHRT_MAX) { yyerror("invalid port number: %d", $3); @@ -471,6 +502,7 @@ lookup(char *s) { "code", CODE }, { "digest", DIGEST }, { "disable", DISABLE }, + { "expect", EXPECT }, { "external", EXTERNAL }, { "host", HOST }, { "http", HTTP }, @@ -479,8 +511,10 @@ lookup(char *s) { "interface", INTERFACE }, { "interval", INTERVAL }, { "ip", IP }, + { "nothing", NOTHING }, { "port", PORT }, { "real", REAL }, + { "send", SEND }, { "service", SERVICE }, { "sticky-address", STICKYADDR }, { "table", TABLE }, @@ -528,7 +562,13 @@ lgetc(FILE *f) while ((c = getc(f)) == '\\') { next = getc(f); - if (next != '\n') { + if (next == 'n') { + c = '\n'; + break; + } else if (next == 'r') { + c = '\r'; + break; + } else if (next != '\n') { c = next; break; } diff --git a/usr.sbin/relayd/pfe.c b/usr.sbin/relayd/pfe.c index a4575ad17bd..18bf664347f 100644 --- a/usr.sbin/relayd/pfe.c +++ b/usr.sbin/relayd/pfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe.c,v 1.3 2006/12/16 18:50:33 reyk Exp $ */ +/* $OpenBSD: pfe.c,v 1.4 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -30,6 +30,7 @@ #include <string.h> #include <unistd.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/pfe_filter.c b/usr.sbin/relayd/pfe_filter.c index 53f52c06e2a..dba7980325e 100644 --- a/usr.sbin/relayd/pfe_filter.c +++ b/usr.sbin/relayd/pfe_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfe_filter.c,v 1.4 2007/01/05 16:39:23 reyk Exp $ */ +/* $OpenBSD: pfe_filter.c,v 1.5 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -34,6 +34,7 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c index 90648bfc898..ef75a4c755e 100644 --- a/usr.sbin/relayd/relayd.c +++ b/usr.sbin/relayd/relayd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.c,v 1.5 2006/12/25 18:40:38 reyk Exp $ */ +/* $OpenBSD: relayd.c,v 1.6 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -32,6 +32,7 @@ #include <signal.h> #include <unistd.h> #include <pwd.h> +#include <regex.h> #include "hostated.h" diff --git a/usr.sbin/relayd/relayd.conf.5 b/usr.sbin/relayd/relayd.conf.5 index 48c805c0b2c..8445a43ef08 100644 --- a/usr.sbin/relayd/relayd.conf.5 +++ b/usr.sbin/relayd/relayd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: relayd.conf.5,v 1.8 2007/01/03 09:42:30 reyk Exp $ +.\" $OpenBSD: relayd.conf.5,v 1.9 2007/01/08 13:37:26 reyk Exp $ .\" .\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> .\" @@ -115,6 +115,21 @@ a9993e36476816aba3e25717850c26c9cd0d89d Ping hosts in this table to determine whether they are up or not. This method will automatically use ICMP or ICMPV6 depending on the address family of each host. +.It Ic check send Ar data Ic expect Ar regexp +For each host in the table, a TCP connection is established on the +port specified, then +.Ar data +is sent. +Incoming data is then read and is expected to match against +.Ar regexp. +If +.Ar data +is an empty string or +.Ic nothing +then nothing is sent on the connection and data is immediately +read. +This can be useful with protocols that output a banner like +SMTP, NNTP and FTP. .It Ic check tcp Use a simple TCP connect to check that hosts are up. .It Ic disable diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h index c8f02dc181f..f6dbe7bfc28 100644 --- a/usr.sbin/relayd/relayd.h +++ b/usr.sbin/relayd/relayd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.h,v 1.8 2007/01/03 09:45:29 reyk Exp $ */ +/* $OpenBSD: relayd.h,v 1.9 2007/01/08 13:37:26 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@spootnik.org> @@ -190,8 +190,11 @@ struct table { struct timeval timeout; char name[TABLE_NAME_SIZE]; char path[MAXPATHLEN]; + char sendbuf[64]; + char exbuf[64]; char digest[41]; /* length of sha1 digest * 2 */ struct hostlist hosts; + regex_t regx; TAILQ_ENTRY(table) entry; }; TAILQ_HEAD(tablelist, table); @@ -201,6 +204,7 @@ TAILQ_HEAD(tablelist, table); #define CHECK_TCP 2 #define CHECK_HTTP_CODE 3 #define CHECK_HTTP_DIGEST 4 +#define CHECK_SEND_EXPECT 5 struct service { objid_t id; @@ -339,6 +343,9 @@ void check_tcp(struct ctl_tcp_event *); /* check_http.c */ void send_http_request(struct ctl_tcp_event *); +/* check_send_expect.c */ +void start_send_expect(struct ctl_tcp_event *); + /* hostated.c */ struct host *host_find(struct hostated *, objid_t); struct table *table_find(struct hostated *, objid_t); |