summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2007-12-07 17:27:05 +0000
committerderaadt <deraadt@openbsd.org>2007-12-07 17:27:05 +0000
commit84c0bb2c27b61f2fe5a2c1cb7fc6cbe1863db6a2 (patch)
tree7b6b728962355d5a400f4590a99302b7a73e44f8
parentoops, _relayd not _relay; spotted by reyk (diff)
downloadwireguard-openbsd-84c0bb2c27b61f2fe5a2c1cb7fc6cbe1863db6a2.tar.xz
wireguard-openbsd-84c0bb2c27b61f2fe5a2c1cb7fc6cbe1863db6a2.zip
hoststated/hoststatectl get repository copied (and de-tagged) into
relayd/relayctl. This is a more suitable place for a daemon that has grown out of it's initial roots of "monitoring and redirecting services at various layers", into one that is "a full featured proxy, which happens to know what is up/down"
-rw-r--r--usr.sbin/hoststatectl/Makefile16
-rw-r--r--usr.sbin/hoststatectl/hoststatectl.894
-rw-r--r--usr.sbin/hoststatectl/hoststatectl.c499
-rw-r--r--usr.sbin/hoststatectl/parser.c261
-rw-r--r--usr.sbin/hoststatectl/parser.h44
-rw-r--r--usr.sbin/hoststated/Makefile18
-rw-r--r--usr.sbin/hoststated/buffer.c244
-rw-r--r--usr.sbin/hoststated/carp.c217
-rw-r--r--usr.sbin/hoststated/check_icmp.c368
-rw-r--r--usr.sbin/hoststated/check_script.c167
-rw-r--r--usr.sbin/hoststated/check_tcp.c385
-rw-r--r--usr.sbin/hoststated/control.c392
-rw-r--r--usr.sbin/hoststated/hce.c515
-rw-r--r--usr.sbin/hoststated/hoststated.8146
-rw-r--r--usr.sbin/hoststated/hoststated.c971
-rw-r--r--usr.sbin/hoststated/hoststated.conf.5965
-rw-r--r--usr.sbin/hoststated/hoststated.h810
-rw-r--r--usr.sbin/hoststated/imsg.c233
-rw-r--r--usr.sbin/hoststated/log.c302
-rw-r--r--usr.sbin/hoststated/name2id.c177
-rw-r--r--usr.sbin/hoststated/parse.y2158
-rw-r--r--usr.sbin/hoststated/pfe.c910
-rw-r--r--usr.sbin/hoststated/pfe_filter.c478
-rw-r--r--usr.sbin/hoststated/relay.c2924
-rw-r--r--usr.sbin/hoststated/relay_udp.c469
-rw-r--r--usr.sbin/hoststated/ssl.c296
-rw-r--r--usr.sbin/hoststated/ssl_privsep.c170
27 files changed, 0 insertions, 14229 deletions
diff --git a/usr.sbin/hoststatectl/Makefile b/usr.sbin/hoststatectl/Makefile
deleted file mode 100644
index f2260e3e920..00000000000
--- a/usr.sbin/hoststatectl/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# $OpenBSD: Makefile,v 1.2 2007/01/09 00:45:32 deraadt Exp $
-
-.PATH: ${.CURDIR}/../hoststated
-
-PROG= hoststatectl
-SRCS= buffer.c imsg.c log.c hoststatectl.c parser.c
-
-MAN= hoststatectl.8
-
-CFLAGS+= -Wall -Werror -I${.CURDIR} -I${.CURDIR}/../hoststated
-CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
-CFLAGS+= -Wmissing-declarations
-CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
-CFLAGS+= -Wsign-compare -Wbounded
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/hoststatectl/hoststatectl.8 b/usr.sbin/hoststatectl/hoststatectl.8
deleted file mode 100644
index 6d01526f3b2..00000000000
--- a/usr.sbin/hoststatectl/hoststatectl.8
+++ /dev/null
@@ -1,94 +0,0 @@
-.\" $OpenBSD: hoststatectl.8,v 1.14 2007/11/21 09:55:21 pyr Exp $
-.\"
-.\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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.
-.\"
-.Dd $Mdocdate: November 21 2007 $
-.Dt HOSTSTATECTL 8
-.Os
-.Sh NAME
-.Nm hoststatectl
-.Nd control the Host Status daemon
-.Sh SYNOPSIS
-.Nm
-.Ar command
-.Op Ar arguments ...
-.Sh DESCRIPTION
-The
-.Nm
-program controls the
-.Xr hoststated 8
-daemon.
-.Pp
-The following commands are available:
-.Bl -tag -width Ds
-.It Cm host disable Op Ar name | id
-Disable a host.
-Treat it as though it were always down.
-.It Cm host enable Op Ar name | id
-Enable the host.
-Start checking its health again.
-.It Cm monitor
-Continuously report any changes in the host checking engine and the
-pf engine.
-.It Cm poll
-Schedule an immediate check of all hosts.
-.It Cm reload
-Reload the configuration file.
-.It Cm service disable Op Ar name | id
-Disable a service.
-If it has
-.Xr pf 4
-redirection rules installed, remove them.
-Mark the service's main table and \(en
-if applicable \(en backup table disabled as well.
-.It Cm service enable Op Ar name | id
-Enable a service.
-Mark the service's main table and \(en if applicable \(en backup
-table enabled as well.
-.It Cm show hosts
-Show detailed status of hosts, tables, and services.
-.It Cm show relays
-Show detailed status of relays including the current and average
-access statistics.
-The statistics will be updated every minute.
-.It Cm show sessions
-Dump the complete list of running relay sessions.
-.It Cm show summary
-Display a list of all relays, services, tables, and hosts.
-.It Cm table disable Op Ar name | id
-Disable a table.
-Consider all hosts disabled.
-If it is a main table of a service which has a non-empty backup table,
-swap the contents of the
-.Xr pf 4
-table with those of the backup table.
-.It Cm table enable Op Ar name | id
-Enable a table.
-Start doing checks for all hosts that aren't individually disabled
-again.
-.El
-.Sh FILES
-.Bl -tag -width "/var/run/hoststated.sockXX" -compact
-.It /var/run/hoststated.sock
-Unix-domain socket used for communication with
-.Xr hoststated 8 .
-.El
-.Sh SEE ALSO
-.Xr hoststated 8
-.Sh HISTORY
-The
-.Nm
-program first appeared in
-.Ox 4.1 .
diff --git a/usr.sbin/hoststatectl/hoststatectl.c b/usr.sbin/hoststatectl/hoststatectl.c
deleted file mode 100644
index 2ce1db20476..00000000000
--- a/usr.sbin/hoststatectl/hoststatectl.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/* $OpenBSD: hoststatectl.c,v 1.27 2007/11/24 17:09:12 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
- * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
- * Copyright (c) 2003 Henning Brauer <henning@openbsd.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/socket.h>
-#include <sys/queue.h>
-#include <sys/un.h>
-
-#include <net/if.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <event.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-#include "parser.h"
-
-__dead void usage(void);
-int show_summary_msg(struct imsg *, int);
-int show_session_msg(struct imsg *);
-int show_command_output(struct imsg *);
-char *print_service_status(int);
-char *print_host_status(int, int);
-char *print_table_status(int, int);
-char *print_relay_status(int);
-
-struct imsgname {
- int type;
- char *name;
- void (*func)(struct imsg *);
-};
-
-struct imsgname *monitor_lookup(u_int8_t);
-void monitor_host_status(struct imsg *);
-void monitor_id(struct imsg *);
-int monitor(struct imsg *);
-
-struct imsgname imsgs[] = {
- { IMSG_HOST_STATUS, "host_status", monitor_host_status },
- { IMSG_CTL_SERVICE_DISABLE, "ctl_disable_service", monitor_id },
- { IMSG_CTL_SERVICE_ENABLE, "ctl_service_enable", monitor_id },
- { IMSG_CTL_TABLE_DISABLE, "ctl_table_disable", monitor_id },
- { IMSG_CTL_TABLE_ENABLE, "ctl_table_enable", monitor_id },
- { IMSG_CTL_HOST_DISABLE, "ctl_host_disable", monitor_id },
- { IMSG_CTL_HOST_ENABLE, "ctl_host_enable", monitor_id },
- { IMSG_CTL_TABLE_CHANGED, "ctl_table_changed", monitor_id },
- { IMSG_CTL_PULL_RULESET, "ctl_pull_ruleset", monitor_id },
- { IMSG_CTL_PUSH_RULESET, "ctl_push_ruleset", monitor_id },
- { IMSG_SYNC, "sync", NULL },
- { 0, NULL, NULL }
-};
-struct imsgname imsgunknown = {
- -1, "<unknown>", NULL
-};
-
-struct imsgbuf *ibuf;
-
-__dead void
-usage(void)
-{
- extern char *__progname;
-
- fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname);
- exit(1);
-}
-
-/* dummy function so that hoststatectl does not need libevent */
-void
-imsg_event_add(struct imsgbuf *i)
-{
- /* nothing */
-}
-
-int
-main(int argc, char *argv[])
-{
- struct sockaddr_un sun;
- struct parse_result *res;
- struct imsg imsg;
- int ctl_sock;
- int done = 0;
- int n;
-
- /* parse options */
- if ((res = parse(argc - 1, argv + 1)) == NULL)
- exit(1);
-
- /* connect to hoststated control socket */
- if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
- err(1, "socket");
-
- bzero(&sun, sizeof(sun));
- sun.sun_family = AF_UNIX;
- strlcpy(sun.sun_path, HOSTSTATED_SOCKET, sizeof(sun.sun_path));
- reconnect:
- if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
- /* Keep retrying if running in monitor mode */
- if (res->action == MONITOR &&
- (errno == ENOENT || errno == ECONNREFUSED)) {
- usleep(100);
- goto reconnect;
- }
- err(1, "connect: %s", HOSTSTATED_SOCKET);
- }
-
- if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
- err(1, NULL);
- imsg_init(ibuf, ctl_sock, NULL);
- done = 0;
-
- /* process user request */
- switch (res->action) {
- case NONE:
- usage();
- /* not reached */
- case SHOW_SUM:
- case SHOW_HOSTS:
- case SHOW_RELAYS:
- imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
- printf("Type\t%4s\t%-24s\t%-7s\tStatus\n",
- "Id", "Name", "Avlblty");
- break;
- case SHOW_SESSIONS:
- imsg_compose(ibuf, IMSG_CTL_SESSION, 0, 0, -1, NULL, 0);
- break;
- case SERV_ENABLE:
- imsg_compose(ibuf, IMSG_CTL_SERVICE_ENABLE, 0, 0, -1,
- &res->id, sizeof(res->id));
- break;
- case SERV_DISABLE:
- imsg_compose(ibuf, IMSG_CTL_SERVICE_DISABLE, 0, 0, -1,
- &res->id, sizeof(res->id));
- break;
- case TABLE_ENABLE:
- imsg_compose(ibuf, IMSG_CTL_TABLE_ENABLE, 0, 0, -1,
- &res->id, sizeof(res->id));
- break;
- case TABLE_DISABLE:
- imsg_compose(ibuf, IMSG_CTL_TABLE_DISABLE, 0, 0, -1,
- &res->id, sizeof(res->id));
- break;
- case HOST_ENABLE:
- imsg_compose(ibuf, IMSG_CTL_HOST_ENABLE, 0, 0, -1,
- &res->id, sizeof(res->id));
- break;
- case HOST_DISABLE:
- imsg_compose(ibuf, IMSG_CTL_HOST_DISABLE, 0, 0, -1,
- &res->id, sizeof(res->id));
- break;
- case SHUTDOWN:
- imsg_compose(ibuf, IMSG_CTL_SHUTDOWN, 0, 0, -1, NULL, 0);
- break;
- case POLL:
- imsg_compose(ibuf, IMSG_CTL_POLL, 0, 0, -1, NULL, 0);
- break;
- case RELOAD:
- imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
- break;
- case MONITOR:
- imsg_compose(ibuf, IMSG_CTL_NOTIFY, 0, 0, -1, NULL, 0);
- break;
- }
-
- while (ibuf->w.queued)
- if (msgbuf_write(&ibuf->w) < 0)
- err(1, "write error");
-
- while (!done) {
- if ((n = imsg_read(ibuf)) == -1)
- errx(1, "imsg_read error");
- if (n == 0)
- errx(1, "pipe closed");
-
- while (!done) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- errx(1, "imsg_get error");
- if (n == 0)
- break;
- switch (res->action) {
- case SHOW_SUM:
- case SHOW_HOSTS:
- case SHOW_RELAYS:
- done = show_summary_msg(&imsg, res->action);
- break;
- case SHOW_SESSIONS:
- done = show_session_msg(&imsg);
- break;
- case SERV_DISABLE:
- case SERV_ENABLE:
- case TABLE_DISABLE:
- case TABLE_ENABLE:
- case HOST_DISABLE:
- case HOST_ENABLE:
- case POLL:
- case RELOAD:
- case SHUTDOWN:
- done = show_command_output(&imsg);
- break;
- case NONE:
- break;
- case MONITOR:
- done = monitor(&imsg);
- break;
- }
- imsg_free(&imsg);
- }
- }
- close(ctl_sock);
- free(ibuf);
-
- return (0);
-}
-
-struct imsgname *
-monitor_lookup(u_int8_t type)
-{
- int i;
-
- for (i = 0; imsgs[i].name != NULL; i++)
- if (imsgs[i].type == type)
- return (&imsgs[i]);
- return (&imsgunknown);
-}
-
-void
-monitor_host_status(struct imsg *imsg)
-{
- struct ctl_status cs;
-
- memcpy(&cs, imsg->data, sizeof(cs));
- printf("\tid: %u\n", cs.id);
- printf("\tstate: ");
- switch (cs.up) {
- case HOST_UP:
- printf("up\n");
- break;
- case HOST_DOWN:
- printf("down\n");
- break;
- default:
- printf("unknown\n");
- break;
- }
-}
-
-void
-monitor_id(struct imsg *imsg)
-{
- struct ctl_id id;
-
- memcpy(&id, imsg->data, sizeof(id));
- printf("\tid: %u\n", id.id);
- if (strlen(id.name))
- printf("\tname: %s\n", id.name);
-}
-
-int
-monitor(struct imsg *imsg)
-{
- time_t now;
- int done = 0;
- struct imsgname *imn;
-
- now = time(NULL);
-
- imn = monitor_lookup(imsg->hdr.type);
- printf("%s: imsg type %u len %u peerid %u pid %d\n", imn->name,
- imsg->hdr.type, imsg->hdr.len, imsg->hdr.peerid, imsg->hdr.pid);
- printf("\ttimestamp: %u, %s", now, ctime(&now));
- if (imn->type == -1)
- done = 1;
- if (imn->func != NULL)
- (*imn->func)(imsg);
-
- return (done);
-}
-
-int
-show_summary_msg(struct imsg *imsg, int type)
-{
- struct service *service;
- struct table *table;
- struct host *host;
- struct relay *rlay;
- struct ctl_stats stats[RELAY_MAXPROC], crs;
- int i;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_SERVICE:
- if (type == SHOW_RELAYS)
- break;
- service = imsg->data;
- printf("service\t%4u\t%-24s\t%-7s\t%s\n",
- service->conf.id, service->conf.name, "",
- print_service_status(service->conf.flags));
- break;
- case IMSG_CTL_TABLE:
- if (type == SHOW_RELAYS)
- break;
- table = imsg->data;
- printf("table\t%4u\t%-24s\t%-7s\t%s\n",
- table->conf.id, table->conf.name, "",
- print_table_status(table->up, table->conf.flags));
- break;
- case IMSG_CTL_HOST:
- if (type == SHOW_RELAYS)
- break;
- host = imsg->data;
- printf("host\t%4u\t%-24s\t%-7s\t%s\n",
- host->conf.id, host->conf.name,
- print_availability(host->check_cnt, host->up_cnt),
- print_host_status(host->up, host->flags));
- if (type == SHOW_HOSTS && host->check_cnt) {
- printf("\t%4s\ttotal: %lu/%lu checks",
- "", host->up_cnt, host->check_cnt);
- if (host->retry_cnt)
- printf(", %d retries", host->retry_cnt);
- printf("\n");
- }
- break;
- case IMSG_CTL_RELAY:
- if (type == SHOW_HOSTS)
- break;
- rlay = imsg->data;
- printf("relay\t%4u\t%-24s\t%-7s\t%s\n",
- rlay->conf.id, rlay->conf.name, "",
- print_relay_status(rlay->conf.flags));
- break;
- case IMSG_CTL_STATISTICS:
- if (type != SHOW_RELAYS)
- break;
- bcopy(imsg->data, &stats, sizeof(stats));
- bzero(&crs, sizeof(crs));
- crs.interval = stats[0].interval;
- for (i = 0; stats[i].id != EMPTY_ID; i++) {
- crs.cnt += stats[i].cnt;
- crs.last += stats[i].last;
- crs.avg += stats[i].avg;
- crs.last_hour += stats[i].last_hour;
- crs.avg_hour += stats[i].avg_hour;
- crs.last_day += stats[i].last_day;
- crs.avg_day += stats[i].avg_day;
- }
- if (crs.cnt == 0)
- break;
- printf("\t%4s\ttotal: %lu sessions\n"
- "\t%4s\tlast: %lu/%us %lu/h %lu/d sessions\n"
- "\t%4s\taverage: %lu/%us %lu/h %lu/d sessions\n",
- "", crs.cnt,
- "", crs.last, crs.interval,
- crs.last_hour, crs.last_day,
- "", crs.avg, crs.interval,
- crs.avg_hour, crs.avg_day);
- break;
- case IMSG_CTL_END:
- return (1);
- default:
- errx(1, "wrong message in summary: %u", imsg->hdr.type);
- break;
- }
- return (0);
-}
-
-int
-show_session_msg(struct imsg *imsg)
-{
- struct session *con;
- char a[128], b[128];
- struct timeval tv_now;
-
- switch (imsg->hdr.type) {
- case IMSG_CTL_SESSION:
- con = imsg->data;
-
- (void)print_host(&con->in.ss, a, sizeof(a));
- (void)print_host(&con->out.ss, b, sizeof(b));
- printf("session %u:%u %s:%u -> %s:%u\t%s\n",
- imsg->hdr.peerid, con->id,
- a, ntohs(con->in.port), b, ntohs(con->out.port),
- con->done ? "DONE" : "RUNNING");
-
- if (gettimeofday(&tv_now, NULL))
- fatal("show_session_msg: gettimeofday");
- print_time(&tv_now, &con->tv_start, a, sizeof(a));
- print_time(&tv_now, &con->tv_last, b, sizeof(b));
- printf("\tage %s, idle %s, relay %u", a, b, con->relayid);
- if (con->mark)
- printf(", mark %u", con->mark);
- printf("\n");
- break;
- case IMSG_CTL_END:
- return (1);
- default:
- errx(1, "wrong message in session: %u", imsg->hdr.type);
- break;
- }
- return (0);
-}
-
-int
-show_command_output(struct imsg *imsg)
-{
- switch (imsg->hdr.type) {
- case IMSG_CTL_OK:
- printf("command succeeded\n");
- break;
- case IMSG_CTL_FAIL:
- printf("command failed\n");
- break;
- default:
- errx(1, "wrong message in summary: %u", imsg->hdr.type);
- }
- return (1);
-}
-
-char *
-print_service_status(int flags)
-{
- if (flags & F_DISABLE) {
- return ("disabled");
- } else if (flags & F_DOWN) {
- return ("down");
- } else if (flags & F_BACKUP) {
- return ("active (using backup table)");
- } else
- return ("active");
-}
-
-char *
-print_table_status(int up, int fl)
-{
- static char buf[1024];
-
- bzero(buf, sizeof(buf));
-
- if (fl & F_DISABLE) {
- snprintf(buf, sizeof(buf) - 1, "disabled");
- } else if (!up) {
- snprintf(buf, sizeof(buf) - 1, "empty");
- } else
- snprintf(buf, sizeof(buf) - 1, "active (%d hosts up)", up);
- return (buf);
-}
-
-char *
-print_host_status(int status, int fl)
-{
- if (fl & F_DISABLE)
- return ("disabled");
-
- switch (status) {
- case HOST_DOWN:
- return ("down");
- case HOST_UNKNOWN:
- return ("unknown");
- case HOST_UP:
- return ("up");
- default:
- errx(1, "invalid status: %d", status);
- }
-}
-
-char *
-print_relay_status(int flags)
-{
- if (flags & F_DISABLE) {
- return ("disabled");
- } else
- return ("active");
-}
-
diff --git a/usr.sbin/hoststatectl/parser.c b/usr.sbin/hoststatectl/parser.c
deleted file mode 100644
index ec70d997eb8..00000000000
--- a/usr.sbin/hoststatectl/parser.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* $OpenBSD: parser.c,v 1.16 2007/11/24 17:09:12 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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/socket.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <err.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <event.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-#include "parser.h"
-
-enum token_type {
- NOTOKEN,
- ENDTOKEN,
- HOSTID,
- TABLEID,
- SERVICEID,
- KEYWORD
-};
-
-struct token {
- enum token_type type;
- const char *keyword;
- int value;
- const struct token *next;
-};
-
-static const struct token t_main[];
-static const struct token t_show[];
-static const struct token t_service[];
-static const struct token t_table[];
-static const struct token t_host[];
-static const struct token t_service_id[];
-static const struct token t_table_id[];
-static const struct token t_host_id[];
-
-static const struct token t_main[] = {
- {KEYWORD, "monitor", MONITOR, NULL},
- {KEYWORD, "show", NONE, t_show},
- {KEYWORD, "poll", POLL, NULL},
- {KEYWORD, "reload", RELOAD, NULL},
- {KEYWORD, "stop", SHUTDOWN, NULL},
- {KEYWORD, "service", NONE, t_service},
- {KEYWORD, "table", NONE, t_table},
- {KEYWORD, "host", NONE, t_host},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_show[] = {
- {KEYWORD, "summary", SHOW_SUM, NULL},
- {KEYWORD, "hosts", SHOW_HOSTS, NULL},
- {KEYWORD, "relays", SHOW_RELAYS, NULL},
- {KEYWORD, "sessions", SHOW_SESSIONS, NULL},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_service[] = {
- {NOTOKEN, "", NONE, NULL},
- {KEYWORD, "disable", SERV_DISABLE, t_service_id},
- {KEYWORD, "enable", SERV_ENABLE, t_service_id},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_table[] = {
- {NOTOKEN, "", NONE, NULL},
- {KEYWORD, "disable", TABLE_DISABLE, t_table_id},
- {KEYWORD, "enable", TABLE_ENABLE, t_table_id},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_host[] = {
- {NOTOKEN, "", NONE, NULL},
- {KEYWORD, "disable", HOST_DISABLE, t_host_id},
- {KEYWORD, "enable", HOST_ENABLE, t_host_id},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_service_id[] = {
- {SERVICEID, "", NONE, NULL},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_table_id[] = {
- {TABLEID, "", NONE, NULL},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static const struct token t_host_id[] = {
- {HOSTID, "", NONE, NULL},
- {ENDTOKEN, "", NONE, NULL}
-};
-
-static struct parse_result res;
-
-struct parse_result *
-parse(int argc, char *argv[])
-{
- const struct token *table = t_main;
- const struct token *match;
-
- bzero(&res, sizeof(res));
-
- while (argc >= 0) {
- if ((match = match_token(argv[0], table)) == NULL) {
- fprintf(stderr, "valid commands/args:\n");
- show_valid_args(table);
- return (NULL);
- }
-
- argc--;
- argv++;
-
- if (match->type == NOTOKEN || match->next == NULL)
- break;
-
- table = match->next;
- }
-
- if (argc > 0) {
- fprintf(stderr, "superfluous argument: %s\n", argv[0]);
- return (NULL);
- }
-
- return (&res);
-}
-
-const struct token *
-match_token(const char *word, const struct token table[])
-{
- u_int i, match;
- const struct token *t = NULL;
- const char *errstr;
-
- match = 0;
-
- for (i = 0; table[i].type != ENDTOKEN; i++) {
- switch (table[i].type) {
- case NOTOKEN:
- if (word == NULL || strlen(word) == 0) {
- match++;
- t = &table[i];
- }
- break;
- case KEYWORD:
- if (word != NULL && strncmp(word, table[i].keyword,
- strlen(word)) == 0) {
- match++;
- t = &table[i];
- if (t->value)
- res.action = t->value;
- }
- break;
- case HOSTID:
- if (word == NULL)
- break;
- res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
- if (errstr) {
- strlcpy(res.id.name, word, sizeof(res.id.name));
- res.id.id = EMPTY_ID;
- }
- t = &table[i];
- match++;
- break;
- case TABLEID:
- if (word == NULL)
- break;
- res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
- if (errstr) {
- strlcpy(res.id.name, word, sizeof(res.id.name));
- res.id.id = EMPTY_ID;
- }
- t = &table[i];
- match++;
- break;
- case SERVICEID:
- if (word == NULL)
- break;
- res.id.id = strtonum(word, 0, UINT_MAX, &errstr);
- if (errstr) {
- strlcpy(res.id.name, word, sizeof(res.id.name));
- res.id.id = EMPTY_ID;
- }
- t = &table[i];
- match++;
- break;
- case ENDTOKEN:
- break;
- }
- }
-
- if (match != 1) {
- if (word == NULL)
- fprintf(stderr, "missing argument:\n");
- else if (match > 1)
- fprintf(stderr, "ambiguous argument: %s\n", word);
- else if (match < 1)
- fprintf(stderr, "unknown argument: %s\n", word);
- return (NULL);
- }
-
- return (t);
-}
-
-void
-show_valid_args(const struct token table[])
-{
- int i;
-
- for (i = 0; table[i].type != ENDTOKEN; i++) {
- switch (table[i].type) {
- case NOTOKEN:
- fprintf(stderr, " <cr>\n");
- break;
- case KEYWORD:
- fprintf(stderr, " %s\n", table[i].keyword);
- break;
- case SERVICEID:
- fprintf(stderr, " <serviceid>\n");
- break;
- case TABLEID:
- fprintf(stderr, " <tableid>\n");
- break;
- case HOSTID:
- fprintf(stderr, " <hostid>\n");
- break;
- case ENDTOKEN:
- break;
- }
- }
-}
diff --git a/usr.sbin/hoststatectl/parser.h b/usr.sbin/hoststatectl/parser.h
deleted file mode 100644
index c9c1e875fd2..00000000000
--- a/usr.sbin/hoststatectl/parser.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* $OpenBSD: parser.h,v 1.7 2007/10/19 12:08:55 pyr Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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.
- */
-
-enum actions {
- NONE,
- SHOW_SUM,
- SHOW_HOSTS,
- SHOW_RELAYS,
- SHOW_SESSIONS,
- SERV_DISABLE,
- SERV_ENABLE,
- TABLE_DISABLE,
- TABLE_ENABLE,
- HOST_DISABLE,
- HOST_ENABLE,
- SHUTDOWN,
- POLL,
- RELOAD,
- MONITOR
-};
-
-struct parse_result {
- struct ctl_id id;
- enum actions action;
-};
-
-struct parse_result *parse(int, char *[]);
-const struct token *match_token(const char *, const struct token []);
-void show_valid_args(const struct token []);
diff --git a/usr.sbin/hoststated/Makefile b/usr.sbin/hoststated/Makefile
deleted file mode 100644
index 4c2d3010aaf..00000000000
--- a/usr.sbin/hoststated/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# $OpenBSD: Makefile,v 1.15 2007/11/26 09:38:25 reyk Exp $
-
-PROG= hoststated
-SRCS= parse.y log.c control.c buffer.c imsg.c ssl.c ssl_privsep.c \
- hoststated.c pfe.c pfe_filter.c hce.c relay.c relay_udp.c \
- carp.c check_icmp.c check_tcp.c check_script.c name2id.c
-MAN= hoststated.8 hoststated.conf.5
-
-LDADD= -levent -lssl -lcrypto
-DPADD= ${LIBEVENT} ${LIBSSL} ${LIBCRYPTO}
-CFLAGS+= -Wall -I${.CURDIR}
-CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
-CFLAGS+= -Wmissing-declarations
-CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
-CFLAGS+= -Wsign-compare -Wbounded
-CLEANFILES+= y.tab.h
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/hoststated/buffer.c b/usr.sbin/hoststated/buffer.c
deleted file mode 100644
index 5b3cba8e544..00000000000
--- a/usr.sbin/hoststated/buffer.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/* $OpenBSD: buffer.c,v 1.8 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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/param.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-
-#include <net/if.h>
-
-#include <errno.h>
-#include <event.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-int buf_realloc(struct buf *, size_t);
-void buf_enqueue(struct msgbuf *, struct buf *);
-void buf_dequeue(struct msgbuf *, struct buf *);
-
-struct buf *
-buf_open(size_t len)
-{
- struct buf *buf;
-
- if ((buf = calloc(1, sizeof(struct buf))) == NULL)
- return (NULL);
- if ((buf->buf = malloc(len)) == NULL) {
- free(buf);
- return (NULL);
- }
- buf->size = buf->max = len;
- buf->fd = -1;
-
- return (buf);
-}
-
-struct buf *
-buf_dynamic(size_t len, size_t max)
-{
- struct buf *buf;
-
- if (max < len)
- return (NULL);
-
- if ((buf = buf_open(len)) == NULL)
- return (NULL);
-
- if (max > 0)
- buf->max = max;
-
- return (buf);
-}
-
-int
-buf_realloc(struct buf *buf, size_t len)
-{
- u_char *b;
-
- /* on static buffers max is eq size and so the following fails */
- if (buf->wpos + len > buf->max) {
- errno = ENOMEM;
- return (-1);
- }
-
- b = realloc(buf->buf, buf->wpos + len);
- if (b == NULL)
- return (-1);
- buf->buf = b;
- buf->size = buf->wpos + len;
-
- return (0);
-}
-
-int
-buf_add(struct buf *buf, void *data, size_t len)
-{
- if (buf->wpos + len > buf->size)
- if (buf_realloc(buf, len) == -1)
- return (-1);
-
- memcpy(buf->buf + buf->wpos, data, len);
- buf->wpos += len;
- return (0);
-}
-
-void *
-buf_reserve(struct buf *buf, size_t len)
-{
- void *b;
-
- if (buf->wpos + len > buf->size)
- if (buf_realloc(buf, len) == -1)
- return (NULL);
-
- b = buf->buf + buf->wpos;
- buf->wpos += len;
- return (b);
-}
-
-int
-buf_close(struct msgbuf *msgbuf, struct buf *buf)
-{
- buf_enqueue(msgbuf, buf);
- return (1);
-}
-
-void
-buf_free(struct buf *buf)
-{
- free(buf->buf);
- free(buf);
-}
-
-void
-msgbuf_init(struct msgbuf *msgbuf)
-{
- msgbuf->queued = 0;
- msgbuf->fd = -1;
- TAILQ_INIT(&msgbuf->bufs);
-}
-
-void
-msgbuf_clear(struct msgbuf *msgbuf)
-{
- struct buf *buf;
-
- while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
- buf_dequeue(msgbuf, buf);
-}
-
-int
-msgbuf_write(struct msgbuf *msgbuf)
-{
- struct iovec iov[IOV_MAX];
- struct buf *buf, *next;
- int i = 0;
- ssize_t n;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- char cmsgbuf[CMSG_SPACE(sizeof(int))];
-
- bzero(&iov, sizeof(iov));
- bzero(&msg, sizeof(msg));
- TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
- if (i >= IOV_MAX)
- break;
- iov[i].iov_base = buf->buf + buf->rpos;
- iov[i].iov_len = buf->size - buf->rpos;
- i++;
- if (buf->fd != -1)
- break;
- }
-
- msg.msg_iov = iov;
- msg.msg_iovlen = i;
-
- if (buf != NULL && buf->fd != -1) {
- msg.msg_control = (caddr_t)cmsgbuf;
- msg.msg_controllen = CMSG_LEN(sizeof(int));
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- *(int *)CMSG_DATA(cmsg) = buf->fd;
- }
-
- if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
- if (errno == EAGAIN || errno == ENOBUFS ||
- errno == EINTR) /* try later */
- return (0);
- else
- return (-1);
- }
-
- if (n == 0) { /* connection closed */
- errno = 0;
- return (-2);
- }
-
- if (buf != NULL && buf->fd != -1) {
- msg.msg_control = (caddr_t)cmsgbuf;
- msg.msg_controllen = CMSG_LEN(sizeof(int));
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SCM_RIGHTS;
- *(int *)CMSG_DATA(cmsg) = buf->fd;
- }
-
- for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
- buf = next) {
- next = TAILQ_NEXT(buf, entry);
- if (buf->rpos + n >= buf->size) {
- n -= buf->size - buf->rpos;
- buf_dequeue(msgbuf, buf);
- } else {
- buf->rpos += n;
- n = 0;
- }
- }
-
- return (0);
-}
-
-void
-buf_enqueue(struct msgbuf *msgbuf, struct buf *buf)
-{
- TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
- msgbuf->queued++;
-}
-
-void
-buf_dequeue(struct msgbuf *msgbuf, struct buf *buf)
-{
- TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
-
- if (buf->fd != -1)
- close(buf->fd);
-
- msgbuf->queued--;
- buf_free(buf);
-}
diff --git a/usr.sbin/hoststated/carp.c b/usr.sbin/hoststated/carp.c
deleted file mode 100644
index 4288b01b513..00000000000
--- a/usr.sbin/hoststated/carp.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* $OpenBSD: carp.c,v 1.4 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Henning Brauer <henning@openbsd.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/param.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#include <net/if.h>
-
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <event.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-struct carpgroup {
- TAILQ_ENTRY(carpgroup) entry;
- char *group;
- int do_demote;
- int changed_by;
-};
-
-TAILQ_HEAD(carpgroups, carpgroup) carpgroups =
- TAILQ_HEAD_INITIALIZER(carpgroups);
-
-struct carpgroup *carp_group_find(char *group);
-int carp_demote_ioctl(char *, int);
-
-struct carpgroup *
-carp_group_find(char *group)
-{
- struct carpgroup *c;
-
- TAILQ_FOREACH(c, &carpgroups, entry)
- if (!strcmp(c->group, group))
- return (c);
-
- return (NULL);
-}
-
-int
-carp_demote_init(char *group, int force)
-{
- struct carpgroup *c;
- int level;
-
- if ((c = carp_group_find(group)) == NULL) {
- if ((c = calloc(1, sizeof(struct carpgroup))) == NULL) {
- log_warn("carp_demote_init calloc");
- return (-1);
- }
- if ((c->group = strdup(group)) == NULL) {
- log_warn("carp_demote_init calloc");
- free(c);
- return (-1);
- }
-
- /* only demote if this group already is demoted */
- if ((level = carp_demote_get(group)) == -1)
- return (-1);
- if (level > 0 || force)
- c->do_demote = 1;
-
- TAILQ_INSERT_TAIL(&carpgroups, c, entry);
- }
-
- return (0);
-}
-
-void
-carp_demote_shutdown(void)
-{
- struct carpgroup *c;
-
- while ((c = TAILQ_FIRST(&carpgroups)) != NULL) {
- TAILQ_REMOVE(&carpgroups, c, entry);
- for (; c->changed_by > 0; c->changed_by--)
- if (c->do_demote)
- carp_demote_ioctl(c->group, -1);
-
- free(c->group);
- free(c);
- }
-}
-
-int
-carp_demote_get(char *group)
-{
- int s;
- struct ifgroupreq ifgr;
-
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- log_warn("carp_demote_get: socket");
- return (-1);
- }
-
- bzero(&ifgr, sizeof(ifgr));
- if (strlcpy(ifgr.ifgr_name, group, sizeof(ifgr.ifgr_name)) >=
- sizeof(ifgr.ifgr_name)) {
- log_warn("carp_demote_get: invalid group");
- return (-1);
- }
-
- if (ioctl(s, SIOCGIFGATTR, (caddr_t)&ifgr) == -1) {
- if (errno == ENOENT)
- log_warnx("group \"%s\" does not exist", group);
- else
- log_warn("carp_demote_get: ioctl");
- close(s);
- return (-1);
- }
-
- close(s);
- return ((int)ifgr.ifgr_attrib.ifg_carp_demoted);
-}
-
-int
-carp_demote_set(char *group, int demote)
-{
- struct carpgroup *c;
-
- if ((c = carp_group_find(group)) == NULL) {
- log_warnx("carp_group_find for %s returned NULL?!", group);
- return (-1);
- }
-
- if (c->changed_by + demote < 0) {
- log_warnx("carp_demote_set: changed_by + demote < 0");
- return (-1);
- }
-
- if (c->do_demote && carp_demote_ioctl(group, demote) == -1)
- return (-1);
-
- c->changed_by += demote;
-
- /* enable demotion when we return to 0, i. e. all sessions up */
- if (demote < 0 && c->changed_by == 0)
- c->do_demote = 1;
-
- return (0);
-}
-
-int
-carp_demote_reset(char *group, int value)
-{
- int level;
- int demote = 0;
-
- if (value < 0) {
- log_warnx("carp_demote_reset: value < 0");
- return (-1);
- }
-
- if ((level = carp_demote_get(group)) == -1)
- return (-1);
- if (level == value)
- return (0);
-
- demote -= level;
- demote += value;
-
- if (carp_demote_ioctl(group, demote) == -1)
- return (-1);
-
- return (0);
-}
-
-int
-carp_demote_ioctl(char *group, int demote)
-{
- int s, res;
- struct ifgroupreq ifgr;
-
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- log_warn("carp_demote_get: socket");
- return (-1);
- }
-
- bzero(&ifgr, sizeof(ifgr));
- if (strlcpy(ifgr.ifgr_name, group, sizeof(ifgr.ifgr_name)) >=
- sizeof(ifgr.ifgr_name)) {
- log_warn("carp_demote_ioctl: invalid group");
- return (-1);
- }
- ifgr.ifgr_attrib.ifg_carp_demoted = demote;
-
- if ((res = ioctl(s, SIOCSIFGATTR, (caddr_t)&ifgr)) == -1)
- log_warn("unable to %s the demote state "
- "of group '%s'", (demote > 0) ? "increment" : "decrement",
- group);
- else
- log_info("%s the demote state of group '%s'",
- (demote > 0) ? "incremented" : "decremented", group);
-
- close(s);
- return (res);
-}
diff --git a/usr.sbin/hoststated/check_icmp.c b/usr.sbin/hoststated/check_icmp.c
deleted file mode 100644
index 25dc21f2117..00000000000
--- a/usr.sbin/hoststated/check_icmp.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* $OpenBSD: check_icmp.c,v 1.21 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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 <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/icmp6.h>
-#include <arpa/inet.h>
-
-#include <limits.h>
-#include <event.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-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
-icmp_setup(struct hoststated *env, struct ctl_icmp_event *cie, int af)
-{
- int proto = IPPROTO_ICMP;
-
- if (af == AF_INET6)
- proto = IPPROTO_ICMPV6;
- if ((cie->s = socket(af, SOCK_RAW, proto)) < 0)
- fatal("icmp_init: socket");
- session_socket_blockmode(cie->s, BM_NONBLOCK);
- cie->env = env;
- cie->af = af;
-}
-
-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
-schedule_icmp(struct hoststated *env, struct host *host)
-{
- host->last_up = host->up;
- host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
-
- if (((struct sockaddr *)&host->conf.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 (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
-icmp_checks_done(struct ctl_icmp_event *cie)
-{
- struct table *table;
- struct host *host;
-
- TAILQ_FOREACH(table, cie->env->tables, entry) {
- if (table->conf.flags & F_DISABLE ||
- table->conf.check != CHECK_ICMP)
- continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (((struct sockaddr *)&host->conf.ss)->sa_family !=
- cie->af)
- continue;
- if (!(host->flags & F_CHECK_DONE))
- return (0);
- }
- }
- return (1);
-}
-
-void
-icmp_checks_timeout(struct ctl_icmp_event *cie, const char *msg)
-{
- struct table *table;
- struct host *host;
-
- TAILQ_FOREACH(table, cie->env->tables, entry) {
- if (table->conf.flags & F_DISABLE ||
- table->conf.check != CHECK_ICMP)
- continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (((struct sockaddr *)&host->conf.ss)->sa_family !=
- cie->af)
- continue;
- if (!(host->flags & F_CHECK_DONE)) {
- host->up = HOST_DOWN;
- hce_notify_done(host, msg);
- }
- }
- }
-}
-
-void
-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 icmp *icp;
- struct icmp6_hdr *icp6;
- ssize_t r;
- u_char packet[ICMP_BUF_SIZE];
- socklen_t slen;
- int i = 0;
-
- if (event == EV_TIMEOUT) {
- icmp_checks_timeout(cie, "send_icmp: timeout");
- return;
- }
-
- bzero(&packet, sizeof(packet));
- icp = (struct icmp *)packet;
- 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);
- }
-
- TAILQ_FOREACH(table, cie->env->tables, entry) {
- if (table->conf.check != CHECK_ICMP ||
- table->conf.flags & F_DISABLE)
- continue;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & (F_DISABLE | F_CHECK_SENT))
- continue;
- if (((struct sockaddr *)&host->conf.ss)->sa_family !=
- cie->af)
- continue;
- i++;
- to = (struct sockaddr *)&host->conf.ss;
- if (cie->af == AF_INET) {
- icp->icmp_seq = htons(i);
- icp->icmp_cksum = 0;
- memcpy(icp->icmp_data, &host->conf.id,
- sizeof(host->conf.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->conf.id,
- sizeof(host->conf.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;
-
- retry:
- event_again(&cie->ev, s, EV_TIMEOUT|EV_WRITE, send_icmp,
- &cie->tv_start, &cie->env->timeout, cie);
-}
-
-void
-recv_icmp(int s, short event, void *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;
- ssize_t r;
- objid_t id;
-
- if (event == EV_TIMEOUT) {
- icmp_checks_timeout(cie, NULL);
- return;
- }
-
- bzero(&packet, sizeof(packet));
- bzero(&ss, sizeof(ss));
-
- 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;
- }
-
- 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_warn("recv_icmp: ping for unknown host received");
- goto retry;
- }
- if (bcmp(&ss, &host->conf.ss, slen)) {
- log_warnx("recv_icmp: forged icmp packet?");
- goto retry;
- }
-
- host->up = HOST_UP;
- host->flags |= F_CHECK_DONE;
- hce_notify_done(host, "recv_icmp: done");
-
- if (icmp_checks_done(cie))
- return;
-
- retry:
- event_again(&cie->ev, s, EV_TIMEOUT|EV_READ, recv_icmp,
- &cie->tv_start, &cie->env->timeout, cie);
-}
-
-/* in_cksum from ping.c --
- * Checksum routine for Internet Protocol family headers (C Version)
- *
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Mike Muuss.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-int
-in_cksum(u_short *addr, int len)
-{
- int nleft = len;
- u_short *w = addr;
- int sum = 0;
- u_short answer = 0;
-
- /*
- * Our algorithm is simple, using a 32 bit accumulator (sum), we add
- * sequential 16 bit words to it, and at the end, fold back all the
- * carry bits from the top 16 bits into the lower 16 bits.
- */
- while (nleft > 1) {
- sum += *w++;
- nleft -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nleft == 1) {
- *(u_char *)(&answer) = *(u_char *)w ;
- sum += answer;
- }
-
- /* add back carry outs from top 16 bits to low 16 bits */
- sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
- sum += (sum >> 16); /* add carry */
- answer = ~sum; /* truncate to 16 bits */
-
- return (answer);
-}
diff --git a/usr.sbin/hoststated/check_script.c b/usr.sbin/hoststated/check_script.c
deleted file mode 100644
index 2f09c2543a3..00000000000
--- a/usr.sbin/hoststated/check_script.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* $OpenBSD: check_script.c,v 1.4 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.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/param.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-#include <net/if.h>
-
-#include <limits.h>
-#include <event.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <pwd.h>
-#include <err.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-void script_sig_alarm(int);
-
-extern struct imsgbuf *ibuf_main;
-pid_t child = -1;
-
-void
-check_script(struct host *host)
-{
- struct ctl_script scr;
-
- host->last_up = host->up;
- host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
-
- scr.host = host->conf.id;
- imsg_compose(ibuf_main, IMSG_SCRIPT, 0, 0, -1, &scr, sizeof(scr));
-}
-
-void
-script_done(struct hoststated *env, struct ctl_script *scr)
-{
- struct host *host;
-
- if ((host = host_find(env, scr->host)) == NULL)
- fatalx("hce_dispatch_parent: invalid host id");
-
- if (scr->retval < 0)
- host->up = HOST_UNKNOWN;
- else if (scr->retval == 0)
- host->up = HOST_DOWN;
- else
- host->up = HOST_UP;
- host->flags |= F_CHECK_DONE;
-
- hce_notify_done(host, host->up == HOST_UP ?
- "script: done" : "script: failed");
-}
-
-void
-script_sig_alarm(int sig)
-{
- int save_errno = errno;
-
- if (child != -1)
- kill(child, SIGKILL);
- errno = save_errno;
-}
-
-int
-script_exec(struct hoststated *env, struct ctl_script *scr)
-{
- int status = 0, ret = 0;
- sig_t save_quit, save_int, save_chld;
- struct itimerval it;
- struct timeval *tv;
- const char *file, *arg;
- struct host *host;
- struct table *table;
- struct passwd *pw;
-
- if ((host = host_find(env, scr->host)) == NULL)
- fatalx("script_exec: invalid host id");
- if ((table = table_find(env, host->conf.tableid)) == NULL)
- fatalx("script_exec: invalid table id");
-
- arg = host->conf.name;
- file = table->conf.path;
- tv = &table->conf.timeout;
-
- save_quit = signal(SIGQUIT, SIG_IGN);
- save_int = signal(SIGINT, SIG_IGN);
- save_chld = signal(SIGCHLD, SIG_DFL);
-
- switch (child = fork()) {
- case -1:
- ret = -1;
- goto done;
- case 0:
- signal(SIGQUIT, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
-
- if ((pw = getpwnam(HOSTSTATED_USER)) == NULL)
- fatal("script_exec: getpwnam");
- if (chdir("/") == -1)
- fatal("script_exec: chdir(\"/\")");
- 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("script_exec: can't drop privileges");
-
- execlp(file, file, arg, (char *)NULL);
- _exit(0);
- break;
- default:
- /* Kill the process after a timeout */
- signal(SIGALRM, script_sig_alarm);
- bzero(&it, sizeof(it));
- bcopy(tv, &it.it_value, sizeof(it.it_value));
- setitimer(ITIMER_REAL, &it, NULL);
-
- waitpid(child, &status, 0);
- break;
- }
-
- switch (ret) {
- case -1:
- ret = -1;
- break;
- default:
- if (WIFEXITED(status))
- ret = WEXITSTATUS(status);
- else
- ret = -1;
- }
-
- done:
- /* Disable the process timeout timer */
- bzero(&it, sizeof(it));
- setitimer(ITIMER_REAL, &it, NULL);
- child = -1;
-
- signal(SIGQUIT, save_quit);
- signal(SIGINT, save_int);
- signal(SIGCHLD, save_chld);
- signal(SIGALRM, SIG_DFL);
-
- return (ret);
-}
diff --git a/usr.sbin/hoststated/check_tcp.c b/usr.sbin/hoststated/check_tcp.c
deleted file mode 100644
index d039a1d1335..00000000000
--- a/usr.sbin/hoststated/check_tcp.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/* $OpenBSD: check_tcp.c,v 1.30 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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/param.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-
-#include <limits.h>
-#include <event.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <fnmatch.h>
-#include <sha1.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-void tcp_write(int, short, void *);
-void tcp_host_up(int, struct ctl_tcp_event *);
-void tcp_send_req(int, short, void *);
-void tcp_read_buf(int, short, void *);
-
-int check_http_code(struct ctl_tcp_event *);
-int check_http_digest(struct ctl_tcp_event *);
-int check_send_expect(struct ctl_tcp_event *);
-
-void
-check_tcp(struct ctl_tcp_event *cte)
-{
- int s;
- int type;
- socklen_t len;
- struct timeval tv;
- struct linger lng;
-
- switch (cte->host->conf.ss.ss_family) {
- case AF_INET:
- ((struct sockaddr_in *)&cte->host->conf.ss)->sin_port =
- cte->table->conf.port;
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *)&cte->host->conf.ss)->sin6_port =
- cte->table->conf.port;
- break;
- }
-
- len = ((struct sockaddr *)&cte->host->conf.ss)->sa_len;
-
- if ((s = socket(cte->host->conf.ss.ss_family, SOCK_STREAM, 0)) == -1)
- goto bad;
-
- bzero(&lng, sizeof(lng));
- if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1)
- goto bad;
-
- type = 1;
- if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &type, sizeof(type)) == -1)
- goto bad;
-
- if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
- goto bad;
-
- bcopy(&cte->table->conf.timeout, &tv, sizeof(tv));
- if (connect(s, (struct sockaddr *)&cte->host->conf.ss, len) == -1) {
- if (errno != EINPROGRESS)
- goto bad;
- }
-
- cte->host->up = HOST_UP;
- 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;
- hce_notify_done(cte->host, "check_tcp: cannot connect");
-}
-
-void
-tcp_write(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int err;
- socklen_t len;
-
- if (event == EV_TIMEOUT) {
- log_debug("tcp_write: connect timed out");
- cte->host->up = HOST_DOWN;
- } else {
- len = sizeof(err);
- if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &len))
- fatal("tcp_write: getsockopt");
- if (err != 0)
- cte->host->up = HOST_DOWN;
- else
- cte->host->up = HOST_UP;
- }
-
- if (cte->host->up == HOST_UP)
- tcp_host_up(s, cte);
- else {
- close(s);
- hce_notify_done(cte->host, "tcp_write: connect failed");
- }
-}
-
-void
-tcp_host_up(int s, struct ctl_tcp_event *cte)
-{
- cte->s = s;
-
- switch (cte->table->conf.check) {
- case CHECK_TCP:
- if (cte->table->conf.flags & F_SSL)
- break;
- close(s);
- hce_notify_done(cte->host, "tcp_host_up: connect successful");
- return;
- case CHECK_HTTP_CODE:
- cte->validate_read = NULL;
- cte->validate_close = check_http_code;
- break;
- case CHECK_HTTP_DIGEST:
- cte->validate_read = NULL;
- cte->validate_close = check_http_digest;
- break;
- case CHECK_SEND_EXPECT:
- cte->validate_read = check_send_expect;
- cte->validate_close = check_send_expect;
- break;
- }
-
- if (cte->table->conf.flags & F_SSL) {
- ssl_transaction(cte);
- return;
- }
-
- if (cte->table->sendbuf != NULL) {
- cte->req = cte->table->sendbuf;
- event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_send_req,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
- }
-
- if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
- fatalx("tcp_host_up: cannot create dynamic buffer");
- event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-void
-tcp_send_req(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int bs;
- int len;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- close(cte->s);
- hce_notify_done(cte->host, "tcp_send_req: timeout");
- return;
- }
- len = strlen(cte->req);
- do {
- bs = write(s, cte->req, len);
- if (bs == -1) {
- if (errno == EAGAIN || errno == EINTR)
- goto retry;
- log_warnx("tcp_send_req: cannot send request");
- cte->host->up = HOST_DOWN;
- close(cte->s);
- hce_notify_done(cte->host, "tcp_send_req: write");
- return;
- }
- cte->req += bs;
- len -= bs;
- } while (len > 0);
-
- if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
- fatalx("tcp_send_req: cannot create dynamic buffer");
- event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-
- retry:
- event_again(&cte->ev, s, EV_TIMEOUT|EV_WRITE, tcp_send_req,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-void
-tcp_read_buf(int s, short event, void *arg)
-{
- ssize_t br;
- char rbuf[SMALL_READ_BUF_SIZE];
- struct ctl_tcp_event *cte = arg;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- buf_free(cte->buf);
- close(s);
- hce_notify_done(cte->host, "tcp_read_buf: timeout");
- return;
- }
-
- bzero(rbuf, sizeof(rbuf));
- br = read(s, rbuf, sizeof(rbuf) - 1);
- switch (br) {
- case -1:
- if (errno == EAGAIN || errno == EINTR)
- goto retry;
- cte->host->up = HOST_DOWN;
- buf_free(cte->buf);
- close(cte->s);
- hce_notify_done(cte->host, "tcp_read_buf: read failed");
- return;
- case 0:
- cte->host->up = HOST_DOWN;
- (void)cte->validate_close(cte);
- close(cte->s);
- buf_free(cte->buf);
- if (cte->host->up == HOST_UP)
- hce_notify_done(cte->host,
- "tcp_read_buf: check succeeded");
- else
- hce_notify_done(cte->host,
- "tcp_read_buf: check failed");
- return;
- default:
- if (buf_add(cte->buf, rbuf, br) == -1)
- fatal("tcp_read_buf: buf_add error");
- if (cte->validate_read != NULL) {
- if (cte->validate_read(cte) != 0)
- goto retry;
-
- close(cte->s);
- buf_free(cte->buf);
- if (cte->host->up == HOST_UP)
- hce_notify_done(cte->host,
- "tcp_read_buf: check succeeded");
- else
- hce_notify_done(cte->host,
- "tcp_read_buf: check failed");
- return;
- }
- break; /* retry */
- }
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-int
-check_send_expect(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 (fnmatch(cte->table->conf.exbuf, cte->buf->buf, 0) == 0) {
- cte->host->up = HOST_UP;
- return (0);
- }
- cte->host->up = HOST_UNKNOWN;
-
- /*
- * go back to original position.
- */
- cte->buf->wpos--;
- return (1);
-}
-
-int
-check_http_code(struct ctl_tcp_event *cte)
-{
- char *head;
- char scode[4];
- const char *estr;
- u_char *b;
- int code;
- struct host *host;
-
- /*
- * ensure string is nul-terminated.
- */
- b = buf_reserve(cte->buf, 1);
- if (b == NULL)
- fatal("out of memory");
- *b = '\0';
-
- head = cte->buf->buf;
- host = cte->host;
- if (strncmp(head, "HTTP/1.1 ", strlen("HTTP/1.1 ")) &&
- strncmp(head, "HTTP/1.0 ", strlen("HTTP/1.0 "))) {
- log_debug("check_http_code: %s failed "
- "(cannot parse HTTP version)", host->conf.name);
- host->up = HOST_DOWN;
- return (1);
- }
- head += strlen("HTTP/1.1 ");
- if (strlen(head) < 5) /* code + \r\n */ {
- host->up = HOST_DOWN;
- return (1);
- }
- (void)strlcpy(scode, head, sizeof(scode));
- code = strtonum(scode, 100, 999, &estr);
- if (estr != NULL) {
- log_debug("check_http_code: %s failed "
- "(cannot parse HTTP code)", host->conf.name);
- host->up = HOST_DOWN;
- return (1);
- }
- if (code != cte->table->conf.retcode) {
- log_debug("check_http_code: %s failed "
- "(invalid HTTP code returned)", host->conf.name);
- host->up = HOST_DOWN;
- } else
- host->up = HOST_UP;
- return (!(host->up == HOST_UP));
-}
-
-int
-check_http_digest(struct ctl_tcp_event *cte)
-{
- char *head;
- u_char *b;
- char digest[SHA1_DIGEST_STRING_LENGTH];
- struct host *host;
-
- /*
- * ensure string is nul-terminated.
- */
- b = buf_reserve(cte->buf, 1);
- if (b == NULL)
- fatal("out of memory");
- *b = '\0';
-
- head = cte->buf->buf;
- host = cte->host;
- if ((head = strstr(head, "\r\n\r\n")) == NULL) {
- log_debug("check_http_digest: %s failed "
- "(no end of headers)", host->conf.name);
- host->up = HOST_DOWN;
- return (1);
- }
- head += strlen("\r\n\r\n");
-
- digeststr(cte->table->conf.digest_type, head, strlen(head), digest);
-
- if (strcmp(cte->table->conf.digest, digest)) {
- log_warnx("check_http_digest: %s failed "
- "(wrong digest)", host->conf.name);
- host->up = HOST_DOWN;
- } else
- host->up = HOST_UP;
- return (!(host->up == HOST_UP));
-}
diff --git a/usr.sbin/hoststated/control.c b/usr.sbin/hoststated/control.c
deleted file mode 100644
index 97597dd8489..00000000000
--- a/usr.sbin/hoststated/control.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/* $OpenBSD: control.c,v 1.21 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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/queue.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <net/if.h>
-
-#include <errno.h>
-#include <event.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-#define CONTROL_BACKLOG 5
-
-struct ctl_connlist ctl_conns;
-
-struct ctl_conn *control_connbyfd(int);
-void control_close(int);
-
-struct imsgbuf *ibuf_main = NULL;
-struct imsgbuf *ibuf_hce = NULL;
-
-int
-control_init(void)
-{
- struct sockaddr_un sun;
- int fd;
- mode_t old_umask;
-
- if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- log_warn("control_init: socket");
- return (-1);
- }
-
- sun.sun_family = AF_UNIX;
- if (strlcpy(sun.sun_path, HOSTSTATED_SOCKET,
- sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
- log_warn("control_init: %s name too long", HOSTSTATED_SOCKET);
- close(fd);
- return (-1);
- }
-
- if (unlink(HOSTSTATED_SOCKET) == -1)
- if (errno != ENOENT) {
- log_warn("control_init: unlink %s", HOSTSTATED_SOCKET);
- close(fd);
- return (-1);
- }
-
- old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
- if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
- log_warn("control_init: bind: %s", HOSTSTATED_SOCKET);
- close(fd);
- (void)umask(old_umask);
- return (-1);
- }
- (void)umask(old_umask);
-
- if (chmod(HOSTSTATED_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
- log_warn("control_init: chmod");
- close(fd);
- (void)unlink(HOSTSTATED_SOCKET);
- return (-1);
- }
-
- session_socket_blockmode(fd, BM_NONBLOCK);
- control_state.fd = fd;
-
- return (0);
-}
-
-int
-control_listen(struct hoststated *env, struct imsgbuf *i_main,
- struct imsgbuf *i_hce)
-{
-
- ibuf_main = i_main;
- ibuf_hce = i_hce;
-
- if (listen(control_state.fd, CONTROL_BACKLOG) == -1) {
- log_warn("control_listen: listen");
- return (-1);
- }
-
- event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST,
- control_accept, env);
- event_add(&control_state.ev, NULL);
-
- return (0);
-}
-
-void
-control_cleanup(void)
-{
- (void)unlink(HOSTSTATED_SOCKET);
-}
-
-/* ARGSUSED */
-void
-control_accept(int listenfd, short event, void *arg)
-{
- int connfd;
- socklen_t len;
- struct sockaddr_un sun;
- struct ctl_conn *c;
- struct hoststated *env = arg;
-
- len = sizeof(sun);
- if ((connfd = accept(listenfd,
- (struct sockaddr *)&sun, &len)) == -1) {
- if (errno != EWOULDBLOCK && errno != EINTR)
- log_warn("control_accept");
- return;
- }
-
- session_socket_blockmode(connfd, BM_NONBLOCK);
-
- if ((c = malloc(sizeof(struct ctl_conn))) == NULL) {
- log_warn("control_accept");
- return;
- }
-
- imsg_init(&c->ibuf, connfd, control_dispatch_imsg);
- c->ibuf.events = EV_READ;
- event_set(&c->ibuf.ev, c->ibuf.fd, c->ibuf.events,
- c->ibuf.handler, env);
- event_add(&c->ibuf.ev, NULL);
-
- TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
-}
-
-struct ctl_conn *
-control_connbyfd(int fd)
-{
- struct ctl_conn *c;
-
- for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->ibuf.fd != fd;
- c = TAILQ_NEXT(c, entry))
- ; /* nothing */
-
- return (c);
-}
-
-void
-control_close(int fd)
-{
- struct ctl_conn *c;
-
- if ((c = control_connbyfd(fd)) == NULL)
- log_warn("control_close: fd %d: not found", fd);
-
- msgbuf_clear(&c->ibuf.w);
- TAILQ_REMOVE(&ctl_conns, c, entry);
-
- event_del(&c->ibuf.ev);
- close(c->ibuf.fd);
- free(c);
-}
-
-/* ARGSUSED */
-void
-control_dispatch_imsg(int fd, short event, void *arg)
-{
- struct ctl_conn *c;
- struct imsg imsg;
- struct ctl_id id;
- int n;
- struct hoststated *env = arg;
-
- if ((c = control_connbyfd(fd)) == NULL) {
- log_warn("control_dispatch_imsg: fd %d: not found", fd);
- return;
- }
-
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) {
- control_close(fd);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&c->ibuf.w) < 0) {
- control_close(fd);
- return;
- }
- imsg_event_add(&c->ibuf);
- return;
- default:
- fatalx("unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(&c->ibuf, &imsg)) == -1) {
- control_close(fd);
- return;
- }
-
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_CTL_SHOW_SUM:
- show(c);
- break;
- case IMSG_CTL_SESSION:
- show_sessions(c);
- break;
- case IMSG_CTL_SERVICE_DISABLE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
- fatalx("invalid imsg header len");
- memcpy(&id, imsg.data, sizeof(id));
- if (disable_service(c, &id))
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- else {
- memcpy(imsg.data, &id, sizeof(id));
- control_imsg_forward(&imsg);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
- NULL, 0);
- }
- break;
- case IMSG_CTL_SERVICE_ENABLE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
- fatalx("invalid imsg header len");
- memcpy(&id, imsg.data, sizeof(id));
- if (enable_service(c, &id))
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- else {
- memcpy(imsg.data, &id, sizeof(id));
- control_imsg_forward(&imsg);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
- NULL, 0);
- }
- break;
- case IMSG_CTL_TABLE_DISABLE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
- fatalx("invalid imsg header len");
- memcpy(&id, imsg.data, sizeof(id));
- if (disable_table(c, &id))
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- else {
- memcpy(imsg.data, &id, sizeof(id));
- control_imsg_forward(&imsg);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
- NULL, 0);
- }
- break;
- case IMSG_CTL_TABLE_ENABLE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
- fatalx("invalid imsg header len");
- memcpy(&id, imsg.data, sizeof(id));
- if (enable_table(c, &id))
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- else {
- memcpy(imsg.data, &id, sizeof(id));
- control_imsg_forward(&imsg);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
- NULL, 0);
- }
- break;
- case IMSG_CTL_HOST_DISABLE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
- fatalx("invalid imsg header len");
- memcpy(&id, imsg.data, sizeof(id));
- if (disable_host(c, &id))
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- else {
- memcpy(imsg.data, &id, sizeof(id));
- control_imsg_forward(&imsg);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
- NULL, 0);
- }
- break;
- case IMSG_CTL_HOST_ENABLE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(id))
- fatalx("invalid imsg header len");
- memcpy(&id, imsg.data, sizeof(id));
- if (enable_host(c, &id))
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- else {
- memcpy(imsg.data, &id, sizeof(id));
- control_imsg_forward(&imsg);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1,
- NULL, 0);
- }
- break;
- case IMSG_CTL_SHUTDOWN:
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1, NULL,
- 0);
- break;
- case IMSG_CTL_POLL:
- imsg_compose(ibuf_hce, IMSG_CTL_POLL, 0, 0,-1, NULL, 0);
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
- break;
- case IMSG_CTL_RELOAD:
- if (env->prefork_relay > 0) {
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- break;
- }
- imsg_compose(ibuf_main, IMSG_CTL_RELOAD, 0, 0, -1, NULL,
- 0);
- /*
- * we unconditionnaly return a CTL_OK imsg because
- * we have no choice.
- *
- * so in this case, the reply hoststatectl gets means
- * that the reload command has been set,
- * it doesn't say wether the command succeeded or not.
- */
- imsg_compose(&c->ibuf, IMSG_CTL_OK, 0, 0, -1, NULL, 0);
- break;
- case IMSG_CTL_NOTIFY:
- if (c->flags & CTL_CONN_NOTIFY) {
- log_debug("control_dispatch_imsg: "
- "client requested notify more than once");
- imsg_compose(&c->ibuf, IMSG_CTL_FAIL, 0, 0, -1,
- NULL, 0);
- break;
- }
- c->flags |= CTL_CONN_NOTIFY;
- break;
- default:
- log_debug("control_dispatch_imsg: "
- "error handling imsg %d", imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
-
- imsg_event_add(&c->ibuf);
-}
-
-void
-control_imsg_forward(struct imsg *imsg)
-{
- struct ctl_conn *c;
-
- TAILQ_FOREACH(c, &ctl_conns, entry)
- if (c->flags & CTL_CONN_NOTIFY)
- imsg_compose(&c->ibuf, imsg->hdr.type, 0, imsg->hdr.pid,
- -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
-}
-
-void
-session_socket_blockmode(int fd, enum blockmodes bm)
-{
- int flags;
-
- if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
- fatal("fcntl F_GETFL");
-
- if (bm == BM_NONBLOCK)
- flags |= O_NONBLOCK;
- else
- flags &= ~O_NONBLOCK;
-
- if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
- fatal("fcntl F_SETFL");
-}
diff --git a/usr.sbin/hoststated/hce.c b/usr.sbin/hoststated/hce.c
deleted file mode 100644
index cb3240f52da..00000000000
--- a/usr.sbin/hoststated/hce.c
+++ /dev/null
@@ -1,515 +0,0 @@
-/* $OpenBSD: hce.c,v 1.36 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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/param.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-
-#include <errno.h>
-#include <event.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <err.h>
-#include <pwd.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-__dead void hce_shutdown(void);
-void hce_sig_handler(int sig, short, void *);
-void hce_dispatch_imsg(int, short, void *);
-void hce_dispatch_parent(int, short, void *);
-void hce_launch_checks(int, short, void *);
-void hce_setup_events(void);
-void hce_disable_events(void);
-
-static struct hoststated *env = NULL;
-struct imsgbuf *ibuf_pfe;
-struct imsgbuf *ibuf_main;
-int pipe_pfe;
-int pipe_parent;
-int running = 0;
-
-void
-hce_sig_handler(int sig, short event, void *arg)
-{
- switch (sig) {
- case SIGINT:
- case SIGTERM:
- hce_shutdown();
- break;
- default:
- fatalx("hce_sig_handler: unexpected signal");
- }
-}
-
-pid_t
-hce(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
- int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
- int pipe_pfe2relay[RELAY_MAXPROC][2])
-{
- pid_t pid;
- struct passwd *pw;
- int i;
- struct event ev_sigint;
- struct event ev_sigterm;
-
- switch (pid = fork()) {
- case -1:
- fatal("hce: cannot fork");
- case 0:
- break;
- default:
- return (pid);
- }
-
- env = x_env;
- purge_config(env, PURGE_SERVICES|PURGE_RELAYS|PURGE_PROTOS);
-
- if ((pw = getpwnam(HOSTSTATED_USER)) == NULL)
- fatal("hce: getpwnam");
-
-#ifndef DEBUG
- if (chroot(pw->pw_dir) == -1)
- fatal("hce: chroot");
- if (chdir("/") == -1)
- fatal("hce: chdir(\"/\")");
-#else
-#warning disabling privilege revocation and chroot in DEBUG mode
-#endif
-
- setproctitle("host check engine");
- hoststated_process = PROC_HCE;
-
- /* this is needed for icmp tests */
- icmp_init(env);
-
-#ifndef DEBUG
- 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");
-#endif
-
- event_init();
-
- if ((ibuf_pfe = calloc(1, sizeof(struct imsgbuf))) == NULL ||
- (ibuf_main = calloc(1, sizeof(struct imsgbuf))) == NULL)
- fatal("hce");
- imsg_init(ibuf_pfe, pipe_pfe2hce[0], hce_dispatch_imsg);
- imsg_init(ibuf_main, pipe_parent2hce[1], hce_dispatch_parent);
-
- ibuf_pfe->events = EV_READ;
- event_set(&ibuf_pfe->ev, ibuf_pfe->fd, ibuf_pfe->events,
- ibuf_pfe->handler, ibuf_pfe);
- event_add(&ibuf_pfe->ev, NULL);
-
- ibuf_main->events = EV_READ;
- event_set(&ibuf_main->ev, ibuf_main->fd, ibuf_main->events,
- ibuf_main->handler, ibuf_main);
- event_add(&ibuf_main->ev, NULL);
-
- signal_set(&ev_sigint, SIGINT, hce_sig_handler, NULL);
- signal_set(&ev_sigterm, SIGTERM, hce_sig_handler, NULL);
- signal_add(&ev_sigint, NULL);
- signal_add(&ev_sigterm, NULL);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
-
- /* setup pipes */
- close(pipe_pfe2hce[1]);
- close(pipe_parent2hce[0]);
- close(pipe_parent2pfe[0]);
- close(pipe_parent2pfe[1]);
- for (i = 0; i < env->prefork_relay; i++) {
- close(pipe_parent2relay[i][0]);
- close(pipe_parent2relay[i][1]);
- close(pipe_pfe2relay[i][0]);
- close(pipe_pfe2relay[i][1]);
- }
-
- hce_setup_events();
- event_dispatch();
- hce_shutdown();
-
- return (0);
-}
-
-void
-hce_setup_events(void)
-{
- struct timeval tv;
- struct table *table;
-
- if (!TAILQ_EMPTY(env->tables)) {
- evtimer_set(&env->ev, hce_launch_checks, env);
- bzero(&tv, sizeof(tv));
- evtimer_add(&env->ev, &tv);
- }
-
- if (env->flags & F_SSL) {
- ssl_init(env);
- TAILQ_FOREACH(table, env->tables, entry) {
- if (!(table->conf.flags & F_SSL))
- continue;
- table->ssl_ctx = ssl_ctx_create(env);
- }
- }
-}
-
-void
-hce_disable_events(void)
-{
- struct table *table;
- struct host *host;
-
- evtimer_del(&env->ev);
- TAILQ_FOREACH(table, env->tables, entry) {
- TAILQ_FOREACH(host, &table->hosts, entry) {
- event_del(&host->cte.ev);
- close(host->cte.s);
- }
- }
- if (env->has_icmp) {
- event_del(&env->icmp_send.ev);
- event_del(&env->icmp_recv.ev);
- }
- if (env->has_icmp6) {
- event_del(&env->icmp6_send.ev);
- event_del(&env->icmp6_recv.ev);
- }
-}
-
-void
-hce_launch_checks(int fd, short event, void *arg)
-{
- struct host *host;
- struct table *table;
- struct timeval tv;
-
- /*
- * notify pfe checks are done and schedule next check
- */
- imsg_compose(ibuf_pfe, IMSG_SYNC, 0, 0, -1, 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->conf.flags & F_DISABLE)
- continue;
- if (table->conf.skip_cnt) {
- if (table->skipped++ > table->conf.skip_cnt)
- table->skipped = 0;
- if (table->skipped != 1)
- continue;
- }
- if (table->conf.check == CHECK_NOCHECK)
- fatalx("hce_launch_checks: unknown check type");
-
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->flags & F_DISABLE)
- continue;
- switch (table->conf.check) {
- case CHECK_ICMP:
- schedule_icmp(env, host);
- break;
- case CHECK_SCRIPT:
- check_script(host);
- break;
- default:
- /* Any other TCP-style checks */
- bzero(&host->cte, sizeof(host->cte));
- host->last_up = host->up;
- host->cte.host = host;
- host->cte.table = table;
- bcopy(&tv, &host->cte.tv_start,
- sizeof(host->cte.tv_start));
- check_tcp(&host->cte);
- break;
- }
- }
- }
- check_icmp(env, &tv);
-
- bcopy(&env->interval, &tv, sizeof(tv));
- evtimer_add(&env->ev, &tv);
-}
-
-void
-hce_notify_done(struct host *host, const char *msg)
-{
- struct table *table;
- struct ctl_status st;
- struct timeval tv_now, tv_dur;
- u_long duration;
- u_int logopt;
-
- if (host->up == HOST_DOWN && host->retry_cnt) {
- log_debug("hce_notify_done: host %s retry %d",
- host->conf.name, host->retry_cnt);
- host->up = host->last_up;
- host->retry_cnt--;
- } else
- host->retry_cnt = host->conf.retry;
- if (host->up != HOST_UNKNOWN) {
- host->check_cnt++;
- if (host->up == HOST_UP)
- host->up_cnt++;
- }
- st.id = host->conf.id;
- st.up = host->up;
- st.check_cnt = host->check_cnt;
- st.retry_cnt = host->retry_cnt;
- host->flags |= (F_CHECK_SENT|F_CHECK_DONE);
- if (msg)
- log_debug("hce_notify_done: %s (%s)", host->conf.name, msg);
-
- imsg_compose(ibuf_pfe, IMSG_HOST_STATUS, 0, 0, -1, &st, sizeof(st));
- if (host->up != host->last_up)
- logopt = HOSTSTATED_OPT_LOGUPDATE;
- else
- logopt = HOSTSTATED_OPT_LOGNOTIFY;
-
- if (gettimeofday(&tv_now, NULL))
- fatal("hce_notify_done: gettimeofday");
- timersub(&tv_now, &host->cte.tv_start, &tv_dur);
- if (timercmp(&host->cte.tv_start, &tv_dur, >))
- duration = (tv_dur.tv_sec * 1000) + (tv_dur.tv_usec / 1000.0);
- else
- duration = 0;
-
- if ((table = table_find(env, host->conf.tableid)) == NULL)
- fatalx("hce_notify_done: invalid table id");
-
- if (env->opts & logopt) {
- log_info("host %s, check %s%s (%lums), state %s -> %s, "
- "availability %s",
- host->conf.name, table_check(table->conf.check),
- (table->conf.flags & F_SSL) ? " use ssl" : "", duration,
- host_status(host->last_up), host_status(host->up),
- print_availability(host->check_cnt, host->up_cnt));
- }
- host->last_up = host->up;
-}
-
-void
-hce_shutdown(void)
-{
- log_info("host check engine exiting");
- _exit(0);
-}
-
-void
-hce_dispatch_imsg(int fd, short event, void *ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
- objid_t id;
- struct host *host;
- struct table *table;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("hce_dispatch_imsg: imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("hce_dispatch_imsg: msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("hce_dispatch_imsg: unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("hce_dispatch_imsg: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_HOST_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- host->flags |= F_DISABLE;
- host->up = HOST_UNKNOWN;
- host->check_cnt = 0;
- host->up_cnt = 0;
- break;
- case IMSG_HOST_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- host->flags &= ~(F_DISABLE);
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_TABLE_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((table = table_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- table->conf.flags |= F_DISABLE;
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_TABLE_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((table = table_find(env, id)) == NULL)
- fatalx("hce_dispatch_imsg: desynchronized");
- table->conf.flags &= ~(F_DISABLE);
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_CTL_POLL:
- evtimer_del(&env->ev);
- TAILQ_FOREACH(table, env->tables, entry)
- table->skipped = 0;
- hce_launch_checks(-1, EV_TIMEOUT, env);
- break;
- default:
- log_debug("hce_dispatch_msg: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-hce_dispatch_parent(int fd, short event, void * ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- struct ctl_script scr;
- ssize_t n;
- size_t len;
-
- static struct table *table = NULL;
- struct host *host;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("hce_dispatch_parent: imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("hce_dispatch_parent: msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("hce_dispatch_parent: unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("hce_dispatch_parent: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_SCRIPT:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(scr))
- fatalx("hce_dispatch_parent: "
- "invalid size of script request");
- bcopy(imsg.data, &scr, sizeof(scr));
- script_done(env, &scr);
- break;
- case IMSG_RECONF:
- log_debug("hce: reloading configuration");
- if (imsg.hdr.len !=
- sizeof(struct hoststated) + IMSG_HEADER_SIZE)
- fatalx("corrupted reload data");
- hce_disable_events();
- purge_config(env, PURGE_TABLES);
- merge_config(env, (struct hoststated *)imsg.data);
-
- env->tables = calloc(1, sizeof(*env->tables));
- if (env->tables == NULL)
- fatal(NULL);
-
- TAILQ_INIT(env->tables);
- break;
- case IMSG_RECONF_TABLE:
- if ((table = calloc(1, sizeof(*table))) == NULL)
- fatal(NULL);
- memcpy(&table->conf, imsg.data, sizeof(table->conf));
- TAILQ_INIT(&table->hosts);
- TAILQ_INSERT_TAIL(env->tables, table, entry);
- break;
- case IMSG_RECONF_SENDBUF:
- len = imsg.hdr.len - IMSG_HEADER_SIZE;
- table->sendbuf = calloc(1, len);
- (void)strlcpy(table->sendbuf, (char *)imsg.data, len);
- break;
- case IMSG_RECONF_HOST:
- if ((host = calloc(1, sizeof(*host))) == NULL)
- fatal(NULL);
- memcpy(&host->conf, imsg.data, sizeof(host->conf));
- host->tablename = table->conf.name;
- TAILQ_INSERT_TAIL(&table->hosts, host, entry);
- break;
- case IMSG_RECONF_END:
- log_warnx("hce: configuration reloaded");
- hce_setup_events();
- break;
- default:
- log_debug("hce_dispatch_parent: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
diff --git a/usr.sbin/hoststated/hoststated.8 b/usr.sbin/hoststated/hoststated.8
deleted file mode 100644
index d488117d83c..00000000000
--- a/usr.sbin/hoststated/hoststated.8
+++ /dev/null
@@ -1,146 +0,0 @@
-.\" $OpenBSD: hoststated.8,v 1.10 2007/09/28 18:08:00 pyr Exp $
-.\"
-.\" Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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.
-.\"
-.Dd $Mdocdate: September 28 2007 $
-.Dt HOSTSTATED 8
-.Os
-.Sh NAME
-.Nm hoststated
-.Nd Host Status daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl dnv
-.Oo Xo
-.Fl D Ar macro Ns = Ns Ar value Oc
-.Xc
-.Op Fl f Ar file
-.Sh DESCRIPTION
-.Nm
-is a host status daemon for server load-balancing.
-It monitors groups of hosts for availability,
-which is determined by checking for a specific service
-common to a host group.
-When availability is confirmed, Layer 3 and/or Layer 7
-load-balancing services are set up by
-.Nm .
-.Pp
-Layer 3 load-balancing happens at the packet level; to configure
-it,
-.Nm
-communicates with
-.Xr pf 4 .
-To allow
-.Nm
-to properly set up
-.Xr pf 4
-rules, the following line is required in the NAT section of
-.Xr pf.conf 5 :
-.Bd -literal -offset indent
-rdr-anchor "hoststated/*"
-.Ed
-.Pp
-Layer 7 load-balancing happens at the application level and is
-handled by
-.Nm
-itself.
-.Pp
-.Nm
-works in terms of the following
-.Em entities :
-relays, protocols, services, and tables.
-A
-.Em relay
-represents a Layer 7 load-balancing instance.
-Each instance translates to a listening TCP or UDP port.
-A
-.Em protocol
-defines which actions, if any, must be taken on the
-packet payload as data crosses a relay.
-A
-.Em service
-represents a Layer 3 load-balancing instance.
-Each instance translates to a
-.Xr pf 4
-rdr rule being added.
-A
-.Em table
-represents a group of hosts which can be checked for
-availability using the same method.
-Each table contains at least one host.
-If a table is used in a Layer 3 load-balancing instance, it
-will be mapped to a
-.Xr pf 4
-table containing only hosts which are up.
-.Pp
-All these entities can be configured in
-.Xr hoststated.conf 5
-and
-.Xr hoststatectl 8
-can be used to alter or report the status of each entity.
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl D Ar macro Ns = Ns Ar value
-Define
-.Ar macro
-to be set to
-.Ar value
-on the command line.
-Overrides the definition of
-.Ar macro
-in the configuration file.
-.It Fl d
-Do not daemonize.
-If this option is specified,
-.Nm
-will run in the foreground and log to
-.Em stderr .
-.It Fl f Ar file
-Specify an alternative configuration file.
-The default is
-.Pa /etc/hoststated.conf .
-.It Fl n
-Configtest mode.
-Only check the configuration file for validity.
-.It Fl v
-Produce more verbose output.
-.El
-.Sh FILES
-.Bl -tag -width "/var/run/hoststated.sockXX" -compact
-.It /etc/hoststated.conf
-Default
-.Nm
-configuration file.
-.It /var/run/hoststated.sock
-Unix-domain socket used for communication with
-.Xr hoststatectl 8 .
-.El
-.Sh SEE ALSO
-.Xr hoststated.conf 5 ,
-.Xr hoststatectl 8
-.Sh HISTORY
-The
-.Nm
-program first appeared in
-.Ox 4.1 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm
-program was written by
-.An Pierre-Yves Ritschard Aq pyr@openbsd.org
-and
-.An Reyk Floeter Aq reyk@openbsd.org .
diff --git a/usr.sbin/hoststated/hoststated.c b/usr.sbin/hoststated/hoststated.c
deleted file mode 100644
index c0ea8f8d7ef..00000000000
--- a/usr.sbin/hoststated/hoststated.c
+++ /dev/null
@@ -1,971 +0,0 @@
-/* $OpenBSD: hoststated.c,v 1.61 2007/11/28 11:37:59 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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/wait.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <signal.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <sha1.h>
-#include <md5.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-__dead void usage(void);
-
-void main_sig_handler(int, short, void *);
-void main_shutdown(struct hoststated *);
-void main_dispatch_pfe(int, short, void *);
-void main_dispatch_hce(int, short, void *);
-void main_dispatch_relay(int, short, void *);
-int check_child(pid_t, const char *);
-int send_all(struct hoststated *, enum imsg_type,
- void *, u_int16_t);
-void reconfigure(void);
-void purge_tree(struct proto_tree *);
-
-int pipe_parent2pfe[2];
-int pipe_parent2hce[2];
-int pipe_pfe2hce[2];
-int pipe_parent2relay[RELAY_MAXPROC][2];
-int pipe_pfe2relay[RELAY_MAXPROC][2];
-
-struct hoststated *hoststated_env;
-
-struct imsgbuf *ibuf_pfe;
-struct imsgbuf *ibuf_hce;
-struct imsgbuf *ibuf_relay;
-
-pid_t pfe_pid = 0;
-pid_t hce_pid = 0;
-pid_t relay_pid = 0;
-
-void
-main_sig_handler(int sig, short event, void *arg)
-{
- struct hoststated *env = arg;
- int die = 0;
-
- switch (sig) {
- case SIGTERM:
- case SIGINT:
- die = 1;
- /* FALLTHROUGH */
- case SIGCHLD:
- if (check_child(pfe_pid, "pf update engine")) {
- pfe_pid = 0;
- die = 1;
- }
- if (check_child(hce_pid, "host check engine")) {
- hce_pid = 0;
- die = 1;
- }
- if (check_child(relay_pid, "socket relay engine")) {
- relay_pid = 0;
- die = 1;
- }
- if (die)
- main_shutdown(env);
- break;
- case SIGHUP:
- reconfigure();
- break;
- default:
- fatalx("unexpected signal");
- }
-}
-
-/* __dead is for lint */
-__dead void
-usage(void)
-{
- extern char *__progname;
-
- fprintf(stderr, "%s [-dnv] [-D macro=value] [-f file]\n", __progname);
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- int c;
- int debug;
- u_int32_t opts;
- struct hoststated *env;
- const char *conffile;
- struct event ev_sigint;
- struct event ev_sigterm;
- struct event ev_sigchld;
- struct event ev_sighup;
- struct imsgbuf *ibuf;
-
- opts = 0;
- debug = 0;
- conffile = CONF_FILE;
-
- log_init(1); /* log to stderr until daemonized */
-
- while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
- switch (c) {
- case 'd':
- debug = 2;
- break;
- case 'D':
- if (cmdline_symset(optarg) < 0)
- log_warnx("could not parse macro definition %s",
- optarg);
- break;
- case 'n':
- debug = 2;
- opts |= HOSTSTATED_OPT_NOACTION;
- break;
- case 'f':
- conffile = optarg;
- break;
- case 'v':
- opts |= HOSTSTATED_OPT_VERBOSE;
- break;
- default:
- usage();
- }
- }
-
- if ((env = parse_config(conffile, opts)) == NULL)
- exit(1);
- hoststated_env = env;
-
- if (env->opts & HOSTSTATED_OPT_NOACTION) {
- fprintf(stderr, "configuration OK\n");
- exit(0);
- }
- if (debug)
- env->opts |= HOSTSTATED_OPT_LOGUPDATE;
-
- if (geteuid())
- errx(1, "need root privileges");
-
- if (getpwnam(HOSTSTATED_USER) == NULL)
- errx(1, "unknown user %s", HOSTSTATED_USER);
-
- log_init(debug);
-
- if (!debug) {
- if (daemon(1, 0) == -1)
- err(1, "failed to daemonize");
- }
-
- log_info("startup");
-
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_parent2pfe) == -1)
- fatal("socketpair");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_parent2hce) == -1)
- fatal("socketpair");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_pfe2hce) == -1)
- fatal("socketpair");
- for (c = 0; c < env->prefork_relay; c++) {
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_parent2relay[c]) == -1)
- fatal("socketpair");
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
- pipe_pfe2relay[c]) == -1)
- fatal("socketpair");
- session_socket_blockmode(pipe_pfe2relay[c][0], BM_NONBLOCK);
- session_socket_blockmode(pipe_pfe2relay[c][1], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2relay[c][0], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2relay[c][1], BM_NONBLOCK);
- }
-
- session_socket_blockmode(pipe_parent2pfe[0], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2pfe[1], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2hce[0], BM_NONBLOCK);
- session_socket_blockmode(pipe_parent2hce[1], BM_NONBLOCK);
- session_socket_blockmode(pipe_pfe2hce[0], BM_NONBLOCK);
- session_socket_blockmode(pipe_pfe2hce[1], BM_NONBLOCK);
-
- pfe_pid = pfe(env, pipe_parent2pfe, pipe_parent2hce,
- pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
- hce_pid = hce(env, pipe_parent2pfe, pipe_parent2hce,
- pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
- if (env->prefork_relay > 0)
- relay_pid = relay(env, pipe_parent2pfe, pipe_parent2hce,
- pipe_parent2relay, pipe_pfe2hce, pipe_pfe2relay);
-
- setproctitle("parent");
-
- event_init();
-
- signal_set(&ev_sigint, SIGINT, main_sig_handler, env);
- signal_set(&ev_sigterm, SIGTERM, main_sig_handler, env);
- signal_set(&ev_sigchld, SIGCHLD, main_sig_handler, env);
- signal_set(&ev_sighup, SIGHUP, main_sig_handler, env);
- signal_add(&ev_sigint, NULL);
- signal_add(&ev_sigterm, NULL);
- signal_add(&ev_sigchld, NULL);
- signal_add(&ev_sighup, NULL);
- signal(SIGPIPE, SIG_IGN);
-
- close(pipe_parent2pfe[1]);
- close(pipe_parent2hce[1]);
- close(pipe_pfe2hce[0]);
- close(pipe_pfe2hce[1]);
- for (c = 0; c < env->prefork_relay; c++) {
- close(pipe_pfe2relay[c][0]);
- close(pipe_pfe2relay[c][1]);
- close(pipe_parent2relay[c][0]);
- }
-
- if ((ibuf_pfe = calloc(1, sizeof(struct imsgbuf))) == NULL ||
- (ibuf_hce = calloc(1, sizeof(struct imsgbuf))) == NULL)
- fatal(NULL);
-
- if (env->prefork_relay > 0) {
- if ((ibuf_relay = calloc(env->prefork_relay,
- sizeof(struct imsgbuf))) == NULL)
- fatal(NULL);
- }
-
- imsg_init(ibuf_pfe, pipe_parent2pfe[0], main_dispatch_pfe);
- imsg_init(ibuf_hce, pipe_parent2hce[0], main_dispatch_hce);
- for (c = 0; c < env->prefork_relay; c++) {
- ibuf = &ibuf_relay[c];
- imsg_init(ibuf, pipe_parent2relay[c][1], main_dispatch_relay);
- ibuf->events = EV_READ;
- event_set(&ibuf->ev, ibuf->fd, ibuf->events,
- ibuf->handler, ibuf);
- event_add(&ibuf->ev, NULL);
- }
-
- ibuf_pfe->events = EV_READ;
- event_set(&ibuf_pfe->ev, ibuf_pfe->fd, ibuf_pfe->events,
- ibuf_pfe->handler, ibuf_pfe);
- event_add(&ibuf_pfe->ev, NULL);
-
- ibuf_hce->events = EV_READ;
- event_set(&ibuf_hce->ev, ibuf_hce->fd, ibuf_hce->events,
- ibuf_hce->handler, ibuf_hce);
- event_add(&ibuf_hce->ev, NULL);
-
- if (env->flags & F_DEMOTE)
- carp_demote_reset(env->demote_group, 0);
-
- event_dispatch();
-
- return (0);
-}
-
-void
-main_shutdown(struct hoststated *env)
-{
- pid_t pid;
-
- if (pfe_pid)
- kill(pfe_pid, SIGTERM);
- if (hce_pid)
- kill(hce_pid, SIGTERM);
- if (relay_pid)
- kill(relay_pid, SIGTERM);
-
- do {
- if ((pid = wait(NULL)) == -1 &&
- errno != EINTR && errno != ECHILD)
- fatal("wait");
- } while (pid != -1 || (pid == -1 && errno == EINTR));
-
- control_cleanup();
- carp_demote_shutdown();
- if (env->flags & F_DEMOTE)
- carp_demote_reset(env->demote_group, 128);
- log_info("terminating");
- exit(0);
-}
-
-int
-check_child(pid_t pid, const char *pname)
-{
- int status;
-
- if (waitpid(pid, &status, WNOHANG) > 0) {
- if (WIFEXITED(status)) {
- log_warnx("check_child: lost child: %s exited", pname);
- return (1);
- }
- if (WIFSIGNALED(status)) {
- log_warnx("check_child: lost child: %s terminated; "
- "signal %d", pname, WTERMSIG(status));
- return (1);
- }
- }
-
- return (0);
-}
-
-int
-send_all(struct hoststated *env, enum imsg_type type, void *buf, u_int16_t len)
-{
- int i;
-
- if (imsg_compose(ibuf_pfe, type, 0, 0, -1, buf, len) == -1)
- return (-1);
- if (imsg_compose(ibuf_hce, type, 0, 0, -1, buf, len) == -1)
- return (-1);
- for (i = 0; i < env->prefork_relay; i++) {
- if (imsg_compose(&ibuf_relay[i], type, 0, 0, -1, buf, len)
- == -1)
- return (-1);
- }
- return (0);
-}
-
-void
-merge_config(struct hoststated *env, struct hoststated *new_env)
-{
- env->opts = new_env->opts;
- env->flags = new_env->flags;
- env->confpath = new_env->confpath;
- env->tablecount = new_env->tablecount;
- env->servicecount = new_env->servicecount;
- env->protocount = new_env->protocount;
- env->relaycount = new_env->relaycount;
-
- memcpy(&env->interval, &new_env->interval, sizeof(env->interval));
- memcpy(&env->timeout, &new_env->timeout, sizeof(env->timeout));
- memcpy(&env->empty_table, &new_env->empty_table,
- sizeof(env->empty_table));
- memcpy(&env->proto_default, &new_env->proto_default,
- sizeof(env->proto_default));
- env->prefork_relay = new_env->prefork_relay;
- (void)strlcpy(env->demote_group, new_env->demote_group,
- sizeof(env->demote_group));
-
- env->tables = new_env->tables;
- env->services = new_env->services;
- env->relays = new_env->relays;
- env->protos = new_env->protos;
-}
-
-
-void
-reconfigure(void)
-{
- struct hoststated *env = hoststated_env;
- struct hoststated *new_env;
- struct service *service;
- struct address *virt;
- struct table *table;
- struct host *host;
-
- log_info("reloading configuration");
- if ((new_env = parse_config(env->confpath, env->opts)) == NULL)
- exit(1);
-
- purge_config(env, PURGE_EVERYTHING);
- merge_config(env, new_env);
- free(new_env);
- log_info("configuration merge done");
-
- /*
- * first reconfigure pfe
- */
- imsg_compose(ibuf_pfe, IMSG_RECONF, 0, 0, -1, env, sizeof(*env));
- TAILQ_FOREACH(table, env->tables, entry) {
- imsg_compose(ibuf_pfe, IMSG_RECONF_TABLE, 0, 0, -1,
- &table->conf, sizeof(table->conf));
- TAILQ_FOREACH(host, &table->hosts, entry) {
- imsg_compose(ibuf_pfe, IMSG_RECONF_HOST, 0, 0, -1,
- &host->conf, sizeof(host->conf));
- }
- }
- TAILQ_FOREACH(service, env->services, entry) {
- imsg_compose(ibuf_pfe, IMSG_RECONF_SERVICE, 0, 0, -1,
- &service->conf, sizeof(service->conf));
- TAILQ_FOREACH(virt, &service->virts, entry)
- imsg_compose(ibuf_pfe, IMSG_RECONF_VIRT, 0, 0, -1,
- virt, sizeof(*virt));
- }
- imsg_compose(ibuf_pfe, IMSG_RECONF_END, 0, 0, -1, NULL, 0);
-
- /*
- * then reconfigure hce
- */
- imsg_compose(ibuf_hce, IMSG_RECONF, 0, 0, -1, env, sizeof(*env));
- TAILQ_FOREACH(table, env->tables, entry) {
- imsg_compose(ibuf_hce, IMSG_RECONF_TABLE, 0, 0, -1,
- &table->conf, sizeof(table->conf));
- if (table->sendbuf != NULL)
- imsg_compose(ibuf_hce, IMSG_RECONF_SENDBUF, 0, 0, -1,
- table->sendbuf, strlen(table->sendbuf) + 1);
- TAILQ_FOREACH(host, &table->hosts, entry) {
- imsg_compose(ibuf_hce, IMSG_RECONF_HOST, 0, 0, -1,
- &host->conf, sizeof(host->conf));
- }
- }
- imsg_compose(ibuf_hce, IMSG_RECONF_END, 0, 0, -1, NULL, 0);
-}
-
-void
-purge_config(struct hoststated *env, u_int8_t what)
-{
- struct table *table;
- struct host *host;
- struct service *service;
- struct address *virt;
- struct protocol *proto;
- struct relay *rly;
- struct session *sess;
-
- if (what & PURGE_TABLES && env->tables != NULL) {
- while ((table = TAILQ_FIRST(env->tables)) != NULL) {
-
- while ((host = TAILQ_FIRST(&table->hosts)) != NULL) {
- TAILQ_REMOVE(&table->hosts, host, entry);
- free(host);
- }
- if (table->sendbuf != NULL)
- free(table->sendbuf);
- if (table->conf.flags & F_SSL)
- SSL_CTX_free(table->ssl_ctx);
-
- TAILQ_REMOVE(env->tables, table, entry);
-
- free(table);
- }
- free(env->tables);
- env->tables = NULL;
- }
-
- if (what & PURGE_SERVICES && env->services != NULL) {
- while ((service = TAILQ_FIRST(env->services)) != NULL) {
- TAILQ_REMOVE(env->services, service, entry);
- while ((virt = TAILQ_FIRST(&service->virts)) != NULL) {
- TAILQ_REMOVE(&service->virts, virt, entry);
- free(virt);
- }
- free(service);
- }
- free(env->services);
- env->services = NULL;
- }
-
- if (what & PURGE_RELAYS && env->relays != NULL) {
- while ((rly = TAILQ_FIRST(env->relays)) != NULL) {
- TAILQ_REMOVE(env->relays, rly, entry);
- while ((sess = SPLAY_ROOT(&rly->sessions)) != NULL) {
- SPLAY_REMOVE(session_tree,
- &rly->sessions, sess);
- free(sess);
- }
- if (rly->bev != NULL)
- bufferevent_free(rly->bev);
- if (rly->dstbev != NULL)
- bufferevent_free(rly->dstbev);
- if (rly->ssl_ctx != NULL)
- SSL_CTX_free(rly->ssl_ctx);
- free(rly);
- }
- free(env->relays);
- env->relays = NULL;
- }
-
- if (what & PURGE_PROTOS && env->protos != NULL) {
- while ((proto = TAILQ_FIRST(env->protos)) != NULL) {
- TAILQ_REMOVE(env->protos, proto, entry);
- purge_tree(&proto->request_tree);
- purge_tree(&proto->response_tree);
- if (proto->style != NULL)
- free(proto->style);
- free(proto);
- }
- free(env->protos);
- env->protos = NULL;
- }
-}
-
-void
-purge_tree(struct proto_tree *tree)
-{
- struct protonode *proot, *pn;
-
- while ((proot = RB_ROOT(tree)) != NULL) {
- RB_REMOVE(proto_tree, tree, proot);
- if (proot->key != NULL)
- free(proot->key);
- if (proot->value != NULL)
- free(proot->value);
- while ((pn = SIMPLEQ_FIRST(&proot->head)) != NULL) {
- SIMPLEQ_REMOVE_HEAD(&proot->head, entry);
- if (pn->key != NULL)
- free(pn->key);
- if (pn->value != NULL)
- free(pn->value);
- if (pn->label != 0)
- pn_unref(pn->label);
- free(pn);
- }
- free(proot);
- }
-}
-
-void
-imsg_event_add(struct imsgbuf *ibuf)
-{
- ibuf->events = EV_READ;
- if (ibuf->w.queued)
- ibuf->events |= EV_WRITE;
-
- event_del(&ibuf->ev);
- event_set(&ibuf->ev, ibuf->fd, ibuf->events, ibuf->handler, ibuf);
- event_add(&ibuf->ev, NULL);
-}
-
-void
-main_dispatch_pfe(int fd, short event, void *ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
- struct ctl_demote demote;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("main_dispatch_pfe: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_DEMOTE:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(demote))
- fatalx("main_dispatch_pfe: "
- "invalid size of demote request");
- memcpy(&demote, imsg.data, sizeof(demote));
- carp_demote_set(demote.group, demote.level);
- break;
- case IMSG_CTL_RELOAD:
- /*
- * so far we only get here if no L7 (relay) is done.
- */
- reconfigure();
- break;
- default:
- log_debug("main_dispatch_pfe: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-main_dispatch_hce(int fd, short event, void * ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
- struct ctl_script scr;
- struct hoststated *env;
-
- env = hoststated_env;
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("main_dispatch_hce: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_SCRIPT:
- if (imsg.hdr.len - IMSG_HEADER_SIZE !=
- sizeof(scr))
- fatalx("main_dispatch_hce: "
- "invalid size of script request");
- bcopy(imsg.data, &scr, sizeof(scr));
- scr.retval = script_exec(env, &scr);
- imsg_compose(ibuf_hce, IMSG_SCRIPT,
- 0, 0, -1, &scr, sizeof(scr));
- break;
- default:
- log_debug("main_dispatch_hce: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-main_dispatch_relay(int fd, short event, void * ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("main_dispatch_relay: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- default:
- log_debug("main_dispatch_relay: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-struct host *
-host_find(struct hoststated *env, objid_t id)
-{
- struct table *table;
- struct host *host;
-
- TAILQ_FOREACH(table, env->tables, entry)
- TAILQ_FOREACH(host, &table->hosts, entry)
- if (host->conf.id == id)
- return (host);
- return (NULL);
-}
-
-struct table *
-table_find(struct hoststated *env, objid_t id)
-{
- struct table *table;
-
- TAILQ_FOREACH(table, env->tables, entry)
- if (table->conf.id == id)
- return (table);
- return (NULL);
-}
-
-struct service *
-service_find(struct hoststated *env, objid_t id)
-{
- struct service *service;
-
- TAILQ_FOREACH(service, env->services, entry)
- if (service->conf.id == id)
- return (service);
- return (NULL);
-}
-
-struct relay *
-relay_find(struct hoststated *env, objid_t id)
-{
- struct relay *rlay;
-
- TAILQ_FOREACH(rlay, env->relays, entry)
- if (rlay->conf.id == id)
- return (rlay);
- return (NULL);
-}
-
-struct session *
-session_find(struct hoststated *env, objid_t id)
-{
- struct relay *rlay;
- struct session *con;
-
- TAILQ_FOREACH(rlay, env->relays, entry)
- SPLAY_FOREACH(con, session_tree, &rlay->sessions)
- if (con->id == id)
- return (con);
- return (NULL);
-}
-
-struct host *
-host_findbyname(struct hoststated *env, const char *name)
-{
- struct table *table;
- struct host *host;
-
- TAILQ_FOREACH(table, env->tables, entry)
- TAILQ_FOREACH(host, &table->hosts, entry)
- if (strcmp(host->conf.name, name) == 0)
- return (host);
- return (NULL);
-}
-
-struct table *
-table_findbyname(struct hoststated *env, const char *name)
-{
- struct table *table;
-
- TAILQ_FOREACH(table, env->tables, entry)
- if (strcmp(table->conf.name, name) == 0)
- return (table);
- return (NULL);
-}
-
-struct service *
-service_findbyname(struct hoststated *env, const char *name)
-{
- struct service *service;
-
- TAILQ_FOREACH(service, env->services, entry)
- if (strcmp(service->conf.name, name) == 0)
- return (service);
- return (NULL);
-}
-
-struct relay *
-relay_findbyname(struct hoststated *env, const char *name)
-{
- struct relay *rlay;
-
- TAILQ_FOREACH(rlay, env->relays, entry)
- if (strcmp(rlay->conf.name, name) == 0)
- return (rlay);
- 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);
-}
-
-int
-expand_string(char *label, size_t len, const char *srch, const char *repl)
-{
- char *tmp;
- char *p, *q;
-
- if ((tmp = calloc(1, len)) == NULL) {
- log_debug("expand_string: calloc");
- return (-1);
- }
- p = q = label;
- while ((q = strstr(p, srch)) != NULL) {
- *q = '\0';
- if ((strlcat(tmp, p, len) >= len) ||
- (strlcat(tmp, repl, len) >= len)) {
- log_debug("expand_string: string too long");
- return (-1);
- }
- q += strlen(srch);
- p = q;
- }
- if (strlcat(tmp, p, len) >= len) {
- log_debug("expand_string: string too long");
- return (-1);
- }
- (void)strlcpy(label, tmp, len); /* always fits */
- free(tmp);
-
- return (0);
-}
-
-void
-translate_string(char *str)
-{
- char *reader;
- char *writer;
-
- reader = writer = str;
-
- while (*reader) {
- if (*reader == '\\') {
- reader++;
- switch (*reader) {
- case 'n':
- *writer++ = '\n';
- break;
- case 'r':
- *writer++ = '\r';
- break;
- default:
- *writer++ = *reader;
- }
- } else
- *writer++ = *reader;
- reader++;
- }
- *writer = '\0';
-}
-
-char *
-digeststr(enum digest_type type, const u_int8_t *data, size_t len, char *buf)
-{
- switch (type) {
- case DIGEST_SHA1:
- return (SHA1Data(data, len, buf));
- break;
- case DIGEST_MD5:
- return (MD5Data(data, len, buf));
- break;
- default:
- break;
- }
- return (NULL);
-}
-
-const char *
-canonicalize_host(const char *host, char *name, size_t len)
-{
- struct sockaddr_in sin4;
- struct sockaddr_in6 sin6;
- u_int i, j;
- size_t plen;
- char c;
-
- if (len < 2)
- goto fail;
-
- /*
- * Canonicalize an IPv4/6 address
- */
- if (inet_pton(AF_INET, host, &sin4) == 1)
- return (inet_ntop(AF_INET, &sin4, name, len));
- if (inet_pton(AF_INET6, host, &sin6) == 1)
- return (inet_ntop(AF_INET6, &sin6, name, len));
-
- /*
- * Canonicalize a hostname
- */
-
- /* 1. remove repeated dots and convert upper case to lower case */
- plen = strlen(host);
- bzero(name, len);
- for (i = j = 0; i < plen; i++) {
- if (j >= (len - 1))
- goto fail;
- c = tolower(host[i]);
- if ((c == '.') && (j == 0 || name[j - 1] == '.'))
- continue;
- name[j++] = c;
- }
-
- /* 2. remove trailing dots */
- for (i = j; i > 0; i--) {
- if (name[i - 1] != '.')
- break;
- name[i - 1] = '\0';
- j--;
- }
- if (j <= 0)
- goto fail;
-
- return (name);
-
- fail:
- errno = EINVAL;
- return (NULL);
-}
diff --git a/usr.sbin/hoststated/hoststated.conf.5 b/usr.sbin/hoststated/hoststated.conf.5
deleted file mode 100644
index d82f2942121..00000000000
--- a/usr.sbin/hoststated/hoststated.conf.5
+++ /dev/null
@@ -1,965 +0,0 @@
-.\" $OpenBSD: hoststated.conf.5,v 1.69 2007/11/26 09:38:25 reyk Exp $
-.\"
-.\" Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
-.\" Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.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.
-.\"
-.Dd $Mdocdate: November 26 2007 $
-.Dt HOSTSTATED.CONF 5
-.Os
-.Sh NAME
-.Nm hoststated.conf
-.Nd Host Status daemon configuration file
-.Sh DESCRIPTION
-.Nm
-is the configuration file for the Host Status Daemon,
-.Xr hoststated 8 .
-.Sh SECTIONS
-.Nm
-is divided into six main sections:
-.Bl -tag -width xxxx
-.It Sy Macros
-User-defined variables may be defined and used later, simplifying the
-configuration file.
-.It Sy Global Configuration
-Global settings for
-.Xr hoststated 8 .
-.It Sy Tables
-Table definitions describe the content of a
-.Xr pf 4
-table and the method used for checking the health of the hosts
-they contain.
-.It Sy Services
-Services will be translated to
-.Xr pf 4
-rdr rules if their table or backup table have content.
-.It Sy Relays
-Relays allow layer 7 load balancing, SSL acceleration, and
-general purpose TCP proxying.
-.It Sy Protocols
-Protocols are predefined protocol handlers and settings for relays.
-.El
-.Pp
-Within the sections,
-a host
-.Ar address
-can be either specified by IPv4 address, IPv6 address, or DNS hostname.
-A
-.Ar port
-can be either specified by number or by name.
-The port name to number mappings are found in the file
-.Pa /etc/services ;
-see
-.Xr services 5
-for details.
-.Pp
-Comments can be put anywhere in the file using a hash mark
-.Pq Sq # ,
-and extend to the end of the current line.
-.Pp
-Additional configuration files can be included with the
-.Ic include
-keyword, for example:
-.Bd -literal -offset indent
-include "/etc/hoststated.conf.local"
-.Ed
-.Sh MACROS
-Macros can be defined that will later be expanded in context.
-Macro names must start with a letter, and may contain letters, digits,
-and underscores.
-Macro names may not be reserved words (for example,
-.Ic table ,
-.Ic service ,
-or
-.Ic timeout ) .
-Macros are not expanded inside quotes.
-.Pp
-For example:
-.Bd -literal -offset indent
-www1="10.0.0.1"
-www2="10.0.0.2"
-table webhosts {
- check tcp
- timeout 300
- real port 80
- host $www1
- host $www2
-}
-.Ed
-.Sh GLOBAL CONFIGURATION
-Here are the settings that can be set globally:
-.Pp
-.Bl -tag -width Ds -compact
-.It Ic demote Ar group
-Enable the global
-.Xr carp 4
-demotion option, this will reset the carp demotion counter for the
-specified interface group to zero on startup and to 128 on shutdown of
-the daemon.
-For more information on interface groups,
-see the
-.Ic group
-keyword in
-.Xr ifconfig 8 .
-.Pp
-.It Xo
-.Ic interval Ar number
-.Xc
-Set the interval in seconds at which the hosts will be checked.
-The default interval is 10 seconds.
-.Pp
-.It Xo
-.Ic log
-.Pq Ic updates Ns \&| Ns Ic all
-.Xc
-Log state notifications after completed host checks.
-Either only log the
-.Ic updates
-to new states or log
-.Ic all
-state notifications, even if the state didn't change.
-The host state can be
-.Ar up
-(the health check completed successfully),
-.Ar down
-(the host is down or didn't match the check criteria),
-or
-.Ar unknown
-(the host is disabled or has not been checked yet).
-.Pp
-.It Ic prefork Ar number
-When using relays, run the specified number of processes to handle
-relayed connections.
-This will increase the performance and prevents delays when connecting
-to a relay.
-.Xr hoststated 8
-will run 5 relay processes by default and every process will handle
-all configured relays.
-.Pp
-.It Xo
-.Ic timeout Ar number
-.Xc
-Set the global timeout in milliseconds for checks.
-This can be overriden by the timeout value in the table definitions.
-The default interval is 200 milliseconds and it must not exceed the
-global interval.
-.El
-.Sh TABLES
-Tables are used to group a set of hosts that can be checked using the same
-method.
-Only one health-checking method can be used per table.
-Table specific configuration directives are described below.
-.Bl -tag -width Ds
-.It Xo
-.Ic check http Ar path
-.Op Ic host Ar hostname
-.Ic code Ar number
-.Xc
-For each host in the table, verify that retrieving the URL
-.Ar path
-gives the HTTP return code
-.Ar number .
-If
-.Ar hostname
-is specified, it is used as the
-.Dq Host:
-header to query a specific hostname at target host.
-.It Xo
-.Ic check https Ar path
-.Op Ic host Ar hostname
-.Ic code Ar number
-.Xc
-This has the same effect as above but wraps the HTTP request in SSL.
-.It Xo
-.Ic check http Ar path
-.Op Ic host Ar hostname
-.Ic digest Ar string
-.Xc
-For each host in the table, verify that retrieving the URL
-.Ar path
-produces content whose message digest matches the defined string.
-The algorithm used is determined by the string length of the
-.Ar digest
-argument, either SHA1 (40 characters) or MD5 (32 characters).
-If
-.Ar hostname
-is specified, it is used as the
-.Dq Host:
-header to query a specific hostname at target host.
-The digest does not take the HTTP headers into account.
-To compute the digest, use this simple command:
-.Bd -literal -offset indent
-ftp -o - http://host[:port]/path | sha1
-.Ed
-.Pp
-This gives a digest
-that can be used as is in a digest statement:
-.Bd -literal -offset indent
-a9993e36476816aba3e25717850c26c9cd0d89d
-.Ed
-.It Xo
-.Ic check https Ar path
-.Op Ic host Ar hostname
-.Ic digest Ar string
-.Xc
-This has the same effect as above but wraps the HTTP request in SSL.
-.It Ic check icmp
-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 Xo
-.Ic check send
-.Ar data
-.Ic expect
-.Ar pattern
-.Op Ic ssl
-.Xc
-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 pattern
-using shell globbing rules.
-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.
-If the
-.Ic ssl
-keyword is present,
-the transaction will occur in an SSL tunnel.
-.It Ic check script Ar path
-Execute an external program to check the host state.
-The program will be executed for each host by specifing the hostname
-on the command line:
-.Bd -literal -offset indent
-/usr/local/bin/checkload.pl front-www1.private.example.com
-.Ed
-.Pp
-.Xr hoststated 8
-expects a positive return value on success and zero on failure.
-Note that the script will be executed with the privileges of the
-.Qq _hoststated
-user and terminated after
-.Ar timeout
-milliseconds.
-.It Ic check ssl
-Perform a complete SSL handshake with each host to check their availability.
-.It Ic check tcp
-Use a simple TCP connect to check that hosts are up.
-.It Ic demote Ar group
-Enable the per-table
-.Xr carp 4
-demotion option.
-This will increment the carp demotion counter for the
-specified interface group if all hosts in the table are down.
-For more information on interface groups,
-see the
-.Ic group
-keyword in
-.Xr ifconfig 8 .
-.It Ic disable
-Start the table disabled \(en no hosts will be checked in this table.
-The table can be later enabled through
-.Xr hoststatectl 8 .
-.It Xo
-.Ic host Ar address
-.Op Ic retry Ar number
-.Xc
-Add the host whose address is
-.Ar address
-to the list of hosts to be checked in this table.
-Each table needs at least one host.
-The optional retry option adds a tolerance for failed host checks,
-the check will be retried for
-.Ar number
-more times before setting the host state to down.
-.It Ic interval Ar number
-Override the global interval and specify one for this table.
-It must be a multiple of the global interval.
-.It Ic real port Ar port
-When using the TCP or HTTP checking methods, use this
-.Ar port
-to connect to hosts.
-If this parameter is not specified,
-.Xr hoststated 8
-will create a template table which inherits the port from the
-referencing service or relay.
-Main and backup tables need to have the same real port.
-.It Ic timeout Ar number
-Set the timeout in milliseconds for each host that is checked using
-TCP as the transport.
-This will override the global timeout, which is 200 milliseconds by default.
-.El
-.Sh SERVICES
-Services represent a
-.Xr pf 4
-rdr rule.
-They are used to specify which addresses will be redirected
-to the hosts in the specified tables.
-The configuration directives that are valid in this context are described
-below.
-.Bl -tag -width Ds
-.It Ic backup table Ar name
-Specify the table to switch to when all hosts in the main table
-are seen as down or disabled.
-.It Ic disable
-Set the service initially disabled.
-It can be later enabled through
-.Xr hoststatectl 8 .
-.It Ic sticky-address
-This has the same effect than specifying sticky-address
-for a rdr rule in
-.Xr pf.conf 5 .
-It will ensure that multiple connections from the same source are
-mapped to the same redirection address.
-.It Xo
-.Ic table Ar name Op Ic port Ar port
-.Xc
-Specify the main table to be used.
-Optionally supply a port which will
-override the real port specification in the table.
-This is mandatory.
-.It Ic tag Ar name
-Automatically tag packets passing through the
-.Xr pf 4
-rdr rule with the name supplied.
-This allows simpler filter rules.
-.It Ic virtual host Ar address Ic port Ar port
-Specify an
-.Ar address
-and a
-.Ar port
-that will be used to redirect requests
-to the hosts in the main or backup table.
-Optionally an interface name can be given as follows,
-to specify which interface the rdr rule will be enabled on:
-.Bd -literal -offset indent
-interface ``ifname''
-.Ed
-.El
-.Sh RELAYS
-Relays will forward TCP traffic between a client and a target server.
-In contrast to IP forwarding and redirection in the network stack, a
-relay will accept incoming TCP connections from remote clients as a
-server, open an outgoing connection to a target host, and forward
-any traffic between the target host and the remote client.
-A relay is also called an application layer or layer 7 proxy.
-.Pp
-The main purpose of a relay is to provide advanced load balancing
-functionality based on specified protocol characteristics, such as
-HTTP headers, to provide SSL acceleration functionality and to allow
-basic handling of the underlying application protocol.
-.Pp
-The relay configuration directives are described below.
-.Bl -tag -width Ds
-.It Xo
-.Ic listen on Ar address Ic port Ar port
-.Op Ic ssl
-.Xc
-Specify the address and port for the relay to listen on.
-The relay will accept incoming connections to the specified address.
-.Pp
-If the
-.Ic ssl
-keyword is present, the relay will accept connections using the
-encrypted SSL protocol.
-The relay will look up a private key in
-.Pa /etc/ssl/private/address.key
-and a public certificate in
-.Pa /etc/ssl/address.crt ,
-where
-.Ar address
-is the specified IP address of the relay to listen on.
-See
-.Xr ssl 8
-for details about SSL server certificates.
-.It Xo
-.Ic forward to Ar address Ic port Ar port
-.Op Ic retry Ar number
-.Xc
-Specify the address and port of the target host to connect to.
-.It Xo
-.Ic service Ar name
-.Op Ic retry Ar number
-.Xc
-Use the first virtual IP address and port from the specified service
-as the target host to connect to.
-This is exclusive to the
-.Ic forward to
-and
-.Ic table
-directives.
-.It Xo
-.Ic table Ar name Ar mode
-.Op Ic no check
-.Xc
-Get the target host from the specified table.
-The following modes are available to select a host from the specified
-table:
-.Pp
-.Bl -tag -width loadbalance -offset indent -compact
-.It Ic roundrobin
-Distributes the outgoing connections using a round-robin scheduler
-through all active hosts.
-.It Ic loadbalance
-Balances the outgoing connections across the active hosts based on the
-hashed name of the table, the source and destination addresses,
-and the corresponding ports.
-.It Ic hash
-Like the
-.Ic loadbalance
-mode, but without including the source and destination addresses and
-ports.
-Additional input can be fed into the hash by looking at HTTP
-headers and GET variables; see the
-.Sx PROTOCOLS
-section below.
-.El
-.Pp
-The optional host retry option will be used as a tolerance for failed
-host connections; the connection will be retried for
-.Ar number
-more times.
-See the
-.Sx TABLES
-section for details about host entries.
-.It Xo
-.Ic nat lookup
-.Op Ic retry Ar number
-.Xc
-When redirecting connections with an
-.Ar rdr
-rule in
-.Xr pf.conf 5
-to a relay listening on localhost, this directive will
-look up the real destination address of the intended target host,
-allowing the relay to be run as a transparent proxy.
-If either the
-.Ic forward to ,
-.Ic service ,
-or
-.Ic table
-directive is present, it will be used as a backup if the NAT lookup
-failed.
-.It Ic timeout Ar seconds
-Specify the timeout in seconds for accepted sessions.
-The default timeout is 600 seconds (10 minutes).
-.It Ic disable
-Start the relay but immediately close any accepted connections.
-.It Ic protocol Ar name
-Use the specified protocol definition for the relay.
-The generic TCP protocol options will be used by default;
-see the
-.Sx PROTOCOLS
-section below.
-.El
-.Sh PROTOCOLS
-Protocols are templates defining actions and settings for relays.
-They allow setting generic TCP options, SSL settings, and actions
-specific to the selected application layer protocol.
-.Pp
-The protocol configuration directives are described below.
-.Bl -tag -width Ds
-.It Ic protocol Ar type
-Enable special handling of the specified application layer protocol.
-The supported TCP protocols are:
-.Pp
-.Bl -tag -width http -offset indent -compact
-.It Ic http
-Handle the Hypertext Transfer Protocol
-(HTTP or "HTTPS" if encapsulated in a SSL tunnel).
-.It Ic tcp
-Generic handler for TCP-based protocols.
-.El
-.Pp
-.Xr hoststated 8
-also supports relaying of UDP protocols.
-There is no generic handler for UDP-based protocols because it is a
-stateless datagram-based protocol which has to look into the
-application layer protocol to find any possible state information.
-The supported UDP protocols are:
-.Pp
-.Bl -tag -width http -offset indent -compact
-.It Ic dns
-Domain Name System (DNS) protocol.
-The request IDs in the DNS header will be used to match the state.
-.Xr hoststated 8
-will replace these IDs with random values to compensate for
-predictable values generated by some hosts.
-.El
-.It Xo
-.Op Ar direction
-.Op Ar type
-.Ar action
-.Op Ic marked Ar id
-.Op Ic log
-.Xc
-Define an action for the selected entity.
-The optional
-.Ic log
-keyword will log the entity name and the value and
-the optional
-.Ic marked
-keyword requires that the session has been marked with a given
-identifier in order to execute the action.
-The actions are depending on the underlying application
-.Ic protocol .
-.Pp
-The following directions are allowed for the specified action:
-.Bl -tag -width Ds
-.It Ic request
-Handle the data stream from the client to the relay, like HTTP
-requests.
-This is the default if the direction directive is omitted.
-.It Ic response
-Handle the data stream from the target host to the relay, like
-HTTP server replies.
-.El
-.Pp
-The following entity types for the actions are available:
-.Bl -tag -width Ds
-.It Ic cookie
-Look up the entity as a value in the Cookie header when using the
-.Ic http
-protocol.
-This type is only available with the direction
-.Ic request .
-.It Ic header
-Look up the entity in the application protocol headers, like HTTP
-headers in
-.Ic http
-mode.
-.It Ic path
-Look up the entity as a value in the URL path when using the
-.Ic http
-protocol.
-This type is only available with the direction
-.Ic request .
-The
-.Ar key
-will match the path of the requested URL without the hostname
-and query and the value will match the complete query,
-for example:
-.Bd -literal -offset indent
-request path filter "/index.html"
-request path filter "foo=bar*" from "/cgi-bin/t.cgi"
-.Ed
-.It Ic query
-Look up the entity as a query variable in the URL when using the
-.Ic http
-protocol.
-This type is only available with the direction
-.Ic request ,
-for example:
-.Bd -literal -offset indent
-# Will match /cgi-bin/example.pl?foo=bar&ok=yes
-request query expect "bar" from "foo"
-.Ed
-.It Ic url
-Look up the entity as a URL suffix/prefix expression consisting of a
-canonicalized hostname without port or suffix and a path name or
-prefix when using the
-.Ic http
-protocol.
-This type is only available with the direction
-.Ic request ,
-for example:
-.Bd -literal -offset indent
-request url filter "example.com/index.html"
-request url filter "example.com/test.cgi?val=1"
-.Ed
-.Pp
-.Xr hoststated 8
-will match the full URL and different possible suffix/prefix
-combinations by stripping subdomains and path components (up to 5
-levels), and the query string.
-For example, the following
-lookups will be done for
-.Ar http://www.example.com:81/1/2/3/4/5.html?query=yes :
-.Bd -literal -offset indent
-www.example.com/1/2/3/4/5.html?query=yes
-www.example.com/1/2/3/4/5.html
-www.example.com/
-www.example.com/1/
-www.example.com/1/2/
-www.example.com/1/2/3/
-example.com/1/2/3/4/5.html?query=yes
-example.com/1/2/3/4/5.html
-example.com/
-example.com/1/
-example.com/1/2/
-example.com/1/2/3/
-.Ed
-.El
-.Pp
-The following actions are available:
-.Bl -tag -width Ds
-.It Ic append Ar value Ic to Ar key
-Append the specified value to a protocol entity with the selected name.
-When using the
-.Ic http
-protocol,
-.Ic key
-will indicate a specified HTTP header.
-If
-.Ar key
-does not exist in the request, it will be created with the value
-set to
-.Ar value .
-.It Ic change Ar key Ic to Ar value
-Like the
-.Ic append
-directive above, but change the contents of the specified entity.
-If
-.Ar key
-does not exist in the request, it will be created with the value
-set to
-.Ar value .
-.It Ic remove Ar key
-Remove the entity with the selected name.
-.It Ic expect Ar value Ic from Ar key
-Expect an entity
-.Ar key
-and match against
-.Ar value
-using shell globbing rules.
-If the entity is not present or the value doesn't match, the connection
-will be dropped.
-.It Xo
-.Ic expect
-.Op Ic digest
-.Ar key
-.Xc
-Expect an entity
-.Ar key
-with any possible value.
-This is the short form of
-.Ic expect Ar * Ic from Ar key .
-.Pp
-If the
-.Ic digest
-keyword is specified,
-compare the message digest of the entity against the defined string.
-The algorithm used is determined by the string length of the
-.Ar key
-argument, either SHA1 (40 characters) or MD5 (32 characters).
-To compute the digest, use this simple command:
-.Bd -literal -offset indent
-echo -n "example.com/path/?args" | sha1
-.Ed
-.It Ic filter Ar value Ic from Ar key
-Like the
-.Ic expect Ar .. Ic from
-directive above, but drop any connections with the specified entity
-.Ar key
-and a matching
-.Ar value .
-.It Xo
-.Ic filter
-.Op Ic digest
-.Ar key
-.Xc
-Like the
-.Ic expect
-directive above, but drop any connections with the specified entity
-.Ar key
-and any possible value.
-This is the short form of
-.Ic filter Ar * Ic from Ar key .
-.It Ic hash Ar key
-Feed the value of the selected entity into the load balancing hash to
-select the target host.
-See the
-.Ic table
-keyword in the
-.Sx RELAYS
-section above.
-.It Ic log Ar key
-Log the name and the value of the entity.
-.It Xo
-.Ic mark
-.Op Ar value Ic from
-.Ar key Ic with Ar id
-.Xc
-Mark the session with the specified identifier (a positive number
-between 1 and 65535) if the specified condition matches.
-Note that the
-.Ic mark
-action does not accept the
-.Ic marked
-option (see above).
-.El
-.It Ic label Ar string
-Add a label to subsequently added actions.
-The label will be printed as part of the error message if the
-.Ic return error
-option is set and may contain HTML tags, for example:
-.Bd -literal -offset indent
-label "<a href='http://example.com/advisory.pl?id=7359'>\e
- Advisory provided by example.com</a>"
-url filter digest 5c1e03f58f8ce0b457474ffb371fd1ef
-url filter digest 80c1a7b8337462093ef8359c57b4d56a
-no label
-.Ed
-.It Ic no label
-Do not set a label for subsequently added actions, this is the default.
-.It Ic return error Op Ar option
-Return an error reponse to the client if an internal operation or the
-forward connection to the client failed.
-By default, the connection will be silently dropped.
-The effect of this option depends on the protocol: HTTP will send an
-error header and page to the client before closing the connection.
-Additional valid options are:
-.Bl -tag -width Ds
-.It Ic style Ar string
-Specify a Cascading Style Sheet (CSS) to be used for the returned
-HTTP error pages, for example:
-.Bd -literal -offset indent
-body { background: #a00000; color: white; }
-.Ed
-.El
-.It Ic tcp Ar option
-Enable or disable the specified TCP/IP options; see
-.Xr tcp 4
-and
-.Xr ip 4
-for more information about the options.
-Valid options are:
-.Bl -tag -width Ds
-.It Ic backlog Ar number
-Set the maximum length the queue of pending connections may grow to.
-The backlog option is 10 by default and is limited by the
-.Ic kern.somaxconn
-.Xr sysctl 8
-variable.
-.It Ic ip minttl Ar number
-This option for the underlying IP connection may be used to discard packets
-with a TTL lower than the specified value.
-This can be used to implement the
-.Ar Generalized TTL Security Mechanism (GTSM)
-according to RFC 3682.
-.It Ic ip ttl
-Change the default time-to-live value in the IP headers.
-.It Xo
-.Op Ic no
-.Ic nodelay
-.Xc
-Enable the TCP NODELAY option for this connection.
-This is recommended to avoid delays in the relayed data stream,
-e.g. for SSH connections.
-.It Xo
-.Op Ic no
-.Ic sack
-.Xc
-Use selective acknowledgements for this connection.
-.It Ic socket buffer Ar number
-Set the socket-level buffer size for input and output for this
-connection.
-This will affect the TCP window size.
-.El
-.It Ic ssl Ar option
-Set the SSL options and session settings.
-This is only used if SSL is enabled in the relay.
-Valid options are:
-.Bl -tag -width Ds
-.It Ic ciphers Ar string
-Set the string defining the SSL cipher suite.
-If not specified, the default value
-.Ar HIGH:!ADH
-will be used (strong crypto cipher suites without anonymous DH).
-See the
-.Sx CIPHERS
-section of
-.Xr openssl 1
-for information about SSL cipher suites and preference lists.
-.It Ic session cache Ar value
-Set the maximum size of the SSL session cache.
-If the
-.Ar value
-is zero, the default size defined by the SSL library will be used.
-A positive number will set the maximum size in bytes and the keyword
-.Ic disable
-will disable the SSL session cache.
-.It Xo
-.Op Ic no
-.Ic sslv2
-.Xc
-Enable the SSLv2 protocol;
-disabled by default.
-.It Xo
-.Op Ic no
-.Ic sslv3
-.Xc
-Disable the SSLv3 protocol;
-enabled by default.
-.It Xo
-.Op Ic no
-.Ic tlsv1
-.Xc
-Disable the TLSv1/SSLv3.1 protocol;
-enabled by default.
-.El
-.El
-.Pp
-The
-.Ar value
-strings of the
-.Ic append
-and
-.Ic change
-directives may contain predefined macros that will be expanded at runtime:
-.Pp
-.Bl -tag -width $SERVER_ADDR -offset indent -compact
-.It Ic $REMOTE_ADDR
-The IP address of the connected client.
-.It Ic $REMOTE_PORT
-The TCP source port of the connected client.
-.It Ic $SERVER_ADDR
-The configured IP address of the relay.
-.It Ic $SERVER_PORT
-The configured TCP server port of the relay.
-.It Ic $TIMEOUT
-The configured session timeout of the relay.
-.El
-.Sh FILES
-.Bl -tag -width "/etc/ssl/private/address.keyXX" -compact
-.It Pa /etc/hoststated.conf
-.Xr hoststated 8
-configuration file.
-.Pp
-.It Pa /etc/services
-Service name database.
-.Pp
-.It Pa /etc/ssl/address.crt
-.It Pa /etc/ssl/private/address.key
-Location of the relay SSL server certificates, where
-.Ar address
-is the configured IP address of the relay.
-.El
-.Sh EXAMPLES
-This configuration file would create a service
-.Dq www
-which load balances four hosts
-and falls back to one host containing a
-.Dq sorry page :
-.Bd -literal -offset indent
-www1=front-www1.private.example.com
-www2=front-www2.private.example.com
-www3=front-www3.private.example.com
-www4=front-www4.private.example.com
-
-interval 5
-
-table phphosts {
- timeout 300
- real port 8080
- check http "/" digest "630aa3c2f..."
- host $www1
- host $www2
- host $www3
- host $www4
-}
-
-table sorryhost {
- check icmp
- disable
- timeout 300
- real port 8080
- host sorryhost.private.example.com
-}
-
-service www {
- virtual host www.example.com port 8080 interface trunk0
- virtual host www6.example.com port 80 interface trunk0
-
- tag HOSTSTATED
- table phphosts
- backup table sorryhost
-}
-.Ed
-.Pp
-The following configuration would add a relay to forward
-secure HTTPS connections to a pool of HTTP webservers
-using the
-.Ic loadbalance
-protocol (SSL acceleration and layer 7 load balancing).
-The HTTP protocol definition will add two HTTP headers containing
-address information of the client and the server, set the
-.Dq Keep-Alive
-header value to the configured session timeout,
-and include the
-.Dq sessid
-variable in the hash to calculate the target host:
-.Bd -literal -offset indent
-protocol http_ssl {
- protocol http
- header append "$REMOTE_ADDR" to "X-Forwarded-For"
- header append "$SERVER_ADDR:$SERVER_PORT" to "X-Forwarded-By"
- header change "Keep-Alive" to "$TIMEOUT"
- query hash "sessid"
- cookie hash "sessid"
- path filter "*command=*" from "/cgi-bin/index.cgi"
-
- ssl { sslv2, ciphers "MEDIUM:HIGH" }
-}
-
-relay sslaccel {
- listen on www.example.com port 443 ssl
- protocol http_ssl
- table phphosts loadbalance
-}
-.Ed
-.Pp
-The second relay example will accept incoming connections to port
-2222 and forward them to a remote SSH server.
-The TCP
-.Ic nodelay
-option will allow a
-.Dq smooth
-SSH session without delays between keystrokes or displayed output on
-the terminal:
-.Bd -literal -offset indent
-protocol myssh {
- tcp { nodelay, socket buffer 65536 }
-}
-
-relay sshforward {
- protocol myssh
- listen on www.example.com port 2222
- forward to shell.example.com port 22
-}
-.Ed
-.Sh SEE ALSO
-.Xr hoststatectl 8 ,
-.Xr hoststated 8 ,
-.Xr ssl 8
-.Sh HISTORY
-The
-.Nm
-file format first appeared in
-.Ox 4.1 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Xr hoststated 8
-program was written by
-.An Pierre-Yves Ritschard Aq pyr@openbsd.org
-and
-.An Reyk Floeter Aq reyk@openbsd.org .
diff --git a/usr.sbin/hoststated/hoststated.h b/usr.sbin/hoststated/hoststated.h
deleted file mode 100644
index 4198325af28..00000000000
--- a/usr.sbin/hoststated/hoststated.h
+++ /dev/null
@@ -1,810 +0,0 @@
-/* $OpenBSD: hoststated.h,v 1.86 2007/11/26 09:38:25 reyk Exp $ */
-
-/*
- * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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/tree.h>
-
-#define CONF_FILE "/etc/hoststated.conf"
-#define HOSTSTATED_SOCKET "/var/run/hoststated.sock"
-#define PF_SOCKET "/dev/pf"
-#define HOSTSTATED_USER "_hoststated"
-#define HOSTSTATED_ANCHOR "hoststated"
-#define HOSTSTATED_SERVERNAME "OpenBSD hoststated"
-#define CHECK_TIMEOUT 200
-#define CHECK_INTERVAL 10
-#define EMPTY_TABLE UINT_MAX
-#define EMPTY_ID UINT_MAX
-#define TABLE_NAME_SIZE 64
-#define TAG_NAME_SIZE 64
-#define SRV_NAME_SIZE 64
-#define MAX_NAME_SIZE 64
-#define SRV_MAX_VIRTS 16
-
-#define RELAY_MAX_SESSIONS 1024
-#define RELAY_TIMEOUT 600
-#define RELAY_CACHESIZE -1 /* use default size */
-#define RELAY_NUMPROC 5
-#define RELAY_MAXPROC 32
-#define RELAY_MAXHOSTS 32
-#define RELAY_STATINTERVAL 60
-#define RELAY_BACKLOG 10
-#define RELAY_MAXLOOKUPLEVELS 5
-
-#define SMALL_READ_BUF_SIZE 1024
-#define READ_BUF_SIZE 65535
-#define ICMP_BUF_SIZE 64
-
-#define PURGE_TABLES 0x01
-#define PURGE_SERVICES 0x02
-#define PURGE_RELAYS 0x04
-#define PURGE_PROTOS 0x08
-#define PURGE_EVERYTHING 0xff
-
-/* buffer */
-struct buf {
- TAILQ_ENTRY(buf) entry;
- u_char *buf;
- size_t size;
- size_t max;
- size_t wpos;
- size_t rpos;
- int fd;
-};
-
-struct msgbuf {
- TAILQ_HEAD(, buf) bufs;
- u_int32_t queued;
- int fd;
-};
-
-#define IMSG_HEADER_SIZE sizeof(struct imsg_hdr)
-#define MAX_IMSGSIZE 8192
-
-struct buf_read {
- u_char buf[READ_BUF_SIZE];
- u_char *rptr;
- size_t wpos;
-};
-
-struct imsg_fd {
- TAILQ_ENTRY(imsg_fd) entry;
- int fd;
-};
-
-struct imsgbuf {
- TAILQ_HEAD(, imsg_fd) fds;
- struct buf_read r;
- struct msgbuf w;
- struct event ev;
- void (*handler)(int, short, void *);
- int fd;
- pid_t pid;
- short events;
-};
-
-enum imsg_type {
- IMSG_NONE,
- IMSG_CTL_OK, /* answer to hoststatectl requests */
- IMSG_CTL_FAIL,
- IMSG_CTL_END,
- IMSG_CTL_SERVICE,
- IMSG_CTL_TABLE,
- IMSG_CTL_HOST,
- IMSG_CTL_RELAY,
- IMSG_CTL_SESSION,
- IMSG_CTL_TABLE_CHANGED,
- IMSG_CTL_PULL_RULESET,
- IMSG_CTL_PUSH_RULESET,
- IMSG_CTL_SHOW_SUM, /* hoststatectl requests */
- IMSG_CTL_SERVICE_ENABLE,
- IMSG_CTL_SERVICE_DISABLE,
- IMSG_CTL_TABLE_ENABLE,
- IMSG_CTL_TABLE_DISABLE,
- IMSG_CTL_HOST_ENABLE,
- IMSG_CTL_HOST_DISABLE,
- IMSG_CTL_SHUTDOWN,
- IMSG_CTL_RELOAD,
- IMSG_CTL_POLL,
- IMSG_CTL_NOTIFY,
- IMSG_CTL_STATISTICS,
- IMSG_SERVICE_ENABLE, /* notifies from pfe to hce */
- IMSG_SERVICE_DISABLE,
- IMSG_TABLE_ENABLE,
- IMSG_TABLE_DISABLE,
- IMSG_HOST_ENABLE,
- IMSG_HOST_DISABLE,
- IMSG_HOST_STATUS, /* notifies from hce to pfe */
- IMSG_SYNC,
- IMSG_NATLOOK,
- IMSG_DEMOTE,
- IMSG_STATISTICS,
- IMSG_RECONF, /* reconfiguration notifies */
- IMSG_RECONF_TABLE,
- IMSG_RECONF_SENDBUF,
- IMSG_RECONF_HOST,
- IMSG_RECONF_SERVICE,
- IMSG_RECONF_VIRT,
- IMSG_RECONF_PROTO,
- IMSG_RECONF_REQUEST_TREE,
- IMSG_RECONF_RESPONSE_TREE,
- IMSG_RECONF_PNODE_KEY,
- IMSG_RECONF_PNODE_VAL,
- IMSG_RECONF_RELAY,
- IMSG_RECONF_END,
- IMSG_SCRIPT
-};
-
-struct imsg_hdr {
- u_int16_t type;
- u_int16_t len;
- u_int32_t peerid;
- pid_t pid;
-};
-
-struct imsg {
- struct imsg_hdr hdr;
- void *data;
-};
-
-typedef u_int32_t objid_t;
-
-struct ctl_status {
- objid_t id;
- int up;
- int retry_cnt;
- u_long check_cnt;
-};
-
-struct ctl_id {
- objid_t id;
- char name[MAX_NAME_SIZE];
-};
-
-struct ctl_script {
- objid_t host;
- int retval;
-};
-
-struct ctl_demote {
- char group[IFNAMSIZ];
- int level;
-};
-
-struct ctl_icmp_event {
- struct hoststated *env;
- int s;
- int af;
- int last_up;
- struct event ev;
- struct timeval tv_start;
-};
-
-struct ctl_tcp_event {
- int s;
- char *req;
- struct buf *buf;
- struct host *host;
- struct table *table;
- struct timeval tv_start;
- struct event ev;
- int (*validate_read)(struct ctl_tcp_event *);
- int (*validate_close)(struct ctl_tcp_event *);
- SSL *ssl;
- char rbuf[SMALL_READ_BUF_SIZE];
-};
-
-enum httpmethod {
- HTTP_METHOD_GET = 0,
- HTTP_METHOD_HEAD = 1,
- HTTP_METHOD_POST = 2,
- HTTP_METHOD_PUT = 3,
- HTTP_METHOD_DELETE = 4,
- HTTP_METHOD_OPTIONS = 5,
- HTTP_METHOD_TRACE = 6,
- HTTP_METHOD_CONNECT = 7,
- HTTP_METHOD_RESPONSE = 8 /* Server response */
-};
-
-enum direction {
- RELAY_DIR_REQUEST = 0,
- RELAY_DIR_RESPONSE = 1
-};
-
-struct ctl_relay_event {
- int s;
- in_port_t port;
- struct sockaddr_storage ss;
- struct bufferevent *bev;
- struct evbuffer *output;
- struct ctl_relay_event *dst;
- void *con;
- SSL *ssl;
- u_int8_t *nodes;
- struct proto_tree *tree;
-
- char *path;
- char *args;
- char *version;
-
- int line;
- size_t toread;
- int chunked;
- int done;
- enum httpmethod method;
- enum direction dir;
-
- u_int8_t *buf;
- int buflen;
-};
-
-struct ctl_natlook {
- objid_t id;
- int proc;
-
- struct sockaddr_storage src;
- struct sockaddr_storage dst;
- struct sockaddr_storage rsrc;
- struct sockaddr_storage rdst;
- in_port_t rsport;
- in_port_t rdport;
- int in;
-};
-
-struct ctl_stats {
- objid_t id;
- int proc;
-
- u_int interval;
- u_long cnt;
- u_long tick;
- u_long avg;
- u_long last;
- u_long avg_hour;
- u_long last_hour;
- u_long avg_day;
- u_long last_day;
-};
-
-struct address {
- struct sockaddr_storage ss;
- in_port_t port;
- char ifname[IFNAMSIZ];
- TAILQ_ENTRY(address) entry;
-};
-TAILQ_HEAD(addresslist, address);
-
-#define F_DISABLE 0x00000001
-#define F_BACKUP 0x00000002
-#define F_USED 0x00000004
-#define F_DOWN 0x00000008
-#define F_ADD 0x00000010
-#define F_DEL 0x00000020
-#define F_CHANGED 0x00000040
-#define F_STICKY 0x00000080
-#define F_CHECK_DONE 0x00000100
-#define F_ACTIVE_RULESET 0x00000200
-#define F_CHECK_SENT 0x00000400
-#define F_SSL 0x00000800
-#define F_NATLOOK 0x00001000
-#define F_DEMOTE 0x00002000
-#define F_LOOKUP_PATH 0x00004000
-#define F_DEMOTED 0x00008000
-#define F_UDP 0x00010000
-#define F_RETURN 0x00020000
-
-struct host_config {
- objid_t id;
- objid_t tableid;
- int retry;
- char name[MAXHOSTNAMELEN];
- struct sockaddr_storage ss;
-};
-
-struct host {
- TAILQ_ENTRY(host) entry;
- struct host_config conf;
- u_int32_t flags;
- char *tablename;
- int up;
- int last_up;
- u_long check_cnt;
- u_long up_cnt;
- int retry_cnt;
- int idx;
- struct ctl_tcp_event cte;
-};
-TAILQ_HEAD(hostlist, host);
-
-enum host_status {
- HOST_DOWN = -1,
- HOST_UNKNOWN = 0,
- HOST_UP = 1
-};
-#define HOST_ISUP(x) (x == HOST_UP)
-
-enum digest_type {
- DIGEST_NONE = 0,
- DIGEST_SHA1 = 1,
- DIGEST_MD5 = 2
-};
-
-struct table_config {
- objid_t id;
- objid_t serviceid;
- u_int32_t flags;
- int check;
- char demote_group[IFNAMSIZ];
- struct timeval timeout;
- in_port_t port;
- int retcode;
- int skip_cnt;
- char name[TABLE_NAME_SIZE];
- char path[MAXPATHLEN];
- char exbuf[64];
- char digest[41]; /* length of sha1 digest * 2 */
- u_int8_t digest_type;
-};
-
-struct table {
- TAILQ_ENTRY(table) entry;
- struct table_config conf;
- int up;
- int skipped;
- struct hostlist hosts;
- SSL_CTX *ssl_ctx;
- int sendbuf_len;
- char *sendbuf;
-};
-TAILQ_HEAD(tablelist, table);
-
-enum table_check {
- CHECK_NOCHECK = 0,
- CHECK_ICMP = 1,
- CHECK_TCP = 2,
- CHECK_HTTP_CODE = 3,
- CHECK_HTTP_DIGEST = 4,
- CHECK_SEND_EXPECT = 5,
- CHECK_SCRIPT = 6
-};
-
-struct service_config {
- objid_t id;
- u_int32_t flags;
- in_port_t port;
- objid_t table_id;
- objid_t backup_id;
- char name[SRV_NAME_SIZE];
- char tag[TAG_NAME_SIZE];
-};
-
-struct service {
- TAILQ_ENTRY(service) entry;
- struct service_config conf;
- struct addresslist virts;
- struct table *table;
- struct table *backup; /* use this if no host up */
-};
-TAILQ_HEAD(servicelist, service);
-
-struct session {
- objid_t id;
- u_int32_t key;
- objid_t relayid;
- struct ctl_relay_event in;
- struct ctl_relay_event out;
- u_int32_t outkey;
- struct event ev;
- struct timeval timeout;
- struct timeval tv_start;
- struct timeval tv_last;
- int done;
- int retry;
- u_int16_t mark;
- struct evbuffer *log;
- void *relay;
- struct ctl_natlook *cnl;
-
- SPLAY_ENTRY(session) nodes;
-};
-SPLAY_HEAD(session_tree, session);
-
-enum nodeaction {
- NODE_ACTION_NONE = 0,
- NODE_ACTION_APPEND = 1,
- NODE_ACTION_CHANGE = 2,
- NODE_ACTION_REMOVE = 3,
- NODE_ACTION_EXPECT = 4,
- NODE_ACTION_FILTER = 5,
- NODE_ACTION_HASH = 6,
- NODE_ACTION_LOG = 7,
- NODE_ACTION_MARK = 8
-};
-
-enum nodetype {
- NODE_TYPE_HEADER = 0,
- NODE_TYPE_QUERY = 1,
- NODE_TYPE_COOKIE = 2,
- NODE_TYPE_PATH = 3,
- NODE_TYPE_URL = 4
-};
-
-#define PNFLAG_MACRO 0x01
-#define PNFLAG_MARK 0x02
-#define PNFLAG_LOG 0x04
-#define PNFLAG_LOOKUP_QUERY 0x08
-#define PNFLAG_LOOKUP_COOKIE 0x10
-#define PNFLAG_LOOKUP_URL 0xe0
-#define PNFLAG_LOOKUP_URL_DIGEST 0xc0
-#define PNFLAG_LOOKUP_DIGEST(x) (0x20 << x)
-
-enum noderesult {
- PN_DROP = 0,
- PN_PASS = 1,
- PN_FAIL = -1
-};
-
-struct protonode {
- objid_t id;
- char *key;
- enum nodeaction action;
- char *value;
- u_int8_t flags;
- enum nodetype type;
- u_int16_t mark;
- u_int16_t label;
-
- SIMPLEQ_HEAD(, protonode) head;
- SIMPLEQ_ENTRY(protonode) entry;
-
- RB_ENTRY(protonode) nodes;
-};
-RB_HEAD(proto_tree, protonode);
-
-#define PROTONODE_FOREACH(elm, root, field) \
- for (elm = root; elm != NULL; elm = SIMPLEQ_NEXT(elm, entry)) \
-
-enum prototype {
- RELAY_PROTO_TCP = 0,
- RELAY_PROTO_HTTP = 1,
- RELAY_PROTO_DNS = 2
-};
-
-#define TCPFLAG_NODELAY 0x01
-#define TCPFLAG_NNODELAY 0x02
-#define TCPFLAG_SACK 0x04
-#define TCPFLAG_NSACK 0x08
-#define TCPFLAG_BUFSIZ 0x10
-#define TCPFLAG_IPTTL 0x20
-#define TCPFLAG_IPMINTTL 0x40
-#define TCPFLAG_DEFAULT 0x00
-
-#define SSLFLAG_SSLV2 0x01
-#define SSLFLAG_SSLV3 0x02
-#define SSLFLAG_TLSV1 0x04
-#define SSLFLAG_VERSION 0x07
-#define SSLFLAG_DEFAULT (SSLFLAG_SSLV3|SSLFLAG_TLSV1)
-
-#define SSLCIPHERS_DEFAULT "HIGH:!ADH"
-
-struct relay;
-struct protocol {
- objid_t id;
- u_int32_t flags;
- u_int8_t tcpflags;
- int tcpbufsiz;
- int tcpbacklog;
- u_int8_t tcpipttl;
- u_int8_t tcpipminttl;
- u_int8_t sslflags;
- char sslciphers[768];
- char name[MAX_NAME_SIZE];
- int cache;
- enum prototype type;
- int lateconnect;
- char *style;
-
- int request_nodes;
- struct proto_tree request_tree;
- int response_nodes;
- struct proto_tree response_tree;
-
- int (*cmp)(struct session *, struct session *);
- int (*validate)(struct relay *,
- struct sockaddr_storage *,
- u_int8_t *, size_t, u_int32_t *);
- int (*request)(struct session *);
-
- TAILQ_ENTRY(protocol) entry;
-};
-TAILQ_HEAD(protolist, protocol);
-
-struct relay_config {
- objid_t id;
- u_int32_t flags;
- objid_t proto;
- char name[MAXHOSTNAMELEN];
- in_port_t port;
- in_port_t dstport;
- int dstmode;
- int dstcheck;
- int dstretry;
- objid_t dsttable;
- struct sockaddr_storage ss;
- struct sockaddr_storage dstss;
- struct timeval timeout;
-};
-
-struct relay {
- TAILQ_ENTRY(relay) entry;
- struct relay_config conf;
-
- int up;
- struct protocol *proto;
- int s;
- struct bufferevent *bev;
-
- int dsts;
- struct bufferevent *dstbev;
-
- struct table *dsttable;
- u_int32_t dstkey;
- struct host *dsthost[RELAY_MAXHOSTS];
- int dstnhosts;
-
- struct event ev;
-
- SSL_CTX *ssl_ctx;
- char *ssl_cert;
- off_t ssl_cert_len;
- char *ssl_key;
- off_t ssl_key_len;
-
- struct ctl_stats stats[RELAY_MAXPROC + 1];
-
- struct session_tree sessions;
-};
-TAILQ_HEAD(relaylist, relay);
-
-enum dstmode {
- RELAY_DSTMODE_LOADBALANCE = 0,
- RELAY_DSTMODE_ROUNDROBIN = 1,
- RELAY_DSTMODE_HASH = 2
-};
-#define RELAY_DSTMODE_DEFAULT RELAY_DSTMODE_LOADBALANCE
-
-enum {
- PROC_MAIN,
- PROC_PFE,
- PROC_HCE,
- PROC_RELAY
-} hoststated_process;
-
-struct hoststated {
- u_int8_t opts;
- u_int32_t flags;
- const char *confpath;
- struct pfdata *pf;
- int tablecount;
- int servicecount;
- int protocount;
- int relaycount;
- struct timeval interval;
- struct timeval timeout;
- struct table empty_table;
- struct protocol proto_default;
- struct event ev;
- struct tablelist *tables;
- struct servicelist *services;
- struct protolist *protos;
- struct relaylist *relays;
- u_int16_t prefork_relay;
- char demote_group[IFNAMSIZ];
- u_int16_t id;
-
- struct event statev;
- struct timeval statinterval;
-
- 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
-#define HOSTSTATED_OPT_NOACTION 0x04
-#define HOSTSTATED_OPT_LOGUPDATE 0x08
-#define HOSTSTATED_OPT_LOGNOTIFY 0x10
-#define HOSTSTATED_OPT_LOGALL 0x18
-
-/* initially control.h */
-struct {
- struct event ev;
- int fd;
-} control_state;
-
-enum blockmodes {
- BM_NORMAL,
- BM_NONBLOCK
-};
-
-struct ctl_conn {
- TAILQ_ENTRY(ctl_conn) entry;
- u_int8_t flags;
-#define CTL_CONN_NOTIFY 0x01
- struct imsgbuf ibuf;
-
-};
-TAILQ_HEAD(ctl_connlist, ctl_conn);
-
-/* control.c */
-int control_init(void);
-int control_listen(struct hoststated *, struct imsgbuf *, struct imsgbuf *);
-void control_accept(int, short, void *);
-void control_dispatch_imsg(int, short, void *);
-void control_imsg_forward(struct imsg *);
-void control_cleanup(void);
-
-void session_socket_blockmode(int, enum blockmodes);
-
-extern struct ctl_connlist ctl_conns;
-
-/* parse.y */
-struct hoststated *parse_config(const char *, int);
-int cmdline_symset(char *);
-
-/* log.c */
-void log_init(int);
-void log_warn(const char *, ...);
-void log_warnx(const char *, ...);
-void log_info(const char *, ...);
-void log_debug(const char *, ...);
-__dead void fatal(const char *);
-__dead void fatalx(const char *);
-const char *host_status(enum host_status);
-const char *table_check(enum table_check);
-const char *print_availability(u_long, u_long);
-const char *print_host(struct sockaddr_storage *, char *, size_t);
-const char *print_time(struct timeval *, struct timeval *, char *, size_t);
-const char *print_httperror(u_int);
-
-/* buffer.c */
-struct buf *buf_open(size_t);
-struct buf *buf_dynamic(size_t, size_t);
-int buf_add(struct buf *, void *, size_t);
-void *buf_reserve(struct buf *, size_t);
-int buf_close(struct msgbuf *, struct buf *);
-void buf_free(struct buf *);
-void msgbuf_init(struct msgbuf *);
-void msgbuf_clear(struct msgbuf *);
-int msgbuf_write(struct msgbuf *);
-
-/* imsg.c */
-void imsg_init(struct imsgbuf *, int, void (*)(int, short, void *));
-ssize_t imsg_read(struct imsgbuf *);
-ssize_t imsg_get(struct imsgbuf *, struct imsg *);
-int imsg_compose(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
- int, void *, u_int16_t);
-struct buf *imsg_create(struct imsgbuf *, enum imsg_type, u_int32_t, pid_t,
- u_int16_t);
-int imsg_add(struct buf *, void *, u_int16_t);
-int imsg_close(struct imsgbuf *, struct buf *);
-void imsg_free(struct imsg *);
-void imsg_event_add(struct imsgbuf *); /* needs to be provided externally */
-int imsg_get_fd(struct imsgbuf *);
-
-/* pfe.c */
-pid_t pfe(struct hoststated *, int [2], int [2], int [RELAY_MAXPROC][2],
- int [2], int [RELAY_MAXPROC][2]);
-void show(struct ctl_conn *);
-void show_sessions(struct ctl_conn *);
-int enable_service(struct ctl_conn *, struct ctl_id *);
-int enable_table(struct ctl_conn *, struct ctl_id *);
-int enable_host(struct ctl_conn *, struct ctl_id *);
-int disable_service(struct ctl_conn *, struct ctl_id *);
-int disable_table(struct ctl_conn *, struct ctl_id *);
-int disable_host(struct ctl_conn *, struct ctl_id *);
-
-/* pfe_filter.c */
-void init_filter(struct hoststated *);
-void init_tables(struct hoststated *);
-void flush_table(struct hoststated *, struct service *);
-void sync_table(struct hoststated *, struct service *, struct table *);
-void sync_ruleset(struct hoststated *, struct service *, int);
-void flush_rulesets(struct hoststated *);
-int natlook(struct hoststated *, struct ctl_natlook *);
-
-/* hce.c */
-pid_t hce(struct hoststated *, int [2], int [2], int [RELAY_MAXPROC][2],
- int [2], int [RELAY_MAXPROC][2]);
-void hce_notify_done(struct host *, const char *);
-
-/* relay.c */
-pid_t relay(struct hoststated *, int [2], int [2], int [RELAY_MAXPROC][2],
- int [2], int [RELAY_MAXPROC][2]);
-void relay_notify_done(struct host *, const char *);
-int relay_session_cmp(struct session *, struct session *);
-int relay_load_certfiles(struct relay *);
-
-RB_PROTOTYPE(proto_tree, protonode, nodes, relay_proto_cmp);
-SPLAY_PROTOTYPE(session_tree, session, nodes, relay_session_cmp);
-
-/* relay_udp.c */
-void relay_udp_privinit(struct hoststated *, struct relay *);
-int relay_udp_bind(struct sockaddr_storage *, in_port_t,
- struct protocol *);
-void relay_udp_server(int, short, void *);
-
-/* check_icmp.c */
-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_script.c */
-void check_script(struct host *);
-void script_done(struct hoststated *, struct ctl_script *);
-int script_exec(struct hoststated *, struct ctl_script *);
-
-/* ssl.c */
-void ssl_init(struct hoststated *);
-void ssl_transaction(struct ctl_tcp_event *);
-SSL_CTX *ssl_ctx_create(struct hoststated *);
-void ssl_error(const char *, const char *);
-
-/* ssl_privsep.c */
-int ssl_ctx_use_private_key(SSL_CTX *, char *, off_t);
-int ssl_ctx_use_certificate_chain(SSL_CTX *, char *, off_t);
-
-/* hoststated.c */
-struct host *host_find(struct hoststated *, objid_t);
-struct table *table_find(struct hoststated *, objid_t);
-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 *);
-struct relay *relay_find(struct hoststated *, objid_t);
-struct session *session_find(struct hoststated *, objid_t);
-struct relay *relay_findbyname(struct hoststated *, const char *);
-int expand_string(char *, size_t, const char *, const char *);
-void translate_string(char *);
-void purge_config(struct hoststated *, u_int8_t);
-void merge_config(struct hoststated *, struct hoststated *);
-char *digeststr(enum digest_type, const u_int8_t *, size_t, char *);
-const char *canonicalize_host(const char *, char *, size_t);
-
-/* carp.c */
-int carp_demote_init(char *, int);
-void carp_demote_shutdown(void);
-int carp_demote_get(char *);
-int carp_demote_set(char *, int);
-int carp_demote_reset(char *, int);
-
-/* name2id.c */
-u_int16_t pn_name2id(const char *);
-const char *pn_id2name(u_int16_t);
-void pn_unref(u_int16_t);
-void pn_ref(u_int16_t);
-
diff --git a/usr.sbin/hoststated/imsg.c b/usr.sbin/hoststated/imsg.c
deleted file mode 100644
index bac50e2007a..00000000000
--- a/usr.sbin/hoststated/imsg.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/* $OpenBSD: imsg.c,v 1.9 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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/param.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
-
-#include <net/if.h>
-
-#include <errno.h>
-#include <event.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-void
-imsg_init(struct imsgbuf *ibuf, int fd, void (*handler)(int, short, void *))
-{
- msgbuf_init(&ibuf->w);
- bzero(&ibuf->r, sizeof(ibuf->r));
- ibuf->fd = fd;
- ibuf->w.fd = fd;
- ibuf->pid = getpid();
- ibuf->handler = handler;
- TAILQ_INIT(&ibuf->fds);
-}
-
-ssize_t
-imsg_read(struct imsgbuf *ibuf)
-{
- struct msghdr msg;
- struct cmsghdr *cmsg;
- char cmsgbuf[CMSG_SPACE(sizeof(int) * 16)];
- struct iovec iov;
- ssize_t n;
- int fd;
- struct imsg_fd *ifd;
-
- bzero(&msg, sizeof(msg));
-
- iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
- iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = cmsgbuf;
- msg.msg_controllen = sizeof(cmsgbuf);
-
- if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
- if (errno != EINTR && errno != EAGAIN) {
- log_warn("imsg_read: pipe read error");
- return (-1);
- }
- return (-2);
- }
-
- ibuf->r.wpos += n;
-
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_RIGHTS) {
- fd = (*(int *)CMSG_DATA(cmsg));
- if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
- fatal("imsg_read calloc");
- ifd->fd = fd;
- TAILQ_INSERT_TAIL(&ibuf->fds, ifd, entry);
- } else
- log_warn("imsg_read: got unexpected ctl data level %d "
- "type %d", cmsg->cmsg_level, cmsg->cmsg_type);
- }
-
- return (n);
-}
-
-ssize_t
-imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
-{
- size_t av, left, datalen;
-
- av = ibuf->r.wpos;
-
- if (IMSG_HEADER_SIZE > av)
- return (0);
-
- memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
- if (imsg->hdr.len < IMSG_HEADER_SIZE ||
- imsg->hdr.len > MAX_IMSGSIZE) {
- log_warnx("imsg_get: imsg hdr len %u out of bounds, type=%u",
- imsg->hdr.len, imsg->hdr.type);
- return (-1);
- }
- if (imsg->hdr.len > av)
- return (0);
- datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
- ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
- if ((imsg->data = malloc(datalen)) == NULL) {
- log_warn("imsg_get");
- return (-1);
- }
- memcpy(imsg->data, ibuf->r.rptr, datalen);
-
- if (imsg->hdr.len < av) {
- left = av - imsg->hdr.len;
- memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
- ibuf->r.wpos = left;
- } else
- ibuf->r.wpos = 0;
-
- return (datalen + IMSG_HEADER_SIZE);
-}
-
-int
-imsg_compose(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid,
- pid_t pid, int fd, void *data, u_int16_t datalen)
-{
- struct buf *wbuf;
- int n;
-
- if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
- return (-1);
-
- if (imsg_add(wbuf, data, datalen) == -1)
- return (-1);
-
- wbuf->fd = fd;
-
- if ((n = imsg_close(ibuf, wbuf)) < 0)
- return (-1);
-
- return (n);
-}
-
-/* ARGSUSED */
-struct buf *
-imsg_create(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid,
- pid_t pid, u_int16_t datalen)
-{
- struct buf *wbuf;
- struct imsg_hdr hdr;
-
- datalen += IMSG_HEADER_SIZE;
- if (datalen > MAX_IMSGSIZE) {
- log_warnx("imsg_create: len %u > MAX_IMSGSIZE; "
- "type %u peerid %lu", datalen + IMSG_HEADER_SIZE,
- type, peerid);
- return (NULL);
- }
-
- hdr.type = type;
- hdr.peerid = peerid;
- if ((hdr.pid = pid) == 0)
- hdr.pid = ibuf->pid;
- if ((wbuf = buf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
- log_warn("imsg_create: buf_open");
- return (NULL);
- }
- if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
- return (NULL);
-
- return (wbuf);
-}
-
-int
-imsg_add(struct buf *msg, void *data, u_int16_t datalen)
-{
- if (datalen)
- if (buf_add(msg, data, datalen) == -1) {
- log_warnx("imsg_add: buf_add error");
- buf_free(msg);
- return (-1);
- }
- return (datalen);
-}
-
-int
-imsg_close(struct imsgbuf *ibuf, struct buf *msg)
-{
- int n;
- struct imsg_hdr *hdr;
-
- hdr = (struct imsg_hdr *)msg->buf;
- hdr->len = (u_int16_t)msg->wpos;
- if ((n = buf_close(&ibuf->w, msg)) < 0) {
- log_warnx("imsg_close: buf_close error");
- buf_free(msg);
- return (-1);
- }
- imsg_event_add(ibuf);
-
- return (n);
-}
-
-void
-imsg_free(struct imsg *imsg)
-{
- free(imsg->data);
-}
-
-int
-imsg_get_fd(struct imsgbuf *ibuf)
-{
- int fd;
- struct imsg_fd *ifd;
-
- if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
- return (-1);
-
- fd = ifd->fd;
- TAILQ_REMOVE(&ibuf->fds, ifd, entry);
- free(ifd);
-
- return (fd);
-}
diff --git a/usr.sbin/hoststated/log.c b/usr.sbin/hoststated/log.c
deleted file mode 100644
index b013a1280e1..00000000000
--- a/usr.sbin/hoststated/log.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* $OpenBSD: log.c,v 1.10 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.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 MIND, 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/tree.h>
-
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <event.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-int debug;
-
-void vlog(int, const char *, va_list);
-void logit(int, const char *, ...);
-
-void
-log_init(int n_debug)
-{
- extern char *__progname;
-
- debug = n_debug;
-
- if (!debug)
- openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
-
- tzset();
-}
-
-void
-logit(int pri, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vlog(pri, fmt, ap);
- va_end(ap);
-}
-
-void
-vlog(int pri, const char *fmt, va_list ap)
-{
- char *nfmt;
-
- if (debug) {
- /* best effort in out of mem situations */
- if (asprintf(&nfmt, "%s\n", fmt) == -1) {
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- } else {
- vfprintf(stderr, nfmt, ap);
- free(nfmt);
- }
- fflush(stderr);
- } else
- vsyslog(pri, fmt, ap);
-}
-
-
-void
-log_warn(const char *emsg, ...)
-{
- char *nfmt;
- va_list ap;
-
- /* best effort to even work in out of memory situations */
- if (emsg == NULL)
- logit(LOG_CRIT, "%s", strerror(errno));
- else {
- va_start(ap, emsg);
-
- if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
- /* we tried it... */
- vlog(LOG_CRIT, emsg, ap);
- logit(LOG_CRIT, "%s", strerror(errno));
- } else {
- vlog(LOG_CRIT, nfmt, ap);
- free(nfmt);
- }
- va_end(ap);
- }
-}
-
-void
-log_warnx(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_CRIT, emsg, ap);
- va_end(ap);
-}
-
-void
-log_info(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_INFO, emsg, ap);
- va_end(ap);
-}
-
-void
-log_debug(const char *emsg, ...)
-{
- va_list ap;
-
- if (debug > 1) {
- va_start(ap, emsg);
- vlog(LOG_DEBUG, emsg, ap);
- va_end(ap);
- }
-}
-
-void
-fatal(const char *emsg)
-{
- if (emsg == NULL)
- logit(LOG_CRIT, "fatal: %s", strerror(errno));
- else
- if (errno)
- logit(LOG_CRIT, "fatal: %s: %s",
- emsg, strerror(errno));
- else
- logit(LOG_CRIT, "fatal: %s", emsg);
-
- exit(1);
-}
-
-void
-fatalx(const char *emsg)
-{
- errno = 0;
- fatal(emsg);
-}
-
-const char *
-host_status(enum host_status status)
-{
- switch (status) {
- case HOST_DOWN:
- return ("down");
- case HOST_UNKNOWN:
- return ("unknown");
- case HOST_UP:
- return ("up");
- };
- /* NOTREACHED */
- return ("invalid");
-}
-
-const char *
-table_check(enum table_check check)
-{
- switch (check) {
- case CHECK_NOCHECK:
- return ("none");
- case CHECK_ICMP:
- return ("icmp");
- case CHECK_TCP:
- return ("tcp");
- case CHECK_HTTP_CODE:
- return ("http code");
- case CHECK_HTTP_DIGEST:
- return ("http digest");
- case CHECK_SEND_EXPECT:
- return ("send expect");
- case CHECK_SCRIPT:
- return ("script");
- };
- /* NOTREACHED */
- return ("invalid");
-}
-
-const char *
-print_availability(u_long cnt, u_long up)
-{
- static char buf[BUFSIZ];
-
- if (cnt == 0)
- return ("");
- bzero(buf, sizeof(buf));
- snprintf(buf, sizeof(buf), "%.2f%%", (double)up / cnt * 100);
- return (buf);
-}
-
-const char *
-print_host(struct sockaddr_storage *ss, char *buf, size_t len)
-{
- int af = ss->ss_family;
- void *ptr;
-
- bzero(buf, len);
- if (af == AF_INET)
- ptr = &((struct sockaddr_in *)ss)->sin_addr;
- else
- ptr = &((struct sockaddr_in6 *)ss)->sin6_addr;
- return (inet_ntop(af, ptr, buf, len));
-}
-
-const char *
-print_time(struct timeval *a, struct timeval *b, char *buf, size_t len)
-{
- struct timeval tv;
- u_long h, sec, min;
-
- timerclear(&tv);
- timersub(a, b, &tv);
- sec = tv.tv_sec % 60;
- min = tv.tv_sec / 60 % 60;
- h = tv.tv_sec / 60 / 60;
-
- snprintf(buf, len, "%.2lu:%.2lu:%.2lu", h, min, sec);
- return (buf);
-}
-
-const char *
-print_httperror(u_int code)
-{
- u_int i;
- struct {
- u_int ht_code;
- const char *ht_err;
- } httperr[] = {
- { 100, "Continue" },
- { 101, "Switching Protocols" },
- { 200, "OK" },
- { 201, "Created" },
- { 202, "Accepted" },
- { 203, "Non-Authorative Information" },
- { 204, "No Content" },
- { 205, "Reset Content" },
- { 206, "Partial Content" },
- { 300, "Multiple Choices" },
- { 301, "Moved Permanently" },
- { 302, "Moved Temporarily" },
- { 303, "See Other" },
- { 304, "Not Modified" },
- { 307, "Temporary Redirect" },
- { 400, "Bad Request" },
- { 401, "Unauthorized" },
- { 402, "Payment Required" },
- { 403, "Forbidden" },
- { 404, "Not Found" },
- { 405, "Method Not Allowed" },
- { 406, "Not Acceptable" },
- { 407, "Proxy Authentication Required" },
- { 408, "Request Timeout" },
- { 409, "Conflict" },
- { 410, "Gone" },
- { 411, "Length Required" },
- { 412, "Precondition Failed" },
- { 413, "Request Entity Too Large" },
- { 414, "Request-URL Too Long" },
- { 415, "Unsupported Media Type" },
- { 416, "Requested Range Not Satisfiable" },
- { 417, "Expectation Failed" },
- { 500, "Internal Server Error" },
- { 501, "Not Implemented" },
- { 502, "Bad Gateway" },
- { 503, "Service Unavailable" },
- { 504, "Gateway Timeout" },
- { 505, "HTTP Version Not Supported" },
- { 0 }
- };
-
- for (i = 0; httperr[i].ht_code != 0; i++)
- if (httperr[i].ht_code == code)
- return (httperr[i].ht_err);
- return ("Unknown Error");
-}
diff --git a/usr.sbin/hoststated/name2id.c b/usr.sbin/hoststated/name2id.c
deleted file mode 100644
index 8b9e4a781b9..00000000000
--- a/usr.sbin/hoststated/name2id.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/* $OpenBSD: name2id.c,v 1.1 2007/11/26 09:38:25 reyk Exp $ */
-
-/*
- * Copyright (c) 2004, 2005 Henning Brauer <henning@openbsd.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 MIND, 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/param.h>
-#include <sys/socket.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <event.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-#define IDVAL_MAX 50000
-
-struct n2id_label {
- TAILQ_ENTRY(n2id_label) entry;
- char *name;
- u_int16_t id;
- int ref;
-};
-
-TAILQ_HEAD(n2id_labels, n2id_label);
-
-u_int16_t _name2id(struct n2id_labels *, const char *);
-const char *_id2name(struct n2id_labels *, u_int16_t);
-void _unref(struct n2id_labels *, u_int16_t);
-void _ref(struct n2id_labels *, u_int16_t);
-
-/* for protocolnode labels */
-struct n2id_labels pn_labels = TAILQ_HEAD_INITIALIZER(pn_labels);
-
-u_int16_t
-pn_name2id(const char *name)
-{
- return (_name2id(&pn_labels, name));
-}
-
-const char *
-pn_id2name(u_int16_t id)
-{
- return (_id2name(&pn_labels, id));
-}
-
-void
-pn_unref(u_int16_t id)
-{
- _unref(&pn_labels, id);
-}
-
-void
-pn_ref(u_int16_t id)
-{
- _ref(&pn_labels, id);
-}
-
-u_int16_t
-_name2id(struct n2id_labels *head, const char *name)
-{
- struct n2id_label *label, *p = NULL;
- u_int16_t new_id = 1;
-
- if (!name[0]) {
- errno = EINVAL;
- return (0);
- }
-
- TAILQ_FOREACH(label, head, entry)
- if (strcmp(name, label->name) == 0) {
- label->ref++;
- return (label->id);
- }
-
- /*
- * to avoid fragmentation, we do a linear search from the beginning
- * and take the first free slot we find. if there is none or the list
- * is empty, append a new entry at the end.
- */
-
- if (!TAILQ_EMPTY(head))
- for (p = TAILQ_FIRST(head); p != NULL &&
- p->id == new_id; p = TAILQ_NEXT(p, entry))
- new_id = p->id + 1;
-
- if (new_id > IDVAL_MAX) {
- errno = ERANGE;
- return (0);
- }
-
- if ((label = calloc(1, sizeof(struct n2id_label))) == NULL)
- return (0);
- if ((label->name = strdup(name)) == NULL) {
- free(label);
- return (0);
- }
- label->id = new_id;
- label->ref++;
-
- if (p != NULL) /* insert new entry before p */
- TAILQ_INSERT_BEFORE(p, label, entry);
- else /* either list empty or no free slot in between */
- TAILQ_INSERT_TAIL(head, label, entry);
-
- return (label->id);
-}
-
-const char *
-_id2name(struct n2id_labels *head, u_int16_t id)
-{
- struct n2id_label *label;
-
- if (id == 0)
- return ("");
-
- TAILQ_FOREACH(label, head, entry)
- if (label->id == id)
- return (label->name);
-
- return ("");
-}
-
-void
-_unref(struct n2id_labels *head, u_int16_t id)
-{
- struct n2id_label *p, *next;
-
- if (id == 0)
- return;
-
- for (p = TAILQ_FIRST(head); p != NULL; p = next) {
- next = TAILQ_NEXT(p, entry);
- if (id == p->id) {
- if (--p->ref == 0) {
- TAILQ_REMOVE(head, p, entry);
- free(p->name);
- free(p);
- }
- break;
- }
- }
-}
-
-void
-_ref(struct n2id_labels *head, u_int16_t id)
-{
- struct n2id_label *label;
-
- if (id == 0)
- return;
-
- TAILQ_FOREACH(label, head, entry)
- if (label->id == id) {
- ++label->ref;
- break;
- }
-}
diff --git a/usr.sbin/hoststated/parse.y b/usr.sbin/hoststated/parse.y
deleted file mode 100644
index dc21d748b27..00000000000
--- a/usr.sbin/hoststated/parse.y
+++ /dev/null
@@ -1,2158 +0,0 @@
-/* $OpenBSD: parse.y,v 1.96 2007/11/26 09:38:25 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org>
- * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
- * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
- * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
- * Copyright (c) 2001 Theo de Raadt. All rights reserved.
- *
- * 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/socket.h>
-#include <sys/stat.h>
-#include <sys/queue.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-
-#include <ctype.h>
-#include <unistd.h>
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
-static struct file {
- TAILQ_ENTRY(file) entry;
- FILE *stream;
- char *name;
- int lineno;
- int errors;
-} *file;
-struct file *pushfile(const char *, int);
-int popfile(void);
-int check_file_secrecy(int, const char *);
-int yyparse(void);
-int yylex(void);
-int yyerror(const char *, ...);
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int lgetc(int);
-int lungetc(int);
-int findeol(void);
-
-TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
- TAILQ_ENTRY(sym) entry;
- int used;
- int persist;
- char *nam;
- char *val;
-};
-int symset(const char *, const char *, int);
-char *symget(const char *);
-
-struct hoststated *conf = NULL;
-static int errors = 0;
-objid_t last_service_id = 0;
-objid_t last_table_id = 0;
-objid_t last_host_id = 0;
-objid_t last_relay_id = 0;
-objid_t last_proto_id = 0;
-
-static struct service *service = NULL;
-static struct table *table = NULL;
-static struct relay *rlay = NULL;
-static struct protocol *proto = NULL;
-static struct protonode node;
-static u_int16_t label = 0;
-
-struct address *host_v4(const char *);
-struct address *host_v6(const char *);
-int host_dns(const char *, struct addresslist *,
- int, in_port_t, const char *);
-int host(const char *, struct addresslist *,
- int, in_port_t, const char *);
-
-struct table *table_inherit(const char *, in_port_t);
-
-typedef struct {
- union {
- int64_t number;
- char *string;
- struct host *host;
- struct timeval tv;
- struct {
- enum digest_type type;
- char *digest;
- } digest;
- } v;
- int lineno;
-} YYSTYPE;
-
-%}
-
-%token SERVICE TABLE BACKUP HOST REAL INCLUDE
-%token CHECK TCP ICMP EXTERNAL REQUEST RESPONSE
-%token TIMEOUT CODE DIGEST PORT TAG INTERFACE STYLE RETURN LABEL
-%token VIRTUAL INTERVAL DISABLE STICKYADDR BACKLOG PATH SCRIPT WITH
-%token SEND EXPECT NOTHING SSL LOADBALANCE ROUNDROBIN CIPHERS COOKIE
-%token RELAY LISTEN ON FORWARD TO NAT LOOKUP PREFORK NO MARK MARKED URL
-%token PROTO SESSION CACHE APPEND CHANGE REMOVE FROM FILTER HASH HEADER
-%token LOG UPDATES ALL DEMOTE NODELAY SACK SOCKET BUFFER QUERYSTR RETRY IP
-%token ERROR
-%token <v.string> STRING
-%token <v.number> NUMBER
-%type <v.string> interface hostname
-%type <v.number> port http_type loglevel sslcache optssl dstport mark
-%type <v.number> proto_type dstmode docheck retry log flag direction
-%type <v.host> host
-%type <v.tv> timeout
-%type <v.digest> digest
-
-%%
-
-grammar : /* empty */
- | grammar include '\n'
- | grammar '\n'
- | grammar varset '\n'
- | grammar main '\n'
- | grammar service '\n'
- | grammar table '\n'
- | grammar relay '\n'
- | grammar proto '\n'
- | grammar error '\n' { file->errors++; }
- ;
-
-include : INCLUDE STRING {
- struct file *nfile;
-
- if ((nfile = pushfile($2, 0)) == NULL) {
- yyerror("failed to include file %s", $2);
- free($2);
- YYERROR;
- }
- free($2);
-
- file = nfile;
- lungetc('\n');
- }
-
-optssl : /*empty*/ { $$ = 0; }
- | SSL { $$ = 1; }
- ;
-
-http_type : STRING {
- if (strcmp("https", $1) == 0) {
- $$ = 1;
- } else if (strcmp("http", $1) == 0) {
- $$ = 0;
- } else {
- yyerror("invalid check type: %s", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-
-hostname : /* empty */ {
- $$ = strdup("");
- if ($$ == NULL)
- fatal("calloc");
- }
- | HOST STRING {
- if (asprintf(&$$, "Host: %s\r\n", $2) == -1)
- fatal("asprintf");
- }
- ;
-
-proto_type : TCP { $$ = RELAY_PROTO_TCP; }
- | STRING {
- if (strcmp("http", $1) == 0) {
- $$ = RELAY_PROTO_HTTP;
- } else if (strcmp("dns", $1) == 0) {
- $$ = RELAY_PROTO_DNS;
- } else {
- yyerror("invalid protocol type: %s", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-
-eflags_l : eflags comma eflags_l
- | eflags
- ;
-
-opteflags : /* nothing */
- | eflags
- ;
-
-eflags : STYLE STRING
- {
- if ((proto->style = strdup($2)) == NULL)
- fatal("out of memory");
- free($2);
- }
- ;
-
-port : PORT STRING {
- struct servent *servent;
-
- servent = getservbyname($2, "tcp");
- if (servent == NULL) {
- yyerror("port %s is invalid", $2);
- free($2);
- YYERROR;
- }
- $$ = servent->s_port;
- free($2);
- }
- | PORT NUMBER {
- if ($2 <= 0 || $2 >= (int)USHRT_MAX) {
- yyerror("invalid port: %d", $2);
- YYERROR;
- }
- $$ = htons($2);
- }
- ;
-
-varset : STRING '=' STRING {
- if (symset($1, $3, 0) == -1)
- fatal("cannot store variable");
- free($1);
- free($3);
- }
- ;
-
-sendbuf : NOTHING {
- table->sendbuf = NULL;
- table->sendbuf_len = 0;
- }
- | STRING {
- table->sendbuf = strdup($1);
- if (table->sendbuf == NULL)
- fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
- free($1);
- }
- ;
-
-main : INTERVAL NUMBER {
- if ((conf->interval.tv_sec = $2) < 0) {
- yyerror("invalid interval: %d", $2);
- YYERROR;
- }
- }
- | LOG loglevel { conf->opts |= $2; }
- | TIMEOUT timeout {
- bcopy(&$2, &conf->timeout, sizeof(struct timeval));
- }
- | PREFORK NUMBER {
- if ($2 <= 0 || $2 > RELAY_MAXPROC) {
- yyerror("invalid number of preforked "
- "relays: %d", $2);
- YYERROR;
- }
- conf->prefork_relay = $2;
- }
- | DEMOTE STRING {
- conf->flags |= F_DEMOTE;
- if (strlcpy(conf->demote_group, $2,
- sizeof(conf->demote_group))
- >= sizeof(conf->demote_group)) {
- yyerror("yyparse: demote group name too long");
- free($2);
- YYERROR;
- }
- free($2);
- if (carp_demote_init(conf->demote_group, 1) == -1) {
- yyerror("yyparse: error initializing group %s",
- conf->demote_group);
- YYERROR;
- }
- }
- ;
-
-loglevel : UPDATES { $$ = HOSTSTATED_OPT_LOGUPDATE; }
- | ALL { $$ = HOSTSTATED_OPT_LOGALL; }
- ;
-
-service : SERVICE STRING {
- struct service *srv;
-
- TAILQ_FOREACH(srv, conf->services, entry)
- if (!strcmp(srv->conf.name, $2))
- break;
- if (srv != NULL) {
- yyerror("service %s defined twice", $2);
- free($2);
- YYERROR;
- }
- if ((srv = calloc(1, sizeof (*srv))) == NULL)
- fatal("out of memory");
-
- if (strlcpy(srv->conf.name, $2,
- sizeof(srv->conf.name)) >=
- sizeof(srv->conf.name)) {
- yyerror("service name truncated");
- YYERROR;
- }
- free($2);
- srv->conf.id = last_service_id++;
- if (last_service_id == INT_MAX) {
- yyerror("too many services defined");
- YYERROR;
- }
- service = srv;
- } '{' optnl serviceopts_l '}' {
- if (service->table == NULL) {
- yyerror("service %s has no table",
- service->conf.name);
- YYERROR;
- }
- if (TAILQ_EMPTY(&service->virts)) {
- yyerror("service %s has no virtual ip",
- service->conf.name);
- YYERROR;
- }
- conf->servicecount++;
- if (service->backup == NULL) {
- service->conf.backup_id =
- conf->empty_table.conf.id;
- service->backup = &conf->empty_table;
- } else if (service->backup->conf.port !=
- service->table->conf.port) {
- yyerror("service %s uses two different ports "
- "for its table and backup table",
- service->conf.name);
- YYERROR;
- }
-
- if (!(service->conf.flags & F_DISABLE))
- service->conf.flags |= F_ADD;
- TAILQ_INSERT_HEAD(conf->services, service, entry);
- }
- ;
-
-serviceopts_l : serviceopts_l serviceoptsl nl
- | serviceoptsl optnl
- ;
-
-serviceoptsl : TABLE STRING dstport {
- struct table *tb;
- in_port_t port;
-
- port = $3;
- if (port == 0)
- port = service->conf.port;
- if ((tb = table_inherit($2, port)) == NULL) {
- free($2);
- YYERROR;
- }
- free($2);
-
- service->table = tb;
- service->conf.table_id = tb->conf.id;
- service->table->conf.serviceid = service->conf.id;
- service->table->conf.flags |= F_USED;
- }
- | BACKUP TABLE STRING dstport {
- struct table *tb;
- in_port_t port;
-
- if (service->backup) {
- yyerror("backup already specified");
- free($3);
- YYERROR;
- }
-
- port = $4;
- if (port == 0)
- port = service->conf.port;
- if ((tb = table_inherit($3, port)) == NULL) {
- free($3);
- YYERROR;
- }
- free($3);
-
- service->backup = tb;
- service->conf.backup_id = tb->conf.id;
- service->backup->conf.serviceid = service->conf.id;
- service->backup->conf.flags |= (F_USED|F_BACKUP);
- }
- | VIRTUAL HOST STRING port interface {
- if (host($3, &service->virts,
- SRV_MAX_VIRTS, $4, $5) <= 0) {
- yyerror("invalid virtual ip: %s", $3);
- free($3);
- free($5);
- YYERROR;
- }
- free($3);
- free($5);
- if (service->conf.port == 0)
- service->conf.port = $4;
- }
- | DISABLE { service->conf.flags |= F_DISABLE; }
- | STICKYADDR { service->conf.flags |= F_STICKY; }
- | TAG STRING {
- if (strlcpy(service->conf.tag, $2,
- sizeof(service->conf.tag)) >=
- sizeof(service->conf.tag)) {
- yyerror("service tag name truncated");
- free($2);
- YYERROR;
- }
- free($2);
- }
- | include
- ;
-
-table : TABLE STRING {
- struct table *tb;
-
- TAILQ_FOREACH(tb, conf->tables, entry)
- if (!strcmp(tb->conf.name, $2))
- break;
- if (tb != NULL) {
- yyerror("table %s defined twice", $2);
- free($2);
- YYERROR;
- }
-
- if ((tb = calloc(1, sizeof (*tb))) == NULL)
- fatal("out of memory");
-
- if (strlcpy(tb->conf.name, $2, sizeof(tb->conf.name)) >=
- sizeof(tb->conf.name)) {
- yyerror("table name truncated");
- YYERROR;
- }
- tb->conf.id = last_table_id++;
- bcopy(&conf->timeout, &tb->conf.timeout,
- sizeof(struct timeval));
- if (last_table_id == INT_MAX) {
- yyerror("too many tables defined");
- YYERROR;
- }
- free($2);
- table = tb;
- } '{' optnl tableopts_l '}' {
- if (TAILQ_EMPTY(&table->hosts)) {
- yyerror("table %s has no hosts",
- table->conf.name);
- YYERROR;
- }
- if (table->conf.check == CHECK_NOCHECK) {
- yyerror("table %s has no check",
- table->conf.name);
- YYERROR;
- }
- conf->tablecount++;
- TAILQ_INSERT_HEAD(conf->tables, table, entry);
- }
- ;
-
-tableopts_l : tableopts_l tableoptsl nl
- | tableoptsl optnl
- ;
-
-tableoptsl : host {
- $1->conf.tableid = table->conf.id;
- $1->tablename = table->conf.name;
- TAILQ_INSERT_HEAD(&table->hosts, $1, entry);
- }
- | TIMEOUT timeout {
- bcopy(&$2, &table->conf.timeout,
- sizeof(struct timeval));
- }
- | CHECK ICMP {
- table->conf.check = CHECK_ICMP;
- }
- | CHECK TCP {
- table->conf.check = CHECK_TCP;
- }
- | CHECK SSL {
- table->conf.check = CHECK_TCP;
- conf->flags |= F_SSL;
- table->conf.flags |= F_SSL;
- }
- | CHECK http_type STRING hostname CODE NUMBER {
- if ($2) {
- conf->flags |= F_SSL;
- table->conf.flags |= F_SSL;
- }
- table->conf.check = CHECK_HTTP_CODE;
- if ((table->conf.retcode = $6) <= 0) {
- yyerror("invalid HTTP code: %d", $6);
- free($3);
- free($4);
- YYERROR;
- }
- if (asprintf(&table->sendbuf,
- "HEAD %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
- fatal("asprintf");
- free($3);
- free($4);
- if (table->sendbuf == NULL)
- fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
- }
- | CHECK http_type STRING hostname digest {
- if ($2) {
- conf->flags |= F_SSL;
- table->conf.flags |= F_SSL;
- }
- table->conf.check = CHECK_HTTP_DIGEST;
- if (asprintf(&table->sendbuf,
- "GET %s HTTP/1.0\r\n%s\r\n", $3, $4) == -1)
- fatal("asprintf");
- free($3);
- free($4);
- if (table->sendbuf == NULL)
- fatal("out of memory");
- table->sendbuf_len = strlen(table->sendbuf);
- (void)strlcpy(table->conf.digest, $5.digest,
- sizeof(table->conf.digest));
- table->conf.digest_type = $5.type;
- free($5.digest);
- }
- | CHECK SEND sendbuf EXPECT STRING optssl {
- table->conf.check = CHECK_SEND_EXPECT;
- if ($6) {
- conf->flags |= F_SSL;
- table->conf.flags |= F_SSL;
- }
- if (strlcpy(table->conf.exbuf, $5,
- sizeof(table->conf.exbuf))
- >= sizeof(table->conf.exbuf)) {
- yyerror("yyparse: expect buffer truncated");
- free($5);
- YYERROR;
- }
- translate_string(table->conf.exbuf);
- free($5);
- }
- | CHECK SCRIPT STRING {
- table->conf.check = CHECK_SCRIPT;
- if (strlcpy(table->conf.path, $3,
- sizeof(table->conf.path)) >=
- sizeof(table->conf.path)) {
- yyerror("script path truncated");
- free($3);
- YYERROR;
- }
- free($3);
- }
- | REAL port {
- table->conf.port = $2;
- }
- | DEMOTE STRING {
- table->conf.flags |= F_DEMOTE;
- if (strlcpy(table->conf.demote_group, $2,
- sizeof(table->conf.demote_group))
- >= sizeof(table->conf.demote_group)) {
- yyerror("yyparse: demote group name too long");
- free($2);
- YYERROR;
- }
- free($2);
- if (carp_demote_init(table->conf.demote_group, 1)
- == -1) {
- yyerror("yyparse: error initializing group "
- "'%s'", table->conf.demote_group);
- YYERROR;
- }
- }
- | DISABLE {
- table->conf.flags |= F_DISABLE;
- }
- | INTERVAL NUMBER {
- if ($2 < conf->interval.tv_sec ||
- $2 % conf->interval.tv_sec) {
- yyerror("table interval must be "
- "divisible by global interval");
- YYERROR;
- }
- table->conf.skip_cnt = ($2 / conf->interval.tv_sec) - 1;
- }
- | include
- ;
-
-digest : DIGEST STRING
- {
- switch (strlen($2)) {
- case 40:
- $$.type = DIGEST_SHA1;
- break;
- case 32:
- $$.type = DIGEST_MD5;
- break;
- default:
- yyerror("invalid http digest");
- free($2);
- YYERROR;
- }
- $$.digest = $2;
- }
- ;
-
-proto : PROTO STRING {
- struct protocol *p;
-
- if (strcmp($2, "default") == 0) {
- p = &conf->proto_default;
- } else {
- TAILQ_FOREACH(p, conf->protos, entry)
- if (!strcmp(p->name, $2))
- break;
- }
- if (p != NULL) {
- yyerror("protocol %s defined twice", $2);
- free($2);
- YYERROR;
- }
- if ((p = calloc(1, sizeof (*p))) == NULL)
- fatal("out of memory");
-
- if (strlcpy(p->name, $2, sizeof(p->name)) >=
- sizeof(p->name)) {
- yyerror("protocol name truncated");
- YYERROR;
- }
- free($2);
- p->id = last_proto_id++;
- p->cache = RELAY_CACHESIZE;
- p->type = RELAY_PROTO_TCP;
- p->tcpflags = TCPFLAG_DEFAULT;
- p->sslflags = SSLFLAG_DEFAULT;
- p->tcpbacklog = RELAY_BACKLOG;
- (void)strlcpy(p->sslciphers, SSLCIPHERS_DEFAULT,
- sizeof(p->sslciphers));
- if (last_proto_id == INT_MAX) {
- yyerror("too many protocols defined");
- YYERROR;
- }
- RB_INIT(&p->request_tree);
- RB_INIT(&p->response_tree);
- proto = p;
- } '{' optnl protopts_l '}' {
- conf->protocount++;
-
- if ((proto->sslflags & SSLFLAG_VERSION) == 0) {
- yyerror("invalid SSL protocol");
- YYERROR;
- }
-
- TAILQ_INSERT_HEAD(conf->protos, proto, entry);
- }
- ;
-
-protopts_l : protopts_l protoptsl nl
- | protoptsl optnl
- ;
-
-protoptsl : SSL sslflags
- | SSL '{' sslflags_l '}'
- | TCP tcpflags
- | TCP '{' tcpflags_l '}'
- | PROTO proto_type { proto->type = $2; }
- | RETURN ERROR opteflags { proto->flags |= F_RETURN; }
- | RETURN ERROR '{' eflags_l '}' { proto->flags |= F_RETURN; }
- | LABEL STRING {
- label = pn_name2id($2);
- free($2);
- if (label == 0) {
- yyerror("invalid protocol action label");
- YYERROR;
- }
- }
- | NO LABEL {
- label = 0;
- }
- | direction protonode log {
- struct protonode *pn, *proot, pk;
- struct proto_tree *tree;
-
- if ($1 == RELAY_DIR_RESPONSE)
- tree = &proto->response_tree;
- else
- tree = &proto->request_tree;
- if ((pn = calloc(1, sizeof (*pn))) == NULL)
- fatal("out of memory");
-
- bcopy(&node, pn, sizeof(*pn));
- pn->key = node.key;
- pn->value = node.value;
- pn->type = node.type;
- pn->label = label;
- SIMPLEQ_INIT(&pn->head);
- if ($1 == RELAY_DIR_RESPONSE)
- pn->id = proto->response_nodes++;
- else
- pn->id = proto->request_nodes++;
- if ($3)
- pn->flags |= PNFLAG_LOG;
- if (pn->id == INT_MAX) {
- yyerror("too many protocol nodes defined");
- YYERROR;
- }
- if ((proot =
- RB_INSERT(proto_tree, tree, pn)) != NULL) {
- /*
- * A protocol node with the same key already
- * exists, append it to a queue behind the
- * existing node.
- */
- if (SIMPLEQ_EMPTY(&proot->head))
- SIMPLEQ_NEXT(proot, entry) = pn;
- SIMPLEQ_INSERT_TAIL(&proot->head, pn, entry);
- }
-
- if (node.type == NODE_TYPE_COOKIE)
- pk.key = "Cookie";
- else if (node.type == NODE_TYPE_URL)
- pk.key = "Host";
- else
- pk.key = "GET";
- if (node.type != NODE_TYPE_HEADER) {
- pk.type = NODE_TYPE_HEADER;
- pn = RB_FIND(proto_tree, tree, &pk);
- if (pn == NULL) {
- if ((pn = (struct protonode *)
- calloc(1, sizeof(*pn))) == NULL)
- fatal("out of memory");
- pn->key = strdup(pk.key);
- if (pn->key == NULL)
- fatal("out of memory");
- pn->value = NULL;
- pn->action = NODE_ACTION_NONE;
- pn->type = pk.type;
- SIMPLEQ_INIT(&pn->head);
- if ($1 == RELAY_DIR_RESPONSE)
- pn->id =
- proto->response_nodes++;
- else
- pn->id = proto->request_nodes++;
- if (pn->id == INT_MAX) {
- yyerror("too many protocol "
- "nodes defined");
- YYERROR;
- }
- RB_INSERT(proto_tree, tree, pn);
- }
- switch (node.type) {
- case NODE_TYPE_QUERY:
- pn->flags |= PNFLAG_LOOKUP_QUERY;
- break;
- case NODE_TYPE_COOKIE:
- pn->flags |= PNFLAG_LOOKUP_COOKIE;
- break;
- case NODE_TYPE_URL:
- if (node.flags &
- PNFLAG_LOOKUP_URL_DIGEST)
- pn->flags |= node.flags &
- PNFLAG_LOOKUP_URL_DIGEST;
- else
- pn->flags |=
- PNFLAG_LOOKUP_DIGEST(0);
- break;
- default:
- break;
- }
- }
-
- bzero(&node, sizeof(node));
- }
- | include
- ;
-
-direction : /* empty */ { $$ = RELAY_DIR_REQUEST; }
- | REQUEST { $$ = RELAY_DIR_REQUEST; }
- | RESPONSE { $$ = RELAY_DIR_RESPONSE; }
- ;
-
-tcpflags_l : tcpflags comma tcpflags_l
- | tcpflags
- ;
-
-tcpflags : SACK { proto->tcpflags |= TCPFLAG_SACK; }
- | NO SACK { proto->tcpflags |= TCPFLAG_NSACK; }
- | NODELAY { proto->tcpflags |= TCPFLAG_NODELAY; }
- | NO NODELAY { proto->tcpflags |= TCPFLAG_NNODELAY; }
- | BACKLOG NUMBER {
- if ($2 < 0 || $2 > RELAY_MAX_SESSIONS) {
- yyerror("invalid backlog: %d", $2);
- YYERROR;
- }
- proto->tcpbacklog = $2;
- }
- | SOCKET BUFFER NUMBER {
- proto->tcpflags |= TCPFLAG_BUFSIZ;
- if ((proto->tcpbufsiz = $3) < 0) {
- yyerror("invalid socket buffer size: %d", $3);
- YYERROR;
- }
- }
- | IP STRING NUMBER {
- if ($3 < 0) {
- yyerror("invalid ttl: %d", $3);
- free($2);
- YYERROR;
- }
- if (strcasecmp("ttl", $2) == 0) {
- proto->tcpflags |= TCPFLAG_IPTTL;
- proto->tcpipttl = $3;
- } else if (strcasecmp("minttl", $2) == 0) {
- proto->tcpflags |= TCPFLAG_IPMINTTL;
- proto->tcpipminttl = $3;
- } else {
- yyerror("invalid TCP/IP flag: %s", $2);
- free($2);
- YYERROR;
- }
- free($2);
- }
- ;
-
-sslflags_l : sslflags comma sslflags_l
- | sslflags
- ;
-
-sslflags : SESSION CACHE sslcache { proto->cache = $3; }
- | CIPHERS STRING {
- if (strlcpy(proto->sslciphers, $2,
- sizeof(proto->sslciphers)) >=
- sizeof(proto->sslciphers)) {
- yyerror("sslciphers truncated");
- free($2);
- YYERROR;
- }
- free($2);
- }
- | NO flag { proto->sslflags &= ~($2); }
- | flag { proto->sslflags |= $1; }
- ;
-
-flag : STRING {
- if (strcmp("sslv2", $1) == 0)
- $$ = SSLFLAG_SSLV2;
- else if (strcmp("sslv3", $1) == 0)
- $$ = SSLFLAG_SSLV3;
- else if (strcmp("tlsv1", $1) == 0)
- $$ = SSLFLAG_TLSV1;
- else {
- yyerror("invalid SSL flag: %s", $1);
- free($1);
- YYERROR;
- }
- free($1);
- }
- ;
-
-protonode : nodetype APPEND STRING TO STRING marked {
- node.action = NODE_ACTION_APPEND;
- node.key = strdup($5);
- node.value = strdup($3);
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- if (strchr(node.value, '$') != NULL)
- node.flags |= PNFLAG_MACRO;
- free($5);
- free($3);
- }
- | nodetype CHANGE STRING TO STRING marked {
- node.action = NODE_ACTION_CHANGE;
- node.key = strdup($3);
- node.value = strdup($5);
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- if (strchr(node.value, '$') != NULL)
- node.flags |= PNFLAG_MACRO;
- free($5);
- free($3);
- }
- | nodetype REMOVE STRING marked {
- node.action = NODE_ACTION_REMOVE;
- node.key = strdup($3);
- node.value = NULL;
- if (node.key == NULL)
- fatal("out of memory");
- free($3);
- }
- | nodetype EXPECT STRING FROM STRING marked {
- node.action = NODE_ACTION_EXPECT;
- node.key = strdup($5);
- node.value = strdup($3);
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($5);
- free($3);
- proto->lateconnect++;
- }
- | nodetype EXPECT STRING marked {
- node.action = NODE_ACTION_EXPECT;
- node.key = strdup($3);
- node.value = strdup("*");
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($3);
- proto->lateconnect++;
- }
- | nodetype EXPECT digest marked {
- if (node.type != NODE_TYPE_URL) {
- yyerror("digest not supported for this type");
- free($3.digest);
- YYERROR;
- }
- node.action = NODE_ACTION_EXPECT;
- node.key = strdup($3.digest);
- node.flags |= PNFLAG_LOOKUP_DIGEST($3.type);
- node.value = strdup("*");
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($3.digest);
- proto->lateconnect++;
- }
- | nodetype FILTER STRING FROM STRING marked {
- node.action = NODE_ACTION_FILTER;
- node.key = strdup($5);
- node.value = strdup($3);
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($5);
- free($3);
- proto->lateconnect++;
- }
- | nodetype FILTER STRING marked {
- node.action = NODE_ACTION_FILTER;
- node.key = strdup($3);
- node.value = strdup("*");
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($3);
- proto->lateconnect++;
- }
- | nodetype FILTER digest marked {
- if (node.type != NODE_TYPE_URL) {
- yyerror("digest not supported for this type");
- free($3.digest);
- YYERROR;
- }
- node.action = NODE_ACTION_FILTER;
- node.key = strdup($3.digest);
- node.flags |= PNFLAG_LOOKUP_DIGEST($3.type);
- node.value = strdup("*");
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($3.digest);
- proto->lateconnect++;
- }
- | nodetype HASH STRING marked {
- node.action = NODE_ACTION_HASH;
- node.key = strdup($3);
- node.value = NULL;
- if (node.key == NULL)
- fatal("out of memory");
- free($3);
- proto->lateconnect++;
- }
- | nodetype LOG STRING marked {
- node.action = NODE_ACTION_LOG;
- node.key = strdup($3);
- node.value = NULL;
- node.flags |= PNFLAG_LOG;
- if (node.key == NULL)
- fatal("out of memory");
- free($3);
- }
- | nodetype MARK STRING FROM STRING WITH mark {
- node.action = NODE_ACTION_MARK;
- node.key = strdup($5);
- node.value = strdup($3);
- node.mark = $7;
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($3);
- free($5);
- }
- | nodetype MARK STRING WITH mark {
- node.action = NODE_ACTION_MARK;
- node.key = strdup($3);
- node.value = strdup("*");
- node.mark = $5;
- if (node.key == NULL || node.value == NULL)
- fatal("out of memory");
- free($3);
- }
- ;
-
-marked : /* empty */
- | MARKED mark { node.mark = $2; }
- ;
-
-mark : NUMBER {
- if ($1 <= 0 || $1 >= (int)USHRT_MAX) {
- yyerror("invalid mark: %d", $1);
- YYERROR;
- }
- $$ = $1;
- }
- ;
-
-nodetype : HEADER {
- node.type = NODE_TYPE_HEADER;
- }
- | QUERYSTR { node.type = NODE_TYPE_QUERY; }
- | COOKIE {
- node.type = NODE_TYPE_COOKIE;
- }
- | PATH {
- proto->flags |= F_LOOKUP_PATH;
- node.type = NODE_TYPE_PATH;
- }
- | URL { node.type = NODE_TYPE_URL; }
- ;
-
-sslcache : NUMBER {
- if ($1 < 0) {
- yyerror("invalid sslcache value: %d", $1);
- YYERROR;
- }
- $$ = $1;
- }
- | DISABLE { $$ = -2; }
- ;
-
-relay : RELAY STRING {
- struct relay *r;
-
- TAILQ_FOREACH(r, conf->relays, entry)
- if (!strcmp(r->conf.name, $2))
- break;
- if (r != NULL) {
- yyerror("relay %s defined twice", $2);
- free($2);
- YYERROR;
- }
- if ((r = calloc(1, sizeof (*r))) == NULL)
- fatal("out of memory");
-
- if (strlcpy(r->conf.name, $2, sizeof(r->conf.name)) >=
- sizeof(r->conf.name)) {
- yyerror("relay name truncated");
- YYERROR;
- }
- free($2);
- r->conf.id = last_relay_id++;
- r->conf.timeout.tv_sec = RELAY_TIMEOUT;
- r->proto = NULL;
- r->conf.proto = EMPTY_ID;
- r->conf.dsttable = EMPTY_ID;
- r->conf.dstretry = 0;
- if (last_relay_id == INT_MAX) {
- yyerror("too many relays defined");
- YYERROR;
- }
- rlay = r;
- } '{' optnl relayopts_l '}' {
- if (rlay->conf.ss.ss_family == AF_UNSPEC) {
- yyerror("relay %s has no listener",
- rlay->conf.name);
- YYERROR;
- }
- if ((rlay->conf.flags & F_NATLOOK) == 0 &&
- rlay->conf.dstss.ss_family == AF_UNSPEC &&
- rlay->conf.dsttable == EMPTY_ID) {
- yyerror("relay %s has no target, service, "
- "or table", rlay->conf.name);
- YYERROR;
- }
- if (rlay->conf.proto == EMPTY_ID) {
- rlay->proto = &conf->proto_default;
- rlay->conf.proto = conf->proto_default.id;
- }
- if (relay_load_certfiles(rlay) == -1) {
- yyerror("cannot load certificates for relay %s",
- rlay->conf.name);
- YYERROR;
- }
- conf->relaycount++;
- SPLAY_INIT(&rlay->sessions);
- TAILQ_INSERT_HEAD(conf->relays, rlay, entry);
- }
- ;
-
-relayopts_l : relayopts_l relayoptsl nl
- | relayoptsl optnl
- ;
-
-relayoptsl : LISTEN ON STRING port optssl {
- struct addresslist al;
- struct address *h;
-
- if (rlay->conf.ss.ss_family != AF_UNSPEC) {
- yyerror("relay %s listener already specified",
- rlay->conf.name);
- YYERROR;
- }
-
- TAILQ_INIT(&al);
- if (host($3, &al, 1, $4, NULL) <= 0) {
- yyerror("invalid listen ip: %s", $3);
- free($3);
- YYERROR;
- }
- free($3);
- h = TAILQ_FIRST(&al);
- bcopy(&h->ss, &rlay->conf.ss, sizeof(rlay->conf.ss));
- rlay->conf.port = h->port;
- if ($5) {
- rlay->conf.flags |= F_SSL;
- conf->flags |= F_SSL;
- }
- }
- | FORWARD TO STRING port retry {
- struct addresslist al;
- struct address *h;
-
- if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
- yyerror("relay %s target or service already "
- "specified", rlay->conf.name);
- free($3);
- YYERROR;
- }
-
- TAILQ_INIT(&al);
- if (host($3, &al, 1, $4, NULL) <= 0) {
- yyerror("invalid listen ip: %s", $3);
- free($3);
- YYERROR;
- }
- free($3);
- h = TAILQ_FIRST(&al);
- bcopy(&h->ss, &rlay->conf.dstss,
- sizeof(rlay->conf.dstss));
- rlay->conf.dstport = h->port;
- rlay->conf.dstretry = $5;
- }
- | SERVICE STRING retry {
- struct service *svc;
- struct address *h;
-
- if (rlay->conf.dstss.ss_family != AF_UNSPEC) {
- yyerror("relay %s target or service already "
- "specified", rlay->conf.name);
- free($2);
- YYERROR;
- }
-
- if ((svc = service_findbyname(conf, $2)) == NULL) {
- yyerror("relay %s for unknown service %s",
- rlay->conf.name, $2);
- free($2);
- YYERROR;
- }
- free($2);
- h = TAILQ_FIRST(&svc->virts);
- bcopy(&h->ss, &rlay->conf.dstss,
- sizeof(rlay->conf.dstss));
- rlay->conf.dstport = h->port;
- rlay->conf.dstretry = $3;
- }
- | TABLE STRING dstport dstmode docheck {
- struct table *tb;
-
- rlay->conf.dstport = $3;
- if (rlay->conf.dstport == 0)
- rlay->conf.dstport = rlay->conf.port;
-
- if ((tb = table_inherit($2, rlay->conf.dstport)) ==
- NULL) {
- free($2);
- YYERROR;
- }
- free($2);
- rlay->conf.dsttable = tb->conf.id;
- rlay->dsttable = tb;
- rlay->conf.dstport = tb->conf.port;
- rlay->conf.dstmode = $4;
- rlay->conf.dstcheck = $5;
- rlay->dsttable->conf.flags |= F_USED;
- }
- | PROTO STRING {
- struct protocol *p;
-
- TAILQ_FOREACH(p, conf->protos, entry)
- if (!strcmp(p->name, $2))
- break;
- if (p == NULL) {
- yyerror("no such protocol: %s", $2);
- free($2);
- YYERROR;
- }
- p->flags |= F_USED;
- rlay->conf.proto = p->id;
- rlay->proto = p;
- free($2);
- }
- | NAT LOOKUP retry {
- rlay->conf.flags |= F_NATLOOK;
- rlay->conf.dstretry = $3;
- }
- | TIMEOUT NUMBER {
- if ((rlay->conf.timeout.tv_sec = $2) < 0) {
- yyerror("invalid timeout: %d", $2);
- YYERROR;
- }
- }
- | DISABLE { rlay->conf.flags |= F_DISABLE; }
- | include
- ;
-
-dstmode : /* empty */ { $$ = RELAY_DSTMODE_DEFAULT; }
- | LOADBALANCE { $$ = RELAY_DSTMODE_LOADBALANCE; }
- | ROUNDROBIN { $$ = RELAY_DSTMODE_ROUNDROBIN; }
- | HASH { $$ = RELAY_DSTMODE_HASH; }
- ;
-
-docheck : /* empty */ { $$ = 1; }
- | NO CHECK { $$ = 0; }
- ;
-
-interface : /*empty*/ { $$ = NULL; }
- | INTERFACE STRING { $$ = $2; }
- ;
-
-dstport : /* empty */ { $$ = 0; }
- | port { $$ = $1; }
- ;
-
-host : HOST STRING retry {
- struct address *a;
- struct addresslist al;
-
- if (($$ = calloc(1, sizeof(*($$)))) == NULL)
- fatal("out of memory");
-
- TAILQ_INIT(&al);
- if (host($2, &al, 1, 0, NULL) <= 0) {
- yyerror("invalid host %s", $2);
- free($2);
- free($$);
- YYERROR;
- }
- a = TAILQ_FIRST(&al);
- memcpy(&$$->conf.ss, &a->ss, sizeof($$->conf.ss));
- free(a);
-
- if (strlcpy($$->conf.name, $2, sizeof($$->conf.name)) >=
- sizeof($$->conf.name)) {
- yyerror("host name truncated");
- free($2);
- free($$);
- YYERROR;
- }
- free($2);
- $$->conf.id = last_host_id++;
- $$->conf.retry = $3;
- if (last_host_id == INT_MAX) {
- yyerror("too many hosts defined");
- free($$);
- YYERROR;
- }
- }
- ;
-
-retry : /* nothing */ { $$ = 0; }
- | RETRY NUMBER {
- if (($$ = $2) < 0) {
- yyerror("invalid retry value: %d\n", $2);
- YYERROR;
- }
- }
- ;
-
-timeout : NUMBER
- {
- if ($1 < 0) {
- yyerror("invalid timeout: %d\n", $1);
- YYERROR;
- }
- $$.tv_sec = $1 / 1000;
- $$.tv_usec = ($1 % 1000) * 1000;
- }
- ;
-
-log : /* empty */ { $$ = 0; }
- | LOG { $$ = 1; }
- ;
-
-comma : ','
- | /* empty */
- ;
-
-optnl : '\n' optnl
- |
- ;
-
-nl : '\n' optnl
- ;
-
-%%
-
-struct keywords {
- const char *k_name;
- int k_val;
-};
-
-int
-yyerror(const char *fmt, ...)
-{
- va_list ap;
-
- file->errors++;
- va_start(ap, fmt);
- fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- return (0);
-}
-
-int
-kw_cmp(const void *k, const void *e)
-{
- return (strcmp(k, ((const struct keywords *)e)->k_name));
-}
-
-int
-lookup(char *s)
-{
- /* this has to be sorted always */
- static const struct keywords keywords[] = {
- { "all", ALL },
- { "append", APPEND },
- { "backlog", BACKLOG },
- { "backup", BACKUP },
- { "buffer", BUFFER },
- { "cache", CACHE },
- { "change", CHANGE },
- { "check", CHECK },
- { "ciphers", CIPHERS },
- { "code", CODE },
- { "cookie", COOKIE },
- { "demote", DEMOTE },
- { "digest", DIGEST },
- { "disable", DISABLE },
- { "error", ERROR },
- { "expect", EXPECT },
- { "external", EXTERNAL },
- { "filter", FILTER },
- { "forward", FORWARD },
- { "from", FROM },
- { "hash", HASH },
- { "header", HEADER },
- { "host", HOST },
- { "icmp", ICMP },
- { "include", INCLUDE },
- { "interface", INTERFACE },
- { "interval", INTERVAL },
- { "ip", IP },
- { "label", LABEL },
- { "listen", LISTEN },
- { "loadbalance", LOADBALANCE },
- { "log", LOG },
- { "lookup", LOOKUP },
- { "mark", MARK },
- { "marked", MARKED },
- { "nat", NAT },
- { "no", NO },
- { "nodelay", NODELAY },
- { "nothing", NOTHING },
- { "on", ON },
- { "path", PATH },
- { "port", PORT },
- { "prefork", PREFORK },
- { "protocol", PROTO },
- { "query", QUERYSTR },
- { "real", REAL },
- { "relay", RELAY },
- { "remove", REMOVE },
- { "request", REQUEST },
- { "response", RESPONSE },
- { "retry", RETRY },
- { "return", RETURN },
- { "roundrobin", ROUNDROBIN },
- { "sack", SACK },
- { "script", SCRIPT },
- { "send", SEND },
- { "service", SERVICE },
- { "session", SESSION },
- { "socket", SOCKET },
- { "ssl", SSL },
- { "sticky-address", STICKYADDR },
- { "style", STYLE },
- { "table", TABLE },
- { "tag", TAG },
- { "tcp", TCP },
- { "timeout", TIMEOUT },
- { "to", TO },
- { "updates", UPDATES },
- { "url", URL },
- { "virtual", VIRTUAL },
- { "with", WITH }
- };
- const struct keywords *p;
-
- p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
- sizeof(keywords[0]), kw_cmp);
-
- if (p)
- return (p->k_val);
- else
- return (STRING);
-}
-
-#define MAXPUSHBACK 128
-
-char *parsebuf;
-int parseindex;
-char pushback_buffer[MAXPUSHBACK];
-int pushback_index = 0;
-
-int
-lgetc(int quotec)
-{
- int c, next;
-
- if (parsebuf) {
- /* Read character from the parsebuffer instead of input. */
- if (parseindex >= 0) {
- c = parsebuf[parseindex++];
- if (c != '\0')
- return (c);
- parsebuf = NULL;
- } else
- parseindex++;
- }
-
- if (pushback_index)
- return (pushback_buffer[--pushback_index]);
-
- if (quotec) {
- if ((c = getc(file->stream)) == EOF) {
- yyerror("reached end of file while parsing "
- "quoted string");
- if (popfile() == EOF)
- return (EOF);
- return (quotec);
- }
- return (c);
- }
-
- while ((c = getc(file->stream)) == '\\') {
- next = getc(file->stream);
- if (next != '\n') {
- c = next;
- break;
- }
- yylval.lineno = file->lineno;
- file->lineno++;
- }
-
- while (c == EOF) {
- if (popfile() == EOF)
- return (EOF);
- c = getc(file->stream);
- }
- return (c);
-}
-
-int
-lungetc(int c)
-{
- if (c == EOF)
- return (EOF);
- if (parsebuf) {
- parseindex--;
- if (parseindex >= 0)
- return (c);
- }
- if (pushback_index < MAXPUSHBACK-1)
- return (pushback_buffer[pushback_index++] = c);
- else
- return (EOF);
-}
-
-int
-findeol(void)
-{
- int c;
-
- parsebuf = NULL;
- pushback_index = 0;
-
- /* skip to either EOF or the first real EOL */
- while (1) {
- c = lgetc(0);
- if (c == '\n') {
- file->lineno++;
- break;
- }
- if (c == EOF)
- break;
- }
- return (ERROR);
-}
-
-int
-yylex(void)
-{
- char buf[8096];
- char *p, *val;
- int quotec, next, c;
- int token;
-
-top:
- p = buf;
- while ((c = lgetc(0)) == ' ' || c == '\t')
- ; /* nothing */
-
- yylval.lineno = file->lineno;
- if (c == '#')
- while ((c = lgetc(0)) != '\n' && c != EOF)
- ; /* nothing */
- if (c == '$' && parsebuf == NULL) {
- while (1) {
- if ((c = lgetc(0)) == EOF)
- return (0);
-
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- if (isalnum(c) || c == '_') {
- *p++ = (char)c;
- continue;
- }
- *p = '\0';
- lungetc(c);
- break;
- }
- val = symget(buf);
- if (val == NULL) {
- yyerror("macro '%s' not defined", buf);
- return (findeol());
- }
- parsebuf = val;
- parseindex = 0;
- goto top;
- }
-
- switch (c) {
- case '\'':
- case '"':
- quotec = c;
- while (1) {
- if ((c = lgetc(quotec)) == EOF)
- return (0);
- if (c == '\n') {
- file->lineno++;
- continue;
- } else if (c == '\\') {
- if ((next = lgetc(quotec)) == EOF)
- return (0);
- if (next == quotec || c == ' ' || c == '\t')
- c = next;
- else if (next == '\n')
- continue;
- else
- lungetc(next);
- } else if (c == quotec) {
- *p = '\0';
- break;
- }
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- *p++ = (char)c;
- }
- yylval.v.string = strdup(buf);
- if (yylval.v.string == NULL)
- err(1, "yylex: strdup");
- return (STRING);
- }
-
-#define allowed_to_end_number(x) \
- (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
-
- if (c == '-' || isdigit(c)) {
- do {
- *p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- } while ((c = lgetc(0)) != EOF && isdigit(c));
- lungetc(c);
- if (p == buf + 1 && buf[0] == '-')
- goto nodigits;
- if (c == EOF || allowed_to_end_number(c)) {
- const char *errstr = NULL;
-
- *p = '\0';
- yylval.v.number = strtonum(buf, LLONG_MIN,
- LLONG_MAX, &errstr);
- if (errstr) {
- yyerror("\"%s\" invalid number: %s",
- buf, errstr);
- return (findeol());
- }
- return (NUMBER);
- } else {
-nodigits:
- while (p > buf + 1)
- lungetc(*--p);
- c = *--p;
- if (c == '-')
- return (c);
- }
- }
-
-#define allowed_in_string(x) \
- (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
- x != '{' && x != '}' && \
- x != '!' && x != '=' && x != '#' && \
- x != ','))
-
- if (isalnum(c) || c == ':' || c == '_') {
- do {
- *p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
- lungetc(c);
- *p = '\0';
- if ((token = lookup(buf)) == STRING)
- if ((yylval.v.string = strdup(buf)) == NULL)
- err(1, "yylex: strdup");
- return (token);
- }
- if (c == '\n') {
- yylval.lineno = file->lineno;
- file->lineno++;
- }
- if (c == EOF)
- return (0);
- return (c);
-}
-
-int
-check_file_secrecy(int fd, const char *fname)
-{
- struct stat st;
-
- if (fstat(fd, &st)) {
- log_warn("cannot stat %s", fname);
- return (-1);
- }
- if (st.st_uid != 0 && st.st_uid != getuid()) {
- log_warnx("%s: owner not root or current user", fname);
- return (-1);
- }
- if (st.st_mode & (S_IRWXG | S_IRWXO)) {
- log_warnx("%s: group/world readable/writeable", fname);
- return (-1);
- }
- return (0);
-}
-
-struct file *
-pushfile(const char *name, int secret)
-{
- struct file *nfile;
-
- if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
- (nfile->name = strdup(name)) == NULL) {
- log_warn("malloc");
- return (NULL);
- }
- if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
- log_warn("%s", nfile->name);
- free(nfile->name);
- free(nfile);
- return (NULL);
- } else if (secret &&
- check_file_secrecy(fileno(nfile->stream), nfile->name)) {
- fclose(nfile->stream);
- free(nfile->name);
- free(nfile);
- return (NULL);
- }
- nfile->lineno = 1;
- TAILQ_INSERT_TAIL(&files, nfile, entry);
- return (nfile);
-}
-
-int
-popfile(void)
-{
- struct file *prev;
-
- if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
- prev->errors += file->errors;
- TAILQ_REMOVE(&files, file, entry);
- fclose(file->stream);
- free(file->name);
- free(file);
- file = prev;
- return (0);
- }
- return (EOF);
-}
-
-struct hoststated *
-parse_config(const char *filename, int opts)
-{
- struct sym *sym, *next;
- struct table *nexttb;
- struct host *h;
-
- if ((conf = calloc(1, sizeof(*conf))) == NULL ||
- (conf->tables = calloc(1, sizeof(*conf->tables))) == NULL ||
- (conf->relays = calloc(1, sizeof(*conf->relays))) == NULL ||
- (conf->protos = calloc(1, sizeof(*conf->protos))) == NULL ||
- (conf->services = calloc(1, sizeof(*conf->services))) == NULL) {
- log_warn("cannot allocate memory");
- return (NULL);
- }
-
- errors = 0;
- last_host_id = last_table_id = last_service_id = last_proto_id =
- last_relay_id = 0;
-
- service = NULL;
- table = NULL;
- rlay = NULL;
- proto = NULL;
-
- TAILQ_INIT(conf->services);
- TAILQ_INIT(conf->tables);
- TAILQ_INIT(conf->protos);
- TAILQ_INIT(conf->relays);
-
- memset(&conf->empty_table, 0, sizeof(conf->empty_table));
- conf->empty_table.conf.id = EMPTY_TABLE;
- conf->empty_table.conf.flags |= F_DISABLE;
- (void)strlcpy(conf->empty_table.conf.name, "empty",
- sizeof(conf->empty_table.conf.name));
-
- bzero(&conf->proto_default, sizeof(conf->proto_default));
- conf->proto_default.flags = F_USED;
- conf->proto_default.cache = RELAY_CACHESIZE;
- conf->proto_default.type = RELAY_PROTO_TCP;
- (void)strlcpy(conf->proto_default.name, "default",
- sizeof(conf->proto_default.name));
- RB_INIT(&conf->proto_default.request_tree);
- RB_INIT(&conf->proto_default.response_tree);
-
- conf->timeout.tv_sec = CHECK_TIMEOUT / 1000;
- conf->timeout.tv_usec = (CHECK_TIMEOUT % 1000) * 1000;
- conf->interval.tv_sec = CHECK_INTERVAL;
- conf->interval.tv_usec = 0;
- conf->prefork_relay = RELAY_NUMPROC;
- conf->statinterval.tv_sec = RELAY_STATINTERVAL;
- conf->opts = opts;
- conf->confpath = filename;
-
- if ((file = pushfile(filename, 0)) == NULL) {
- free(conf);
- return (NULL);
- }
- setservent(1);
-
- yyparse();
- errors = file->errors;
- popfile();
-
- endservent();
-
- /* Free macros and check which have not been used. */
- for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
- next = TAILQ_NEXT(sym, entry);
- if ((conf->opts & HOSTSTATED_OPT_VERBOSE) && !sym->used)
- fprintf(stderr, "warning: macro '%s' not "
- "used\n", sym->nam);
- if (!sym->persist) {
- free(sym->nam);
- free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entry);
- free(sym);
- }
- }
-
- if (TAILQ_EMPTY(conf->services) && TAILQ_EMPTY(conf->relays)) {
- log_warnx("no services, nothing to do");
- errors++;
- }
-
- if (TAILQ_EMPTY(conf->relays))
- conf->prefork_relay = 0;
-
- if (timercmp(&conf->timeout, &conf->interval, >=)) {
- log_warnx("global timeout exceeds interval");
- errors++;
- }
-
- /* Verify that every table is used */
- for (table = TAILQ_FIRST(conf->tables); table != NULL;
- table = nexttb) {
- nexttb = TAILQ_NEXT(table, entry);
- if (table->conf.port == 0) {
- TAILQ_REMOVE(conf->tables, table, entry);
- while ((h = TAILQ_FIRST(&table->hosts)) != NULL) {
- TAILQ_REMOVE(&table->hosts, h, entry);
- free(h);
- }
- if (table->sendbuf != NULL)
- free(table->sendbuf);
- free(table);
- continue;
- }
- if (!(table->conf.flags & F_USED)) {
- log_warnx("unused table: %s", table->conf.name);
- errors++;
- }
- if (timercmp(&table->conf.timeout, &conf->interval, >=)) {
- log_warnx("table timeout exceeds interval: %s",
- table->conf.name);
- errors++;
- }
- }
-
- /* Verify that every non-default protocol is used */
- TAILQ_FOREACH(proto, conf->protos, entry) {
- if (!(proto->flags & F_USED)) {
- log_warnx("unused protocol: %s", proto->name);
- }
- }
-
- if (errors) {
- free(conf);
- return (NULL);
- }
-
- return (conf);
-}
-
-int
-symset(const char *nam, const char *val, int persist)
-{
- struct sym *sym;
-
- for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
- sym = TAILQ_NEXT(sym, entry))
- ; /* nothing */
-
- if (sym != NULL) {
- if (sym->persist == 1)
- return (0);
- else {
- free(sym->nam);
- free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entry);
- free(sym);
- }
- }
- if ((sym = calloc(1, sizeof(*sym))) == NULL)
- return (-1);
-
- sym->nam = strdup(nam);
- if (sym->nam == NULL) {
- free(sym);
- return (-1);
- }
- sym->val = strdup(val);
- if (sym->val == NULL) {
- free(sym->nam);
- free(sym);
- return (-1);
- }
- sym->used = 0;
- sym->persist = persist;
- TAILQ_INSERT_TAIL(&symhead, sym, entry);
- return (0);
-}
-
-int
-cmdline_symset(char *s)
-{
- char *sym, *val;
- int ret;
- size_t len;
-
- if ((val = strrchr(s, '=')) == NULL)
- return (-1);
-
- len = strlen(s) - strlen(val) + 1;
- if ((sym = malloc(len)) == NULL)
- errx(1, "cmdline_symset: malloc");
-
- (void)strlcpy(sym, s, len);
-
- ret = symset(sym, val + 1, 1);
- free(sym);
-
- return (ret);
-}
-
-char *
-symget(const char *nam)
-{
- struct sym *sym;
-
- TAILQ_FOREACH(sym, &symhead, entry)
- if (strcmp(nam, sym->nam) == 0) {
- sym->used = 1;
- return (sym->val);
- }
- return (NULL);
-}
-
-struct address *
-host_v4(const char *s)
-{
- struct in_addr ina;
- struct sockaddr_in *sain;
- struct address *h;
-
- bzero(&ina, sizeof(ina));
- if (inet_pton(AF_INET, s, &ina) != 1)
- return (NULL);
-
- if ((h = calloc(1, sizeof(*h))) == NULL)
- fatal(NULL);
- sain = (struct sockaddr_in *)&h->ss;
- sain->sin_len = sizeof(struct sockaddr_in);
- sain->sin_family = AF_INET;
- sain->sin_addr.s_addr = ina.s_addr;
-
- return (h);
-}
-
-struct address *
-host_v6(const char *s)
-{
- struct in6_addr ina6;
- struct sockaddr_in6 *sin6;
- struct address *h;
-
- bzero(&ina6, sizeof(ina6));
- if (inet_pton(AF_INET6, s, &ina6) != 1)
- return (NULL);
-
- if ((h = calloc(1, sizeof(*h))) == NULL)
- fatal(NULL);
- sin6 = (struct sockaddr_in6 *)&h->ss;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_family = AF_INET6;
- memcpy(&sin6->sin6_addr, &ina6, sizeof(ina6));
-
- return (h);
-}
-
-int
-host_dns(const char *s, struct addresslist *al, int max,
- in_port_t port, const char *ifname)
-{
- struct addrinfo hints, *res0, *res;
- int error, cnt = 0;
- struct sockaddr_in *sain;
- struct sockaddr_in6 *sin6;
- struct address *h;
-
- bzero(&hints, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
- error = getaddrinfo(s, NULL, &hints, &res0);
- if (error == EAI_AGAIN || error == EAI_NODATA || error == EAI_NONAME)
- return (0);
- if (error) {
- log_warnx("host_dns: could not parse \"%s\": %s", s,
- gai_strerror(error));
- return (-1);
- }
-
- for (res = res0; res && cnt < max; res = res->ai_next) {
- if (res->ai_family != AF_INET &&
- res->ai_family != AF_INET6)
- continue;
- if ((h = calloc(1, sizeof(*h))) == NULL)
- fatal(NULL);
-
- h->port = port;
- if (ifname != NULL) {
- if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
- sizeof(h->ifname))
- log_warnx("host_dns: interface name truncated");
- return (-1);
- }
- h->ss.ss_family = res->ai_family;
- if (res->ai_family == AF_INET) {
- sain = (struct sockaddr_in *)&h->ss;
- sain->sin_len = sizeof(struct sockaddr_in);
- sain->sin_addr.s_addr = ((struct sockaddr_in *)
- res->ai_addr)->sin_addr.s_addr;
- } else {
- sin6 = (struct sockaddr_in6 *)&h->ss;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- memcpy(&sin6->sin6_addr, &((struct sockaddr_in6 *)
- res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
- }
-
- TAILQ_INSERT_HEAD(al, h, entry);
- cnt++;
- }
- if (cnt == max && res) {
- log_warnx("host_dns: %s resolves to more than %d hosts",
- s, max);
- }
- freeaddrinfo(res0);
- return (cnt);
-}
-
-int
-host(const char *s, struct addresslist *al, int max,
- in_port_t port, const char *ifname)
-{
- struct address *h;
-
- h = host_v4(s);
-
- /* IPv6 address? */
- if (h == NULL)
- h = host_v6(s);
-
- if (h != NULL) {
- h->port = port;
- if (ifname != NULL) {
- if (strlcpy(h->ifname, ifname, sizeof(h->ifname)) >=
- sizeof(h->ifname)) {
- log_warnx("host: interface name truncated");
- return (-1);
- }
- }
-
- TAILQ_INSERT_HEAD(al, h, entry);
- return (1);
- }
-
- return (host_dns(s, al, max, port, ifname));
-}
-
-struct table *
-table_inherit(const char *name, in_port_t port)
-{
- char pname[TABLE_NAME_SIZE + 6];
- struct host *h, *dsth;
- struct table *dsttb, *tb;
-
- /* Get the table or table template */
- if ((dsttb = table_findbyname(conf, name)) == NULL) {
- yyerror("unknown table or template %s", name);
- return (NULL);
- }
- if (dsttb->conf.port != 0)
- return (dsttb);
-
- if (port == 0) {
- yyerror("invalid port");
- return (NULL);
- }
-
- /* Check if a matching table already exists */
- snprintf(pname, sizeof(pname), "%s:%u", name, ntohs(port));
- if ((tb = table_findbyname(conf, pname)) != NULL) {
- if (tb->conf.port == 0) {
- yyerror("invalid table");
- return (NULL);
- }
- return (tb);
- }
-
- /* Create a new table */
- if ((tb = calloc(1, sizeof (*tb))) == NULL)
- fatal("out of memory");
- bcopy(dsttb, tb, sizeof(*tb));
- if (strlcpy(tb->conf.name, pname, sizeof(tb->conf.name))
- >= sizeof(tb->conf.name)) {
- yyerror("table name truncated");
- return (NULL);
- }
- if (dsttb->sendbuf != NULL &&
- (tb->sendbuf = strdup(dsttb->sendbuf)) == NULL)
- fatal("out of memory");
- tb->conf.port = port;
- tb->conf.id = last_table_id++;
- if (last_table_id == INT_MAX) {
- yyerror("too many tables defined");
- return (NULL);
- }
-
- /* Copy the associated hosts */
- bzero(&tb->hosts, sizeof(tb->hosts));
- TAILQ_FOREACH(dsth, &dsttb->hosts, entry) {
- if ((h = (struct host *)
- calloc(1, sizeof (*h))) == NULL)
- fatal("out of memory");
- bcopy(dsth, h, sizeof(*h));
- h->conf.id = last_host_id++;
- if (last_host_id == INT_MAX) {
- yyerror("too many hosts defined");
- return (NULL);
- }
- h->conf.tableid = tb->conf.id;
- h->tablename = tb->conf.name;
- TAILQ_INSERT_HEAD(&tb->hosts, h, entry);
- }
-
- conf->tablecount++;
- TAILQ_INSERT_HEAD(conf->tables, tb, entry);
-
- return (tb);
-}
diff --git a/usr.sbin/hoststated/pfe.c b/usr.sbin/hoststated/pfe.c
deleted file mode 100644
index 32f8c84df18..00000000000
--- a/usr.sbin/hoststated/pfe.c
+++ /dev/null
@@ -1,910 +0,0 @@
-/* $OpenBSD: pfe.c,v 1.43 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <net/if.h>
-
-#include <errno.h>
-#include <event.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <pwd.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-void pfe_sig_handler(int sig, short, void *);
-void pfe_shutdown(void);
-void pfe_setup_events(void);
-void pfe_disable_events(void);
-void pfe_dispatch_imsg(int, short, void *);
-void pfe_dispatch_parent(int, short, void *);
-void pfe_dispatch_relay(int, short, void *);
-
-void pfe_sync(void);
-
-static struct hoststated *env = NULL;
-
-struct imsgbuf *ibuf_main;
-struct imsgbuf *ibuf_hce;
-struct imsgbuf *ibuf_relay;
-
-void
-pfe_sig_handler(int sig, short event, void *arg)
-{
- switch (sig) {
- case SIGINT:
- case SIGTERM:
- pfe_shutdown();
- default:
- fatalx("pfe_sig_handler: unexpected signal");
- }
-}
-
-pid_t
-pfe(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
- int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
- int pipe_pfe2relay[RELAY_MAXPROC][2])
-{
- pid_t pid;
- struct passwd *pw;
- struct event ev_sigint;
- struct event ev_sigterm;
- int i;
- size_t size;
-
- switch (pid = fork()) {
- case -1:
- fatal("pfe: cannot fork");
- case 0:
- break;
- default:
- return (pid);
- }
-
- env = x_env;
- purge_config(env, PURGE_PROTOS);
-
- if (control_init() == -1)
- fatalx("pfe: control socket setup failed");
-
- init_filter(env);
- init_tables(env);
-
- if ((pw = getpwnam(HOSTSTATED_USER)) == NULL)
- fatal("pfe: getpwnam");
-
-#ifndef DEBUG
- if (chroot(pw->pw_dir) == -1)
- fatal("pfe: chroot");
- if (chdir("/") == -1)
- fatal("pfe: chdir(\"/\")");
-#else
-#warning disabling privilege revocation and chroot in DEBUG mode
-#endif
-
- setproctitle("pf update engine");
- hoststated_process = PROC_PFE;
-
-#ifndef DEBUG
- 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("pfe: cannot drop privileges");
-#endif
-
- event_init();
-
- signal_set(&ev_sigint, SIGINT, pfe_sig_handler, NULL);
- signal_set(&ev_sigterm, SIGTERM, pfe_sig_handler, NULL);
- signal_add(&ev_sigint, NULL);
- signal_add(&ev_sigterm, NULL);
- signal(SIGPIPE, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
-
- /* setup pipes */
- close(pipe_pfe2hce[0]);
- close(pipe_parent2pfe[0]);
- close(pipe_parent2hce[0]);
- close(pipe_parent2hce[1]);
- for (i = 0; i < env->prefork_relay; i++) {
- close(pipe_parent2relay[i][0]);
- close(pipe_parent2relay[i][1]);
- close(pipe_pfe2relay[i][0]);
- }
-
- size = sizeof(struct imsgbuf);
- if ((ibuf_hce = calloc(1, size)) == NULL ||
- (ibuf_relay = calloc(env->prefork_relay, size)) == NULL ||
- (ibuf_main = calloc(1, size)) == NULL)
- fatal("pfe");
-
- imsg_init(ibuf_hce, pipe_pfe2hce[1], pfe_dispatch_imsg);
- imsg_init(ibuf_main, pipe_parent2pfe[1], pfe_dispatch_parent);
- for (i = 0; i < env->prefork_relay; i++)
- imsg_init(&ibuf_relay[i], pipe_pfe2relay[i][1],
- pfe_dispatch_relay);
-
- ibuf_main->events = EV_READ;
- event_set(&ibuf_main->ev, ibuf_main->fd, ibuf_main->events,
- ibuf_main->handler, ibuf_main);
- event_add(&ibuf_main->ev, NULL);
-
- pfe_setup_events();
-
- TAILQ_INIT(&ctl_conns);
-
- if (control_listen(env, ibuf_main, ibuf_hce) == -1)
- fatalx("pfe: control socket listen failed");
-
- /* Initial sync */
- pfe_sync();
-
- event_dispatch();
- pfe_shutdown();
-
- return (0);
-}
-
-void
-pfe_shutdown(void)
-{
- flush_rulesets(env);
- log_info("pf update engine exiting");
- _exit(0);
-}
-
-void
-pfe_setup_events(void)
-{
- int i;
- struct imsgbuf *ibuf;
-
- ibuf_hce->events = EV_READ;
- event_set(&ibuf_hce->ev, ibuf_hce->fd, ibuf_hce->events,
- ibuf_hce->handler, ibuf_hce);
- event_add(&ibuf_hce->ev, NULL);
-
- for (i = 0; i < env->prefork_relay; i++) {
- ibuf = &ibuf_relay[i];
-
- ibuf->events = EV_READ;
- event_set(&ibuf->ev, ibuf->fd, ibuf->events,
- ibuf->handler, ibuf);
- event_add(&ibuf->ev, NULL);
- }
-}
-
-void
-pfe_disable_events(void)
-{
- int i;
-
- event_del(&ibuf_hce->ev);
-
- for (i = 0; i < env->prefork_relay; i++)
- event_del(&ibuf_relay[i].ev);
-}
-
-void
-pfe_dispatch_imsg(int fd, short event, void *ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
-
- struct host *host;
- struct table *table;
- struct ctl_status st;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("pfe_dispatch_imsg: imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("pfe_dispatch_imsg: msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("pfe_dispatch_imsg: unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("pfe_dispatch_imsg: imsg_read error");
- if (n == 0)
- break;
-
- control_imsg_forward(&imsg);
- switch (imsg.hdr.type) {
- case IMSG_HOST_STATUS:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(st))
- fatalx("pfe_dispatch_imsg: invalid request");
- memcpy(&st, imsg.data, sizeof(st));
- if ((host = host_find(env, st.id)) == NULL)
- fatalx("pfe_dispatch_imsg: invalid host id");
- if (host->flags & F_DISABLE)
- break;
- host->retry_cnt = st.retry_cnt;
- if (st.up != HOST_UNKNOWN) {
- host->check_cnt++;
- if (st.up == HOST_UP)
- host->up_cnt++;
- }
- if (host->check_cnt != st.check_cnt) {
- log_debug("pfe_dispatch_imsg: host %d => %d",
- host->conf.id, host->up);
- fatalx("pfe_dispatch_imsg: desynchronized");
- }
-
- if (host->up == st.up)
- break;
-
- /* Forward to relay engine(s) */
- for (n = 0; n < env->prefork_relay; n++)
- imsg_compose(&ibuf_relay[n],
- IMSG_HOST_STATUS, 0, 0, -1, &st,
- sizeof(st));
-
- if ((table = table_find(env, host->conf.tableid))
- == NULL)
- fatalx("pfe_dispatch_imsg: invalid table id");
-
- log_debug("pfe_dispatch_imsg: state %d for host %u %s",
- st.up, host->conf.id, host->conf.name);
-
- /*
- * Do not change the table state when the host
- * state switches between UNKNOWN and DOWN.
- */
- if (HOST_ISUP(st.up)) {
- table->conf.flags |= F_CHANGED;
- table->up++;
- host->flags |= F_ADD;
- host->flags &= ~(F_DEL);
- } else if (HOST_ISUP(host->up)) {
- table->up--;
- table->conf.flags |= F_CHANGED;
- host->flags |= F_DEL;
- host->flags &= ~(F_ADD);
- }
-
- host->up = st.up;
- break;
- case IMSG_SYNC:
- pfe_sync();
- break;
- default:
- log_debug("pfe_dispatch_imsg: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-pfe_dispatch_parent(int fd, short event, void * ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
-
- static struct service *service = NULL;
- static struct table *table = NULL;
- struct host *host;
- struct address *virt;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("pfe_dispatch_parent: unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("pfe_dispatch_parent: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_RECONF:
- log_debug("pfe: reloading configuration");
- if (imsg.hdr.len !=
- sizeof(struct hoststated) + IMSG_HEADER_SIZE)
- fatalx("corrupted reload data");
- pfe_disable_events();
- purge_config(env, PURGE_SERVICES|PURGE_TABLES);
- merge_config(env, (struct hoststated *)imsg.data);
- /*
- * no relays when reconfiguring yet.
- */
- env->relays = NULL;
- env->protos = NULL;
-
- env->tables = calloc(1, sizeof(*env->tables));
- env->services = calloc(1, sizeof(*env->services));
- if (env->tables == NULL || env->services == NULL)
- fatal(NULL);
-
- TAILQ_INIT(env->tables);
- TAILQ_INIT(env->services);
- break;
- case IMSG_RECONF_TABLE:
- if ((table = calloc(1, sizeof(*table))) == NULL)
- fatal(NULL);
- memcpy(&table->conf, imsg.data, sizeof(table->conf));
- TAILQ_INIT(&table->hosts);
- TAILQ_INSERT_TAIL(env->tables, table, entry);
- break;
- case IMSG_RECONF_HOST:
- if ((host = calloc(1, sizeof(*host))) == NULL)
- fatal(NULL);
- memcpy(&host->conf, imsg.data, sizeof(host->conf));
- host->tablename = table->conf.name;
- TAILQ_INSERT_TAIL(&table->hosts, host, entry);
- break;
- case IMSG_RECONF_SERVICE:
- if ((service = calloc(1, sizeof(*service))) == NULL)
- fatal(NULL);
- memcpy(&service->conf, imsg.data,
- sizeof(service->conf));
- service->table = table_find(env,
- service->conf.table_id);
- if (service->conf.backup_id == EMPTY_TABLE)
- service->backup = &env->empty_table;
- else
- service->backup = table_find(env,
- service->conf.backup_id);
- if (service->table == NULL || service->backup == NULL)
- fatal("pfe_dispatch_parent:"
- " corrupted configuration");
- log_debug("pfe_dispatch_parent: service->table: %s",
- service->table->conf.name);
- log_debug("pfe_dispatch_parent: service->backup: %s",
- service->backup->conf.name);
- TAILQ_INIT(&service->virts);
- TAILQ_INSERT_TAIL(env->services, service, entry);
- break;
- case IMSG_RECONF_VIRT:
- if ((virt = calloc(1, sizeof(*virt))) == NULL)
- fatal(NULL);
- memcpy(virt, imsg.data, sizeof(*virt));
- TAILQ_INSERT_TAIL(&service->virts, virt, entry);
- break;
- case IMSG_RECONF_END:
- log_warnx("pfe: configuration reloaded");
- pfe_setup_events();
- pfe_sync();
- break;
- default:
- log_debug("pfe_dispatch_parent: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-pfe_dispatch_relay(int fd, short event, void * ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
- struct ctl_natlook cnl;
- struct ctl_stats crs;
- struct relay *rlay;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("pfe_dispatch_relay: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_NATLOOK:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(cnl))
- fatalx("invalid imsg header len");
- bcopy(imsg.data, &cnl, sizeof(cnl));
- if (cnl.proc > env->prefork_relay)
- fatalx("pfe_dispatch_relay: "
- "invalid relay proc");
- if (natlook(env, &cnl) != 0)
- cnl.in = -1;
- imsg_compose(&ibuf_relay[cnl.proc], IMSG_NATLOOK, 0, 0,
- -1, &cnl, sizeof(cnl));
- break;
- case IMSG_STATISTICS:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(crs))
- fatalx("invalid imsg header len");
- bcopy(imsg.data, &crs, sizeof(crs));
- if (crs.proc > env->prefork_relay)
- fatalx("pfe_dispatch_relay: "
- "invalid relay proc");
- if ((rlay = relay_find(env, crs.id)) == NULL)
- fatalx("pfe_dispatch_relay: invalid relay id");
- bcopy(&crs, &rlay->stats[crs.proc], sizeof(crs));
- rlay->stats[crs.proc].interval =
- env->statinterval.tv_sec;
- break;
- default:
- log_debug("pfe_dispatch_relay: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-show(struct ctl_conn *c)
-{
- struct service *service;
- struct host *host;
- struct relay *rlay;
-
- if (env->services == NULL)
- goto relays;
- TAILQ_FOREACH(service, env->services, entry) {
- imsg_compose(&c->ibuf, IMSG_CTL_SERVICE, 0, 0, -1,
- service, sizeof(*service));
- if (service->conf.flags & F_DISABLE)
- continue;
-
- imsg_compose(&c->ibuf, IMSG_CTL_TABLE, 0, 0, -1,
- service->table, sizeof(*service->table));
- if (!(service->table->conf.flags & F_DISABLE))
- TAILQ_FOREACH(host, &service->table->hosts, entry)
- imsg_compose(&c->ibuf, IMSG_CTL_HOST, 0, 0, -1,
- host, sizeof(*host));
-
- if (service->backup->conf.id == EMPTY_TABLE)
- continue;
- imsg_compose(&c->ibuf, IMSG_CTL_TABLE, 0, 0, -1,
- service->backup, sizeof(*service->backup));
- if (!(service->backup->conf.flags & F_DISABLE))
- TAILQ_FOREACH(host, &service->backup->hosts, entry)
- imsg_compose(&c->ibuf, IMSG_CTL_HOST, 0, 0, -1,
- host, sizeof(*host));
- }
-relays:
- if (env->relays == NULL)
- goto end;
- TAILQ_FOREACH(rlay, env->relays, entry) {
- rlay->stats[env->prefork_relay].id = EMPTY_ID;
- imsg_compose(&c->ibuf, IMSG_CTL_RELAY, 0, 0, -1,
- rlay, sizeof(*rlay));
- imsg_compose(&c->ibuf, IMSG_CTL_STATISTICS, 0, 0, -1,
- &rlay->stats, sizeof(rlay->stats));
-
- if (rlay->dsttable == NULL)
- continue;
- imsg_compose(&c->ibuf, IMSG_CTL_TABLE, 0, 0, -1,
- rlay->dsttable, sizeof(*rlay->dsttable));
- if (!(rlay->dsttable->conf.flags & F_DISABLE))
- TAILQ_FOREACH(host, &rlay->dsttable->hosts, entry)
- imsg_compose(&c->ibuf, IMSG_CTL_HOST, 0, 0, -1,
- host, sizeof(*host));
- }
-end:
- imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
-}
-
-void
-show_sessions(struct ctl_conn *c)
-{
- int n, proc, done;
- struct imsg imsg;
-
- for (proc = 0; proc < env->prefork_relay; proc++) {
- /*
- * Request all the running sessions from the process
- */
- imsg_compose(&ibuf_relay[proc],
- IMSG_CTL_SESSION, 0, 0, -1, NULL, 0);
- while (ibuf_relay[proc].w.queued)
- if (msgbuf_write(&ibuf_relay[proc].w) < 0)
- fatalx("write error");
-
- /*
- * Wait for the reply and forward the messages to the
- * control connection.
- */
- done = 0;
- while (!done) {
- do {
- if ((n = imsg_read(&ibuf_relay[proc])) == -1)
- fatalx("imsg_read error");
- } while (n == -2); /* handle non-blocking I/O */
- while (!done) {
- if ((n = imsg_get(&ibuf_relay[proc],
- &imsg)) == -1)
- fatalx("imsg_get error");
- if (n == 0)
- break;
- switch (imsg.hdr.type) {
- case IMSG_CTL_SESSION:
- imsg_compose(&c->ibuf,
- IMSG_CTL_SESSION, proc, 0, -1,
- imsg.data, sizeof(struct session));
- break;
- case IMSG_CTL_END:
- done = 1;
- break;
- default:
- fatalx("wrong message for session");
- break;
- }
- imsg_free(&imsg);
- }
- }
- }
-
- imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
-}
-
-int
-disable_service(struct ctl_conn *c, struct ctl_id *id)
-{
- struct service *service;
-
- if (id->id == EMPTY_ID)
- service = service_findbyname(env, id->name);
- else
- service = service_find(env, id->id);
- if (service == NULL)
- return (-1);
- id->id = service->conf.id;
-
- if (service->conf.flags & F_DISABLE)
- return (0);
-
- service->conf.flags |= F_DISABLE;
- service->conf.flags &= ~(F_ADD);
- service->conf.flags |= F_DEL;
- service->table->conf.flags |= F_DISABLE;
- log_debug("disable_service: disabled service %d", service->conf.id);
- pfe_sync();
- return (0);
-}
-
-int
-enable_service(struct ctl_conn *c, struct ctl_id *id)
-{
- struct service *service;
- struct ctl_id eid;
-
- if (id->id == EMPTY_ID)
- service = service_findbyname(env, id->name);
- else
- service = service_find(env, id->id);
- if (service == NULL)
- return (-1);
- id->id = service->conf.id;
-
- if (!(service->conf.flags & F_DISABLE))
- return (0);
-
- service->conf.flags &= ~(F_DISABLE);
- service->conf.flags &= ~(F_DEL);
- service->conf.flags |= F_ADD;
- log_debug("enable_service: enabled service %d", service->conf.id);
-
- bzero(&eid, sizeof(eid));
-
- /* XXX: we're syncing twice */
- eid.id = service->table->conf.id;
- if (enable_table(c, &eid) == -1)
- return (-1);
- if (service->backup->conf.id == EMPTY_ID)
- return (0);
- eid.id = service->backup->conf.id;
- if (enable_table(c, &eid) == -1)
- return (-1);
- return (0);
-}
-
-int
-disable_table(struct ctl_conn *c, struct ctl_id *id)
-{
- struct table *table;
- struct service *service;
- struct host *host;
-
- if (id->id == EMPTY_ID)
- table = table_findbyname(env, id->name);
- else
- table = table_find(env, id->id);
- if (table == NULL)
- return (-1);
- id->id = table->conf.id;
- if ((service = service_find(env, table->conf.serviceid)) == NULL)
- fatalx("disable_table: desynchronised");
-
- if (table->conf.flags & F_DISABLE)
- return (0);
- table->conf.flags |= (F_DISABLE|F_CHANGED);
- table->up = 0;
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- imsg_compose(ibuf_hce, IMSG_TABLE_DISABLE, 0, 0, -1,
- &table->conf.id, sizeof(table->conf.id));
- log_debug("disable_table: disabled table %d", table->conf.id);
- pfe_sync();
- return (0);
-}
-
-int
-enable_table(struct ctl_conn *c, struct ctl_id *id)
-{
- struct service *service;
- struct table *table;
- struct host *host;
-
- if (id->id == EMPTY_ID)
- table = table_findbyname(env, id->name);
- else
- table = table_find(env, id->id);
- if (table == NULL)
- return (-1);
- id->id = table->conf.id;
-
- if ((service = service_find(env, table->conf.serviceid)) == NULL)
- fatalx("enable_table: desynchronised");
-
- if (!(table->conf.flags & F_DISABLE))
- return (0);
- table->conf.flags &= ~(F_DISABLE);
- table->conf.flags |= F_CHANGED;
- table->up = 0;
- TAILQ_FOREACH(host, &table->hosts, entry)
- host->up = HOST_UNKNOWN;
- imsg_compose(ibuf_hce, IMSG_TABLE_ENABLE, 0, 0, -1,
- &table->conf.id, sizeof(table->conf.id));
- log_debug("enable_table: enabled table %d", table->conf.id);
- pfe_sync();
- return (0);
-}
-
-int
-disable_host(struct ctl_conn *c, struct ctl_id *id)
-{
- struct host *host;
- struct table *table;
- int n;
-
- if (id->id == EMPTY_ID)
- host = host_findbyname(env, id->name);
- else
- host = host_find(env, id->id);
- if (host == NULL)
- return (-1);
- id->id = host->conf.id;
-
- if (host->flags & F_DISABLE)
- return (0);
-
- if (host->up == HOST_UP) {
- if ((table = table_find(env, host->conf.tableid)) == NULL)
- fatalx("disable_host: invalid table id");
- table->up--;
- table->conf.flags |= F_CHANGED;
- }
-
- host->up = HOST_UNKNOWN;
- host->flags |= F_DISABLE;
- host->flags |= F_DEL;
- host->flags &= ~(F_ADD);
- host->check_cnt = 0;
- host->up_cnt = 0;
-
- imsg_compose(ibuf_hce, IMSG_HOST_DISABLE, 0, 0, -1,
- &host->conf.id, sizeof(host->conf.id));
- /* Forward to relay engine(s) */
- for (n = 0; n < env->prefork_relay; n++)
- imsg_compose(&ibuf_relay[n],
- IMSG_HOST_DISABLE, 0, 0, -1,
- &host->conf.id, sizeof(host->conf.id));
- log_debug("disable_host: disabled host %d", host->conf.id);
- pfe_sync();
- return (0);
-}
-
-int
-enable_host(struct ctl_conn *c, struct ctl_id *id)
-{
- struct host *host;
- int n;
-
- if (id->id == EMPTY_ID)
- host = host_findbyname(env, id->name);
- else
- host = host_find(env, id->id);
- if (host == NULL)
- return (-1);
- id->id = host->conf.id;
-
- if (!(host->flags & F_DISABLE))
- return (0);
-
- host->up = HOST_UNKNOWN;
- host->flags &= ~(F_DISABLE);
- host->flags &= ~(F_DEL);
- host->flags &= ~(F_ADD);
-
- imsg_compose(ibuf_hce, IMSG_HOST_ENABLE, 0, 0, -1,
- &host->conf.id, sizeof (host->conf.id));
- /* Forward to relay engine(s) */
- for (n = 0; n < env->prefork_relay; n++)
- imsg_compose(&ibuf_relay[n],
- IMSG_HOST_ENABLE, 0, 0, -1,
- &host->conf.id, sizeof(host->conf.id));
- log_debug("enable_host: enabled host %d", host->conf.id);
- pfe_sync();
- return (0);
-}
-
-void
-pfe_sync(void)
-{
- struct service *service;
- struct table *active;
- struct table *table;
- struct ctl_id id;
- struct imsg imsg;
- struct ctl_demote demote;
-
- bzero(&id, sizeof(id));
- bzero(&imsg, sizeof(imsg));
- TAILQ_FOREACH(service, env->services, entry) {
- service->conf.flags &= ~(F_BACKUP);
- service->conf.flags &= ~(F_DOWN);
-
- if (service->conf.flags & F_DISABLE ||
- (service->table->up == 0 && service->backup->up == 0)) {
- service->conf.flags |= F_DOWN;
- active = NULL;
- } else if (service->table->up == 0 && service->backup->up > 0) {
- service->conf.flags |= F_BACKUP;
- active = service->backup;
- active->conf.flags |=
- service->table->conf.flags & F_CHANGED;
- active->conf.flags |=
- service->backup->conf.flags & F_CHANGED;
- } else
- active = service->table;
-
- if (active != NULL && active->conf.flags & F_CHANGED) {
- id.id = active->conf.id;
- imsg.hdr.type = IMSG_CTL_TABLE_CHANGED;
- imsg.hdr.len = sizeof(id) + IMSG_HEADER_SIZE;
- imsg.data = &id;
- sync_table(env, service, active);
- control_imsg_forward(&imsg);
- }
-
- if (service->conf.flags & F_DOWN) {
- if (service->conf.flags & F_ACTIVE_RULESET) {
- flush_table(env, service);
- log_debug("pfe_sync: disabling ruleset");
- service->conf.flags &= ~(F_ACTIVE_RULESET);
- id.id = service->conf.id;
- imsg.hdr.type = IMSG_CTL_PULL_RULESET;
- imsg.hdr.len = sizeof(id) + IMSG_HEADER_SIZE;
- imsg.data = &id;
- sync_ruleset(env, service, 0);
- control_imsg_forward(&imsg);
- }
- } else if (!(service->conf.flags & F_ACTIVE_RULESET)) {
- log_debug("pfe_sync: enabling ruleset");
- service->conf.flags |= F_ACTIVE_RULESET;
- id.id = service->conf.id;
- imsg.hdr.type = IMSG_CTL_PUSH_RULESET;
- imsg.hdr.len = sizeof(id) + IMSG_HEADER_SIZE;
- imsg.data = &id;
- sync_ruleset(env, service, 1);
- control_imsg_forward(&imsg);
- }
- }
-
- TAILQ_FOREACH(table, env->tables, entry) {
- /*
- * clean up change flag.
- */
- table->conf.flags &= ~(F_CHANGED);
-
- /*
- * handle demotion.
- */
- if ((table->conf.flags & F_DEMOTE) == 0)
- continue;
- demote.level = 0;
- if (table->up && table->conf.flags & F_DEMOTED) {
- demote.level = -1;
- table->conf.flags &= ~F_DEMOTED;
- }
- else if (!table->up && !(table->conf.flags & F_DEMOTED)) {
- demote.level = 1;
- table->conf.flags |= F_DEMOTED;
- }
- if (demote.level == 0)
- continue;
- log_debug("pfe_sync: demote %d table '%s' group '%s'",
- demote.level, table->conf.name, table->conf.demote_group);
- (void)strlcpy(demote.group, table->conf.demote_group,
- sizeof(demote.group));
- imsg_compose(ibuf_main, IMSG_DEMOTE, 0, 0, -1,
- &demote, sizeof(demote));
- }
-}
diff --git a/usr.sbin/hoststated/pfe_filter.c b/usr.sbin/hoststated/pfe_filter.c
deleted file mode 100644
index e8721c4b5cc..00000000000
--- a/usr.sbin/hoststated/pfe_filter.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/* $OpenBSD: pfe_filter.c,v 1.19 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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/ioctl.h>
-
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <limits.h>
-#include <fcntl.h>
-#include <event.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-struct pfdata {
- int dev;
- struct pf_anchor *anchor;
- struct pfioc_trans pft;
- struct pfioc_trans_e pfte;
-};
-
-int transaction_init(struct hoststated *, const char *);
-int transaction_commit(struct hoststated *);
-void kill_tables(struct hoststated *);
-
-void
-init_filter(struct hoststated *env)
-{
- struct pf_status status;
-
- if ((env->pf = calloc(1, sizeof(*(env->pf)))) == NULL)
- fatal("calloc");
- if ((env->pf->dev = open(PF_SOCKET, O_RDWR)) == -1)
- fatal("init_filter: cannot open pf socket");
- if (ioctl(env->pf->dev, DIOCGETSTATUS, &status) == -1)
- fatal("init_filter: DIOCGETSTATUS");
- if (!status.running)
- fatalx("init_filter: pf is disabled");
- log_debug("init_filter: filter init done");
-}
-
-void
-init_tables(struct hoststated *env)
-{
- int i;
- struct service *service;
- struct pfr_table *tables;
- struct pfioc_table io;
-
- if ((tables = calloc(env->servicecount, sizeof(*tables))) == NULL)
- fatal("calloc");
- i = 0;
-
- TAILQ_FOREACH(service, env->services, entry) {
- if (strlcpy(tables[i].pfrt_anchor, HOSTSTATED_ANCHOR "/",
- sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcat(tables[i].pfrt_anchor, service->conf.name,
- sizeof(tables[i].pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcpy(tables[i].pfrt_name, service->conf.name,
- sizeof(tables[i].pfrt_name)) >=
- sizeof(tables[i].pfrt_name))
- goto toolong;
- tables[i].pfrt_flags |= PFR_TFLAG_PERSIST;
- i++;
- }
- if (i != env->servicecount)
- fatalx("init_tables: table count modified");
-
- memset(&io, 0, sizeof(io));
- io.pfrio_size = env->servicecount;
- io.pfrio_esize = sizeof(*tables);
- io.pfrio_buffer = tables;
-
- if (ioctl(env->pf->dev, DIOCRADDTABLES, &io) == -1)
- fatal("init_tables: cannot create tables");
- log_debug("init_tables: created %d tables", io.pfrio_nadd);
-
- free(tables);
-
- if (io.pfrio_nadd == env->servicecount)
- return;
-
- /*
- * clear all tables, since some already existed
- */
- TAILQ_FOREACH(service, env->services, entry)
- flush_table(env, service);
-
- return;
-
- toolong:
- fatal("init_tables: name too long");
-}
-
-void
-kill_tables(struct hoststated *env) {
- struct pfioc_table io;
- struct service *service;
-
- memset(&io, 0, sizeof(io));
- TAILQ_FOREACH(service, env->services, entry) {
- if (strlcpy(io.pfrio_table.pfrt_anchor, HOSTSTATED_ANCHOR "/",
- sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcat(io.pfrio_table.pfrt_anchor, service->conf.name,
- sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (ioctl(env->pf->dev, DIOCRCLRTABLES, &io) == -1)
- fatal("kill_tables: ioctl faile: ioctl failed");
- }
- log_debug("kill_tables: deleted %d tables", io.pfrio_ndel);
- return;
-
- toolong:
- fatal("kill_tables: name too long");
-}
-
-void
-sync_table(struct hoststated *env, struct service *service, struct table *table)
-{
- int i;
- struct pfioc_table io;
- struct pfr_addr *addlist;
- struct sockaddr_in *sain;
- struct sockaddr_in6 *sain6;
- struct host *host;
-
- if (table == NULL)
- return;
-
- if (table->up == 0) {
- flush_table(env, service);
- return;
- }
-
- if ((addlist = calloc(table->up, sizeof(*addlist))) == NULL)
- fatal("calloc");
-
- memset(&io, 0, sizeof(io));
- io.pfrio_esize = sizeof(struct pfr_addr);
- io.pfrio_size = table->up;
- io.pfrio_size2 = 0;
- io.pfrio_buffer = addlist;
- if (strlcpy(io.pfrio_table.pfrt_anchor, HOSTSTATED_ANCHOR "/",
- sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcat(io.pfrio_table.pfrt_anchor, service->conf.name,
- sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcpy(io.pfrio_table.pfrt_name, service->conf.name,
- sizeof(io.pfrio_table.pfrt_name)) >=
- sizeof(io.pfrio_table.pfrt_name))
- goto toolong;
-
- i = 0;
- TAILQ_FOREACH(host, &table->hosts, entry) {
- if (host->up != HOST_UP)
- continue;
- memset(&(addlist[i]), 0, sizeof(addlist[i]));
- switch (host->conf.ss.ss_family) {
- case AF_INET:
- sain = (struct sockaddr_in *)&host->conf.ss;
- addlist[i].pfra_af = AF_INET;
- memcpy(&(addlist[i].pfra_ip4addr), &sain->sin_addr,
- sizeof(sain->sin_addr));
- addlist[i].pfra_net = 32;
- break;
- case AF_INET6:
- sain6 = (struct sockaddr_in6 *)&host->conf.ss;
- addlist[i].pfra_af = AF_INET6;
- memcpy(&(addlist[i].pfra_ip6addr), &sain6->sin6_addr,
- sizeof(sain6->sin6_addr));
- addlist[i].pfra_net = 128;
- break;
- default:
- fatalx("sync_table: unknown address family");
- break;
- }
- i++;
- }
- if (i != table->up)
- fatalx("sync_table: desynchronized");
-
- if (ioctl(env->pf->dev, DIOCRSETADDRS, &io) == -1)
- fatal("sync_table: cannot set address list");
-
- free(addlist);
-
- log_debug("sync_table: table %s: %d added, %d deleted, %d changed",
- io.pfrio_table.pfrt_name,
- io.pfrio_nadd, io.pfrio_ndel, io.pfrio_nchange);
- return;
-
- toolong:
- fatal("sync_table: name too long");
-}
-
-void
-flush_table(struct hoststated *env, struct service *service)
-{
- struct pfioc_table io;
-
- memset(&io, 0, sizeof(io));
- if (strlcpy(io.pfrio_table.pfrt_anchor, HOSTSTATED_ANCHOR "/",
- sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcat(io.pfrio_table.pfrt_anchor, service->conf.name,
- sizeof(io.pfrio_table.pfrt_anchor)) >= PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcpy(io.pfrio_table.pfrt_name, service->conf.name,
- sizeof(io.pfrio_table.pfrt_name)) >=
- sizeof(io.pfrio_table.pfrt_name))
- goto toolong;
- if (ioctl(env->pf->dev, DIOCRCLRADDRS, &io) == -1)
- fatal("flush_table: cannot flush table");
- log_debug("flush_table: flushed table %s", service->conf.name);
- return;
-
- toolong:
- fatal("flush_table: name too long");
-}
-
-int
-transaction_init(struct hoststated *env, const char *anchor)
-{
- env->pf->pft.size = 1;
- env->pf->pft.esize = sizeof env->pf->pfte;
- env->pf->pft.array = &env->pf->pfte;
-
- memset(&env->pf->pfte, 0, sizeof env->pf->pfte);
- (void)strlcpy(env->pf->pfte.anchor, anchor, PF_ANCHOR_NAME_SIZE);
- env->pf->pfte.rs_num = PF_RULESET_RDR;
-
- if (ioctl(env->pf->dev, DIOCXBEGIN, &env->pf->pft) == -1)
- return (-1);
- return (0);
-}
-
-int
-transaction_commit(struct hoststated *env)
-{
- if (ioctl(env->pf->dev, DIOCXCOMMIT, &env->pf->pft) == -1)
- return (-1);
- return (0);
-}
-
-void
-sync_ruleset(struct hoststated *env, struct service *service, int enable)
-{
- struct pfioc_rule rio;
- struct pfioc_pooladdr pio;
- struct sockaddr_in *sain;
- struct sockaddr_in6 *sain6;
- struct address *address;
- char anchor[PF_ANCHOR_NAME_SIZE];
-
- bzero(anchor, sizeof(anchor));
- if (strlcpy(anchor, HOSTSTATED_ANCHOR "/", sizeof(anchor)) >=
- PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcat(anchor, service->conf.name, sizeof(anchor)) >=
- PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (transaction_init(env, anchor) == -1) {
- log_warn("sync_ruleset: transaction init failed");
- return;
- }
-
- if (!enable) {
- if (transaction_commit(env) == -1)
- log_warn("sync_ruleset: "
- "remove rules transaction failed");
- else
- log_debug("sync_ruleset: rules removed");
- return;
- }
-
- TAILQ_FOREACH(address, &service->virts, entry) {
- memset(&rio, 0, sizeof(rio));
- memset(&pio, 0, sizeof(pio));
- (void)strlcpy(rio.anchor, anchor, sizeof(rio.anchor));
-
- rio.ticket = env->pf->pfte.ticket;
- if (ioctl(env->pf->dev, DIOCBEGINADDRS, &pio) == -1)
- fatal("sync_ruleset: cannot initialise address pool");
-
- rio.pool_ticket = pio.ticket;
- rio.rule.af = address->ss.ss_family;
- rio.rule.proto = IPPROTO_TCP;
- rio.rule.src.addr.type = PF_ADDR_ADDRMASK;
- rio.rule.dst.addr.type = PF_ADDR_ADDRMASK;
- rio.rule.dst.port_op = PF_OP_EQ;
- rio.rule.dst.port[0] = address->port;
- rio.rule.rtableid = -1; /* stay in the main routing table */
- rio.rule.action = PF_RDR;
- if (strlen(service->conf.tag))
- (void)strlcpy(rio.rule.tagname, service->conf.tag,
- sizeof(rio.rule.tagname));
- if (strlen(address->ifname))
- (void)strlcpy(rio.rule.ifname, address->ifname,
- sizeof(rio.rule.ifname));
-
- if (address->ss.ss_family == AF_INET) {
- sain = (struct sockaddr_in *)&address->ss;
-
- rio.rule.dst.addr.v.a.addr.addr32[0] =
- sain->sin_addr.s_addr;
- rio.rule.dst.addr.v.a.mask.addr32[0] = 0xffffffff;
-
- } else {
- sain6 = (struct sockaddr_in6 *)&address->ss;
-
- memcpy(&rio.rule.dst.addr.v.a.addr.v6,
- &sain6->sin6_addr.s6_addr,
- sizeof(sain6->sin6_addr.s6_addr));
- memset(&rio.rule.dst.addr.v.a.mask.addr8, 0xff, 16);
- }
-
- pio.addr.addr.type = PF_ADDR_TABLE;
- if (strlcpy(pio.addr.addr.v.tblname, service->conf.name,
- sizeof(pio.addr.addr.v.tblname)) >=
- sizeof(pio.addr.addr.v.tblname))
- fatal("sync_ruleset: table name too long");
- if (ioctl(env->pf->dev, DIOCADDADDR, &pio) == -1)
- fatal("sync_ruleset: cannot add address to pool");
-
- rio.rule.rpool.proxy_port[0] = ntohs(service->table->conf.port);
- rio.rule.rpool.port_op = PF_OP_EQ;
- rio.rule.rpool.opts = PF_POOL_ROUNDROBIN;
- if (service->conf.flags & F_STICKY)
- rio.rule.rpool.opts |= PF_POOL_STICKYADDR;
-
- if (ioctl(env->pf->dev, DIOCADDRULE, &rio) == -1)
- fatal("cannot add rule");
- log_debug("sync_ruleset: rule added");
- }
- if (transaction_commit(env) == -1)
- log_warn("sync_ruleset: add rules transaction failed");
- return;
-
- toolong:
- fatal("sync_ruleset: name too long");
-}
-
-void
-flush_rulesets(struct hoststated *env)
-{
- struct service *service;
- char anchor[PF_ANCHOR_NAME_SIZE];
-
- kill_tables(env);
- TAILQ_FOREACH(service, env->services, entry) {
- if (strlcpy(anchor, HOSTSTATED_ANCHOR "/", sizeof(anchor)) >=
- PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (strlcat(anchor, service->conf.name, sizeof(anchor)) >=
- PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (transaction_init(env, anchor) == -1 ||
- transaction_commit(env) == -1)
- log_warn("flush_rulesets: transaction for %s/ failed",
- HOSTSTATED_ANCHOR);
- }
- if (strlcpy(anchor, HOSTSTATED_ANCHOR, sizeof(anchor)) >=
- PF_ANCHOR_NAME_SIZE)
- goto toolong;
- if (transaction_init(env, anchor) == -1 ||
- transaction_commit(env) == -1)
- log_warn("flush_rulesets: transaction for %s failed",
- HOSTSTATED_ANCHOR);
- log_debug("flush_rulesets: flushed rules");
- return;
-
- toolong:
- fatal("flush_rulesets: name too long");
-}
-
-int
-natlook(struct hoststated *env, struct ctl_natlook *cnl)
-{
- struct pfioc_natlook pnl;
- struct sockaddr_in *in, *out;
- struct sockaddr_in6 *in6, *out6;
- char ibuf[BUFSIZ], obuf[BUFSIZ];
-
- bzero(&pnl, sizeof(pnl));
-
- if ((pnl.af = cnl->src.ss_family) != cnl->dst.ss_family)
- fatalx("natlook: illegal address families");
- switch (pnl.af) {
- case AF_INET:
- in = (struct sockaddr_in *)&cnl->src;
- out = (struct sockaddr_in *)&cnl->dst;
- bcopy(&in->sin_addr, &pnl.saddr.addr8, in->sin_len);
- pnl.sport = in->sin_port;
- bcopy(&out->sin_addr, &pnl.daddr.addr8, out->sin_len);
- pnl.dport = out->sin_port;
- break;
- case AF_INET6:
- in6 = (struct sockaddr_in6 *)&cnl->src;
- out6 = (struct sockaddr_in6 *)&cnl->dst;
- bcopy(&in6->sin6_addr, &pnl.saddr.addr8, in6->sin6_len);
- pnl.sport = in6->sin6_port;
- bcopy(&out6->sin6_addr, &pnl.daddr.addr8, out6->sin6_len);
- pnl.dport = out6->sin6_port;
- }
- pnl.proto = IPPROTO_TCP;
- pnl.direction = PF_IN;
- cnl->in = 1;
-
- if (ioctl(env->pf->dev, DIOCNATLOOK, &pnl) == -1) {
- pnl.direction = PF_OUT;
- cnl->in = 0;
- if (ioctl(env->pf->dev, DIOCNATLOOK, &pnl) == -1) {
- log_debug("natlook: error");
- return (-1);
- }
- }
-
- inet_ntop(pnl.af, &pnl.rsaddr, ibuf, sizeof(ibuf));
- inet_ntop(pnl.af, &pnl.rdaddr, obuf, sizeof(obuf));
- log_debug("natlook: %s %s:%d -> %s:%d",
- pnl.direction == PF_IN ? "in" : "out",
- ibuf, ntohs(pnl.rsport), obuf, ntohs(pnl.rdport));
-
- switch (pnl.af) {
- case AF_INET:
- in = (struct sockaddr_in *)&cnl->rsrc;
- out = (struct sockaddr_in *)&cnl->rdst;
- bcopy(&pnl.rsaddr.addr8, &in->sin_addr, sizeof(in->sin_addr));
- in->sin_port = pnl.rsport;
- bcopy(&pnl.rdaddr.addr8, &out->sin_addr, sizeof(out->sin_addr));
- out->sin_port = pnl.rdport;
- break;
- case AF_INET6:
- in6 = (struct sockaddr_in6 *)&cnl->rsrc;
- out6 = (struct sockaddr_in6 *)&cnl->rdst;
- bcopy(&pnl.rsaddr.addr8, &in6->sin6_addr,
- sizeof(in6->sin6_addr));
- bcopy(&pnl.rdaddr.addr8, &out6->sin6_addr,
- sizeof(out6->sin6_addr));
- break;
- }
- cnl->rsrc.ss_family = pnl.af;
- cnl->rdst.ss_family = pnl.af;
- cnl->rsport = pnl.rsport;
- cnl->rdport = pnl.rdport;
-
- return (0);
-}
diff --git a/usr.sbin/hoststated/relay.c b/usr.sbin/hoststated/relay.c
deleted file mode 100644
index 8039aec31ab..00000000000
--- a/usr.sbin/hoststated/relay.c
+++ /dev/null
@@ -1,2924 +0,0 @@
-/* $OpenBSD: relay.c,v 1.74 2007/11/28 16:25:12 reyk Exp $ */
-
-/*
- * Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.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/time.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/tree.h>
-#include <sys/hash.h>
-#include <sys/resource.h>
-
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <err.h>
-#include <pwd.h>
-#include <event.h>
-#include <fnmatch.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-void relay_sig_handler(int sig, short, void *);
-void relay_statistics(int, short, void *);
-void relay_dispatch_pfe(int, short, void *);
-void relay_dispatch_parent(int, short, void *);
-void relay_shutdown(void);
-
-void relay_privinit(void);
-void relay_nodedebug(const char *, struct protonode *);
-void relay_protodebug(struct relay *);
-void relay_init(void);
-void relay_launch(void);
-int relay_socket_af(struct sockaddr_storage *, in_port_t);
-int relay_socket(struct sockaddr_storage *, in_port_t,
- struct protocol *);
-int relay_socket_listen(struct sockaddr_storage *, in_port_t,
- struct protocol *);
-int relay_socket_connect(struct sockaddr_storage *, in_port_t,
- struct protocol *);
-
-void relay_accept(int, short, void *);
-void relay_input(struct session *);
-void relay_close(struct session *, const char *);
-void relay_session(struct session *);
-void relay_natlook(int, short, void *);
-
-int relay_connect(struct session *);
-void relay_connected(int, short, void *);
-
-u_int32_t relay_hash_addr(struct sockaddr_storage *, u_int32_t);
-int relay_from_table(struct session *);
-
-void relay_write(struct bufferevent *, void *);
-void relay_read(struct bufferevent *, void *);
-void relay_error(struct bufferevent *, short, void *);
-void relay_dump(struct ctl_relay_event *, const void *, size_t);
-
-int relay_resolve(struct ctl_relay_event *,
- struct protonode *, struct protonode *);
-int relay_handle_http(struct ctl_relay_event *,
- struct protonode *, struct protonode *,
- struct protonode *, int);
-void relay_read_http(struct bufferevent *, void *);
-static int _relay_lookup_url(struct ctl_relay_event *, char *, char *,
- char *, enum digest_type);
-int relay_lookup_url(struct ctl_relay_event *,
- const char *, enum digest_type);
-int relay_lookup_query(struct ctl_relay_event *);
-int relay_lookup_cookie(struct ctl_relay_event *, const char *);
-void relay_read_httpcontent(struct bufferevent *, void *);
-void relay_read_httpchunks(struct bufferevent *, void *);
-char *relay_expand_http(struct ctl_relay_event *, char *,
- char *, size_t);
-void relay_close_http(struct session *, u_int, const char *,
- u_int16_t);
-
-SSL_CTX *relay_ssl_ctx_create(struct relay *);
-void relay_ssl_transaction(struct session *);
-void relay_ssl_accept(int, short, void *);
-void relay_ssl_connected(struct ctl_relay_event *);
-void relay_ssl_readcb(int, short, void *);
-void relay_ssl_writecb(int, short, void *);
-
-int relay_bufferevent_add(struct event *, int);
-#ifdef notyet
-int relay_bufferevent_printf(struct ctl_relay_event *,
- const char *, ...);
-#endif
-int relay_bufferevent_print(struct ctl_relay_event *, char *);
-int relay_bufferevent_write_buffer(struct ctl_relay_event *,
- struct evbuffer *);
-int relay_bufferevent_write_chunk(struct ctl_relay_event *,
- struct evbuffer *, size_t);
-int relay_bufferevent_write(struct ctl_relay_event *,
- void *, size_t);
-int relay_cmp_af(struct sockaddr_storage *,
- struct sockaddr_storage *);
-char *relay_load_file(const char *, off_t *);
-static __inline int
- relay_proto_cmp(struct protonode *, struct protonode *);
-extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t,
- size_t, void *);
-
-volatile sig_atomic_t relay_sessions;
-objid_t relay_conid;
-
-static struct hoststated *env = NULL;
-struct imsgbuf *ibuf_pfe;
-struct imsgbuf *ibuf_main;
-int proc_id;
-
-#if DEBUG > 1
-#define DPRINTF log_debug
-#else
-#define DPRINTF(x...) do { } while(0)
-#endif
-
-void
-relay_sig_handler(int sig, short event, void *arg)
-{
- switch (sig) {
- case SIGTERM:
- case SIGINT:
- (void)event_loopexit(NULL);
- }
-}
-
-pid_t
-relay(struct hoststated *x_env, int pipe_parent2pfe[2], int pipe_parent2hce[2],
- int pipe_parent2relay[RELAY_MAXPROC][2], int pipe_pfe2hce[2],
- int pipe_pfe2relay[RELAY_MAXPROC][2])
-{
- pid_t pid;
- struct passwd *pw;
- struct event ev_sigint;
- struct event ev_sigterm;
- int i;
-
- switch (pid = fork()) {
- case -1:
- fatal("relay: cannot fork");
- case 0:
- break;
- default:
- return (pid);
- }
-
- env = x_env;
- purge_config(env, PURGE_SERVICES);
-
- /* Need root privileges for relay initialization */
- relay_privinit();
-
- if ((pw = getpwnam(HOSTSTATED_USER)) == NULL)
- fatal("relay: getpwnam");
-
-#ifndef DEBUG
- if (chroot(pw->pw_dir) == -1)
- fatal("relay: chroot");
- if (chdir("/") == -1)
- fatal("relay: chdir(\"/\")");
-
-#else
-#warning disabling privilege revocation and chroot in DEBUG mode
-#endif
-
- setproctitle("socket relay engine");
- hoststated_process = PROC_RELAY;
-
-#ifndef DEBUG
- 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("relay: can't drop privileges");
-#endif
-
- /* Fork child handlers */
- for (i = 1; i < env->prefork_relay; i++) {
- if (fork() == 0) {
- proc_id = i;
- break;
- }
- }
-
- event_init();
-
- /* Per-child initialization */
- relay_init();
-
- signal_set(&ev_sigint, SIGINT, relay_sig_handler, NULL);
- signal_set(&ev_sigterm, SIGTERM, relay_sig_handler, NULL);
- signal_add(&ev_sigint, NULL);
- signal_add(&ev_sigterm, NULL);
- signal(SIGHUP, SIG_IGN);
- signal(SIGPIPE, SIG_IGN);
-
- /* setup pipes */
- close(pipe_pfe2hce[0]);
- close(pipe_pfe2hce[1]);
- close(pipe_parent2hce[0]);
- close(pipe_parent2hce[1]);
- close(pipe_parent2pfe[0]);
- close(pipe_parent2pfe[1]);
- for (i = 0; i < env->prefork_relay; i++) {
- if (i == proc_id)
- continue;
- close(pipe_parent2relay[i][0]);
- close(pipe_parent2relay[i][1]);
- close(pipe_pfe2relay[i][0]);
- close(pipe_pfe2relay[i][1]);
- }
- close(pipe_parent2relay[proc_id][1]);
- close(pipe_pfe2relay[proc_id][1]);
-
- if ((ibuf_pfe = calloc(1, sizeof(struct imsgbuf))) == NULL ||
- (ibuf_main = calloc(1, sizeof(struct imsgbuf))) == NULL)
- fatal("relay");
- imsg_init(ibuf_main, pipe_parent2relay[proc_id][0],
- relay_dispatch_parent);
- imsg_init(ibuf_pfe, pipe_pfe2relay[proc_id][0], relay_dispatch_pfe);
-
- ibuf_pfe->events = EV_READ;
- event_set(&ibuf_pfe->ev, ibuf_pfe->fd, ibuf_pfe->events,
- ibuf_pfe->handler, ibuf_pfe);
- event_add(&ibuf_pfe->ev, NULL);
-
- ibuf_main->events = EV_READ;
- event_set(&ibuf_main->ev, ibuf_main->fd, ibuf_main->events,
- ibuf_main->handler, ibuf_main);
- event_add(&ibuf_main->ev, NULL);
-
- relay_launch();
-
- event_dispatch();
- relay_shutdown();
-
- return (0);
-}
-
-void
-relay_shutdown(void)
-{
- struct session *con;
-
- struct relay *rlay;
- TAILQ_FOREACH(rlay, env->relays, entry) {
- if (rlay->conf.flags & F_DISABLE)
- continue;
- close(rlay->s);
- while ((con = SPLAY_ROOT(&rlay->sessions)) != NULL)
- relay_close(con, "shutdown");
- }
- usleep(200); /* XXX relay needs to shutdown last */
- log_info("socket relay engine exiting");
- _exit(0);
-}
-
-void
-relay_nodedebug(const char *name, struct protonode *pn)
-{
- const char *s;
- int digest;
-
- if (pn->action == NODE_ACTION_NONE)
- return;
-
- fprintf(stderr, "\t\t");
- fprintf(stderr, "%s ", name);
-
- switch (pn->type) {
- case NODE_TYPE_HEADER:
- break;
- case NODE_TYPE_QUERY:
- fprintf(stderr, "query ");
- break;
- case NODE_TYPE_COOKIE:
- fprintf(stderr, "cookie ");
- break;
- case NODE_TYPE_PATH:
- fprintf(stderr, "path ");
- break;
- case NODE_TYPE_URL:
- fprintf(stderr, "url ");
- break;
- }
-
- switch (pn->action) {
- case NODE_ACTION_APPEND:
- fprintf(stderr, "append \"%s\" to \"%s\"",
- pn->value, pn->key);
- break;
- case NODE_ACTION_CHANGE:
- fprintf(stderr, "change \"%s\" to \"%s\"",
- pn->key, pn->value);
- break;
- case NODE_ACTION_REMOVE:
- fprintf(stderr, "remove \"%s\"",
- pn->key);
- break;
- case NODE_ACTION_EXPECT:
- case NODE_ACTION_FILTER:
- s = pn->action == NODE_ACTION_EXPECT ? "expect" : "filter";
- digest = pn->flags & PNFLAG_LOOKUP_URL_DIGEST;
- if (strcmp(pn->value, "*") == 0)
- fprintf(stderr, "%s %s\"%s\"", s,
- digest ? "digest " : "", pn->key);
- else
- fprintf(stderr, "%s \"%s\" from \"%s\"", s,
- pn->value, pn->key);
- break;
- case NODE_ACTION_HASH:
- fprintf(stderr, "hash \"%s\"", pn->key);
- break;
- case NODE_ACTION_LOG:
- fprintf(stderr, "log \"%s\"", pn->key);
- break;
- case NODE_ACTION_MARK:
- if (strcmp(pn->value, "*") == 0)
- fprintf(stderr, "mark \"%s\"", pn->key);
- else
- fprintf(stderr, "mark \"%s\" from \"%s\"",
- pn->value, pn->key);
- break;
- case NODE_ACTION_NONE:
- break;
- }
- fprintf(stderr, "\n");
-}
-
-void
-relay_protodebug(struct relay *rlay)
-{
- struct protocol *proto = rlay->proto;
- struct protonode *proot, *pn;
- struct proto_tree *tree;
- const char *name;
- int i;
-
- fprintf(stderr, "protocol %d: name %s\n", proto->id, proto->name);
- fprintf(stderr, "\tflags: 0x%04x\n", proto->flags);
- if (proto->cache != -1)
- fprintf(stderr, "\tssl session cache: %d\n", proto->cache);
- fprintf(stderr, "\ttype: ");
- switch (proto->type) {
- case RELAY_PROTO_TCP:
- fprintf(stderr, "tcp\n");
- break;
- case RELAY_PROTO_HTTP:
- fprintf(stderr, "http\n");
- break;
- case RELAY_PROTO_DNS:
- fprintf(stderr, "dns\n");
- break;
- }
-
- name = "request";
- tree = &proto->request_tree;
- show:
- i = 0;
- RB_FOREACH(proot, proto_tree, tree) {
- PROTONODE_FOREACH(pn, proot, entry) {
-#ifndef DEBUG
- if (++i > 100)
- break;
-#endif
- relay_nodedebug(name, pn);
- }
-#ifndef DEBUG
- /* Limit the number of displayed lines */
- if (++i > 100) {
- fprintf(stderr, "\t\t...\n");
- break;
- }
-#endif
- }
- if (tree == &proto->request_tree) {
- name = "response";
- tree = &proto->response_tree;
- goto show;
- }
-}
-
-void
-relay_privinit(void)
-{
- struct relay *rlay;
- extern int debug;
-
- if (env->flags & F_SSL)
- ssl_init(env);
-
- TAILQ_FOREACH(rlay, env->relays, entry) {
- log_debug("relay_privinit: adding relay %s", rlay->conf.name);
-
- if (debug)
- relay_protodebug(rlay);
-
- switch (rlay->proto->type) {
- case RELAY_PROTO_DNS:
- relay_udp_privinit(env, rlay);
- break;
- case RELAY_PROTO_TCP:
- case RELAY_PROTO_HTTP:
- /* Use defaults */
- break;
- }
-
- if (rlay->conf.flags & F_UDP)
- rlay->s = relay_udp_bind(&rlay->conf.ss,
- rlay->conf.port, rlay->proto);
- else
- rlay->s = relay_socket_listen(&rlay->conf.ss,
- rlay->conf.port, rlay->proto);
- if (rlay->s == -1)
- fatal("relay_privinit: failed to listen");
- }
-}
-
-void
-relay_init(void)
-{
- struct relay *rlay;
- struct host *host;
- struct timeval tv;
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
- fatal("relay_init: failed to get resource limit");
- log_debug("relay_init: max open files %d", rl.rlim_max);
-
- /*
- * Allow the maximum number of open file descriptors for this
- * login class (which should be the class "daemon" by default).
- */
- rl.rlim_cur = rl.rlim_max;
- if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
- fatal("relay_init: failed to set resource limit");
-
- TAILQ_FOREACH(rlay, env->relays, entry) {
- if ((rlay->conf.flags & F_SSL) &&
- (rlay->ssl_ctx = relay_ssl_ctx_create(rlay)) == NULL)
- fatal("relay_init: failed to create SSL context");
-
- if (rlay->dsttable != NULL) {
- switch (rlay->conf.dstmode) {
- case RELAY_DSTMODE_ROUNDROBIN:
- rlay->dstkey = 0;
- break;
- case RELAY_DSTMODE_LOADBALANCE:
- case RELAY_DSTMODE_HASH:
- rlay->dstkey =
- hash32_str(rlay->conf.name, HASHINIT);
- rlay->dstkey =
- hash32_str(rlay->dsttable->conf.name,
- rlay->dstkey);
- break;
- }
- rlay->dstnhosts = 0;
- TAILQ_FOREACH(host, &rlay->dsttable->hosts, entry) {
- if (rlay->dstnhosts >= RELAY_MAXHOSTS)
- fatal("relay_init: "
- "too many hosts in table");
- host->idx = rlay->dstnhosts;
- rlay->dsthost[rlay->dstnhosts++] = host;
- }
- log_info("adding %d hosts from table %s%s",
- rlay->dstnhosts, rlay->dsttable->conf.name,
- rlay->conf.dstcheck ? "" : " (no check)");
- }
- }
-
- /* Schedule statistics timer */
- evtimer_set(&env->statev, relay_statistics, NULL);
- bcopy(&env->statinterval, &tv, sizeof(tv));
- evtimer_add(&env->statev, &tv);
-}
-
-void
-relay_statistics(int fd, short events, void *arg)
-{
- struct relay *rlay;
- struct ctl_stats crs, *cur;
- struct timeval tv, tv_now;
- int resethour = 0, resetday = 0;
- struct session *con, *next_con;
-
- /*
- * This is a hack to calculate some average statistics.
- * It doesn't try to be very accurate, but could be improved...
- */
-
- timerclear(&tv);
- if (gettimeofday(&tv_now, NULL))
- fatal("relay_init: gettimeofday");
-
- TAILQ_FOREACH(rlay, env->relays, entry) {
- bzero(&crs, sizeof(crs));
- resethour = resetday = 0;
-
- cur = &rlay->stats[proc_id];
- cur->cnt += cur->last;
- cur->tick++;
- cur->avg = (cur->last + cur->avg) / 2;
- cur->last_hour += cur->last;
- if ((cur->tick % (3600 / env->statinterval.tv_sec)) == 0) {
- cur->avg_hour = (cur->last_hour + cur->avg_hour) / 2;
- resethour++;
- }
- cur->last_day += cur->last;
- if ((cur->tick % (86400 / env->statinterval.tv_sec)) == 0) {
- cur->avg_day = (cur->last_day + cur->avg_day) / 2;
- resethour++;
- }
- bcopy(cur, &crs, sizeof(crs));
-
- cur->last = 0;
- if (resethour)
- cur->last_hour = 0;
- if (resetday)
- cur->last_day = 0;
-
- crs.id = rlay->conf.id;
- crs.proc = proc_id;
- imsg_compose(ibuf_pfe, IMSG_STATISTICS, 0, 0, -1,
- &crs, sizeof(crs));
-
- for (con = SPLAY_ROOT(&rlay->sessions);
- con != NULL; con = next_con) {
- next_con = SPLAY_NEXT(session_tree,
- &rlay->sessions, con);
- timersub(&tv_now, &con->tv_last, &tv);
- if (timercmp(&tv, &rlay->conf.timeout, >=))
- relay_close(con, "hard timeout");
- }
- }
-
- /* Schedule statistics timer */
- evtimer_set(&env->statev, relay_statistics, NULL);
- bcopy(&env->statinterval, &tv, sizeof(tv));
- evtimer_add(&env->statev, &tv);
-}
-
-void
-relay_launch(void)
-{
- struct relay *rlay;
- void (*callback)(int, short, void *);
-
- TAILQ_FOREACH(rlay, env->relays, entry) {
- log_debug("relay_launch: running relay %s", rlay->conf.name);
-
- rlay->up = HOST_UP;
-
- if (rlay->conf.flags & F_UDP)
- callback = relay_udp_server;
- else
- callback = relay_accept;
-
- event_set(&rlay->ev, rlay->s, EV_READ|EV_PERSIST,
- callback, rlay);
- event_add(&rlay->ev, NULL);
- }
-}
-
-int
-relay_socket_af(struct sockaddr_storage *ss, in_port_t port)
-{
- switch (ss->ss_family) {
- case AF_INET:
- ((struct sockaddr_in *)ss)->sin_port = port;
- ((struct sockaddr_in *)ss)->sin_len =
- sizeof(struct sockaddr_in);
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *)ss)->sin6_port = port;
- ((struct sockaddr_in6 *)ss)->sin6_len =
- sizeof(struct sockaddr_in6);
- break;
- default:
- return (-1);
- }
-
- return (0);
-}
-
-int
-relay_socket(struct sockaddr_storage *ss, in_port_t port,
- struct protocol *proto)
-{
- int s = -1, val;
- struct linger lng;
-
- if (relay_socket_af(ss, port) == -1)
- goto bad;
-
- if ((s = socket(ss->ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
- goto bad;
-
- /*
- * Socket options
- */
- bzero(&lng, sizeof(lng));
- if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1)
- goto bad;
- val = 1;
- if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(int)) == -1)
- goto bad;
- if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
- goto bad;
- if (proto->tcpflags & TCPFLAG_BUFSIZ) {
- val = proto->tcpbufsiz;
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
- &val, sizeof(val)) == -1)
- goto bad;
- val = proto->tcpbufsiz;
- if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
- &val, sizeof(val)) == -1)
- goto bad;
- }
-
- /*
- * IP options
- */
- if (proto->tcpflags & TCPFLAG_IPTTL) {
- val = (int)proto->tcpipttl;
- if (setsockopt(s, IPPROTO_IP, IP_TTL,
- &val, sizeof(val)) == -1)
- goto bad;
- }
- if (proto->tcpflags & TCPFLAG_IPMINTTL) {
- val = (int)proto->tcpipminttl;
- if (setsockopt(s, IPPROTO_IP, IP_MINTTL,
- &val, sizeof(val)) == -1)
- goto bad;
- }
-
- /*
- * TCP options
- */
- if (proto->tcpflags & (TCPFLAG_NODELAY|TCPFLAG_NNODELAY)) {
- if (proto->tcpflags & TCPFLAG_NNODELAY)
- val = 0;
- else
- val = 1;
- if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
- &val, sizeof(val)) == -1)
- goto bad;
- }
- if (proto->tcpflags & (TCPFLAG_SACK|TCPFLAG_NSACK)) {
- if (proto->tcpflags & TCPFLAG_NSACK)
- val = 0;
- else
- val = 1;
- if (setsockopt(s, IPPROTO_TCP, TCP_SACK_ENABLE,
- &val, sizeof(val)) == -1)
- goto bad;
- }
-
- return (s);
-
- bad:
- if (s != -1)
- close(s);
- return (-1);
-}
-
-int
-relay_socket_connect(struct sockaddr_storage *ss, in_port_t port,
- struct protocol *proto)
-{
- int s;
-
- if ((s = relay_socket(ss, port, proto)) == -1)
- return (-1);
-
- if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) {
- if (errno != EINPROGRESS)
- goto bad;
- }
-
- return (s);
-
- bad:
- close(s);
- return (-1);
-}
-
-int
-relay_socket_listen(struct sockaddr_storage *ss, in_port_t port,
- struct protocol *proto)
-{
- int s;
-
- if ((s = relay_socket(ss, port, proto)) == -1)
- return (-1);
-
- if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1)
- goto bad;
- if (listen(s, proto->tcpbacklog) == -1)
- goto bad;
-
- return (s);
-
- bad:
- close(s);
- return (-1);
-}
-
-void
-relay_connected(int fd, short sig, void *arg)
-{
- struct session *con = (struct session *)arg;
- struct relay *rlay = (struct relay *)con->relay;
- struct protocol *proto = rlay->proto;
- evbuffercb outrd = relay_read;
- evbuffercb outwr = relay_write;
- struct bufferevent *bev;
-
- if (sig == EV_TIMEOUT) {
- relay_close_http(con, 504, "connect timeout", 0);
- return;
- }
-
- DPRINTF("relay_connected: session %d: %ssuccessful",
- con->id, rlay->proto->lateconnect ? "late connect " : "");
-
- switch (rlay->proto->type) {
- case RELAY_PROTO_HTTP:
- /* Check the servers's HTTP response */
- if (!RB_EMPTY(&rlay->proto->response_tree)) {
- outrd = relay_read_http;
- if ((con->out.nodes = calloc(proto->response_nodes,
- sizeof(u_int8_t))) == NULL) {
- relay_close_http(con, 500,
- "failed to allocate nodes", 0);
- return;
- }
- }
- break;
- case RELAY_PROTO_TCP:
- /* Use defaults */
- break;
- default:
- fatalx("relay_input: unknown protocol");
- }
-
- /*
- * Relay <-> Server
- */
- bev = bufferevent_new(fd, outrd, outwr, relay_error, &con->out);
- if (bev == NULL) {
- relay_close_http(con, 500,
- "failed to allocate output buffer event", 0);
- return;
- }
- evbuffer_free(bev->output);
- bev->output = con->out.output;
- if (bev->output == NULL)
- fatal("relay_connected: invalid output buffer");
-
- con->out.bev = bev;
- bufferevent_settimeout(bev,
- rlay->conf.timeout.tv_sec, rlay->conf.timeout.tv_sec);
- bufferevent_enable(bev, EV_READ|EV_WRITE);
-}
-
-void
-relay_input(struct session *con)
-{
- struct relay *rlay = (struct relay *)con->relay;
- struct protocol *proto = rlay->proto;
- evbuffercb inrd = relay_read;
- evbuffercb inwr = relay_write;
-
- switch (rlay->proto->type) {
- case RELAY_PROTO_HTTP:
- /* Check the client's HTTP request */
- if (!RB_EMPTY(&rlay->proto->request_tree) ||
- proto->lateconnect) {
- inrd = relay_read_http;
- if ((con->in.nodes = calloc(proto->request_nodes,
- sizeof(u_int8_t))) == NULL) {
- relay_close(con, "failed to allocate nodes");
- return;
- }
- }
- break;
- case RELAY_PROTO_TCP:
- /* Use defaults */
- break;
- default:
- fatalx("relay_input: unknown protocol");
- }
-
- /*
- * Client <-> Relay
- */
- con->in.bev = bufferevent_new(con->in.s, inrd, inwr,
- relay_error, &con->in);
- if (con->in.bev == NULL) {
- relay_close(con, "failed to allocate input buffer event");
- return;
- }
-
- /* Initialize the SSL wrapper */
- if ((rlay->conf.flags & F_SSL) && con->in.ssl != NULL)
- relay_ssl_connected(&con->in);
-
- bufferevent_settimeout(con->in.bev,
- rlay->conf.timeout.tv_sec, rlay->conf.timeout.tv_sec);
- bufferevent_enable(con->in.bev, EV_READ|EV_WRITE);
-}
-
-void
-relay_write(struct bufferevent *bev, void *arg)
-{
- struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
- struct session *con = (struct session *)cre->con;
- if (gettimeofday(&con->tv_last, NULL))
- con->done = 1;
- if (con->done)
- relay_close(con, "last write (done)");
-}
-
-void
-relay_dump(struct ctl_relay_event *cre, const void *buf, size_t len)
-{
- /*
- * This function will dump the specified message directly
- * to the underlying session, without waiting for success
- * of non-blocking events etc. This is useful to print an
- * error message before gracefully closing the session.
- */
- if (cre->ssl != NULL)
- (void)SSL_write(cre->ssl, buf, len);
- else
- (void)write(cre->s, buf, len);
-}
-
-void
-relay_read(struct bufferevent *bev, void *arg)
-{
- struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
- struct session *con = (struct session *)cre->con;
- struct evbuffer *src = EVBUFFER_INPUT(bev);
-
- if (gettimeofday(&con->tv_last, NULL))
- goto done;
- if (!EVBUFFER_LENGTH(src))
- return;
- if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
- goto fail;
- if (con->done)
- goto done;
- bufferevent_enable(con->in.bev, EV_READ);
- return;
- done:
- relay_close(con, "last read (done)");
- return;
- fail:
- relay_close(con, strerror(errno));
-}
-
-int
-relay_resolve(struct ctl_relay_event *cre,
- struct protonode *proot, struct protonode *pn)
-{
- struct session *con = (struct session *)cre->con;
- char buf[READ_BUF_SIZE], *ptr;
- int id;
-
- if (pn->mark && (pn->mark != con->mark))
- return (0);
-
- switch (pn->action) {
- case NODE_ACTION_FILTER:
- id = cre->nodes[proot->id];
- if (SIMPLEQ_NEXT(pn, entry) == NULL)
- cre->nodes[proot->id] = 0;
- if (id <= 1)
- return (0);
- break;
- case NODE_ACTION_EXPECT:
- id = cre->nodes[proot->id];
- if (SIMPLEQ_NEXT(pn, entry) == NULL)
- cre->nodes[proot->id] = 0;
- if (id > 1)
- return (0);
- break;
- default:
- if (cre->nodes[pn->id]) {
- cre->nodes[pn->id] = 0;
- return (0);
- }
- break;
- }
- switch (pn->action) {
- case NODE_ACTION_APPEND:
- case NODE_ACTION_CHANGE:
- ptr = pn->value;
- if ((pn->flags & PNFLAG_MACRO) &&
- (ptr = relay_expand_http(cre, pn->value,
- buf, sizeof(buf))) == NULL)
- break;
- if (relay_bufferevent_print(cre->dst, pn->key) == -1 ||
- relay_bufferevent_print(cre->dst, ": ") == -1 ||
- relay_bufferevent_print(cre->dst, ptr) == -1 ||
- relay_bufferevent_print(cre->dst, "\r\n") == -1) {
- relay_close_http(con, 500,
- "failed to modify header", 0);
- return (-1);
- }
- DPRINTF("relay_resolve: add '%s: %s'",
- pn->key, ptr);
- break;
- case NODE_ACTION_EXPECT:
- DPRINTF("relay_resolve: missing '%s: %s'",
- pn->key, pn->value);
- relay_close_http(con, 403, "incomplete request", pn->label);
- return (-1);
- case NODE_ACTION_FILTER:
- DPRINTF("relay_resolve: filtered '%s: %s'",
- pn->key, pn->value);
- relay_close_http(con, 403, "rejecting request", pn->label);
- return (-1);
- default:
- break;
- }
- return (0);
-}
-
-char *
-relay_expand_http(struct ctl_relay_event *cre, char *val, char *buf, size_t len)
-{
- struct session *con = (struct session *)cre->con;
- struct relay *rlay = (struct relay *)con->relay;
- char ibuf[128];
-
- (void)strlcpy(buf, val, len);
-
- if (strstr(val, "$REMOTE_") != NULL) {
- if (strstr(val, "$REMOTE_ADDR") != NULL) {
- if (print_host(&cre->ss, ibuf, sizeof(ibuf)) == NULL)
- return (NULL);
- if (expand_string(buf, len,
- "$REMOTE_ADDR", ibuf) != 0)
- return (NULL);
- }
- if (strstr(val, "$REMOTE_PORT") != NULL) {
- snprintf(ibuf, sizeof(ibuf), "%u", ntohs(cre->port));
- if (expand_string(buf, len,
- "$REMOTE_PORT", ibuf) != 0)
- return (NULL);
- }
- }
- if (strstr(val, "$SERVER_") != NULL) {
- if (strstr(val, "$SERVER_ADDR") != NULL) {
- if (print_host(&rlay->conf.ss,
- ibuf, sizeof(ibuf)) == NULL)
- return (NULL);
- if (expand_string(buf, len,
- "$SERVER_ADDR", ibuf) != 0)
- return (NULL);
- }
- if (strstr(val, "$SERVER_PORT") != NULL) {
- snprintf(ibuf, sizeof(ibuf), "%u",
- ntohs(rlay->conf.port));
- if (expand_string(buf, len,
- "$SERVER_PORT", ibuf) != 0)
- return (NULL);
- }
- }
- if (strstr(val, "$TIMEOUT") != NULL) {
- snprintf(ibuf, sizeof(ibuf), "%lu", rlay->conf.timeout.tv_sec);
- if (expand_string(buf, len, "$TIMEOUT", ibuf) != 0)
- return (NULL);
- }
-
- return (buf);
-}
-
-int
-relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
- struct protonode *pn, struct protonode *pk, int header)
-{
- struct session *con = (struct session *)cre->con;
- char buf[READ_BUF_SIZE], *ptr;
- int ret = PN_DROP, mark = 0;
- struct protonode *next;
-
- /* Check if this action depends on a marked session */
- if (pn->mark != 0)
- mark = pn->mark == con->mark ? 1 : -1;
-
- switch (pn->action) {
- case NODE_ACTION_EXPECT:
- case NODE_ACTION_FILTER:
- case NODE_ACTION_MARK:
- break;
- default:
- if (mark == -1)
- return (PN_PASS);
- break;
- }
-
- switch (pn->action) {
- case NODE_ACTION_APPEND:
- if (!header)
- return (PN_PASS);
- ptr = pn->value;
- if ((pn->flags & PNFLAG_MACRO) &&
- (ptr = relay_expand_http(cre, pn->value,
- buf, sizeof(buf))) == NULL)
- break;
- if (relay_bufferevent_print(cre->dst, pn->key) == -1 ||
- relay_bufferevent_print(cre->dst, ": ") == -1 ||
- relay_bufferevent_print(cre->dst, pk->value) == -1 ||
- relay_bufferevent_print(cre->dst, ", ") == -1 ||
- relay_bufferevent_print(cre->dst, ptr) == -1 ||
- relay_bufferevent_print(cre->dst, "\r\n") == -1)
- goto fail;
- cre->nodes[pn->id] = 1;
- DPRINTF("relay_handle_http: append '%s: %s, %s'",
- pk->key, pk->value, ptr);
- break;
- case NODE_ACTION_CHANGE:
- case NODE_ACTION_REMOVE:
- if (!header)
- return (PN_PASS);
- DPRINTF("relay_handle_http: change/remove '%s: %s'",
- pk->key, pk->value);
- break;
- case NODE_ACTION_EXPECT:
- /*
- * A client may specify the header line for multiple times
- * trying to circumvent the filter.
- */
- if (cre->nodes[proot->id] > 1) {
- relay_close_http(con, 400, "repeated header line", 0);
- return (PN_FAIL);
- }
- /* FALLTHROUGH */
- case NODE_ACTION_FILTER:
- DPRINTF("relay_handle_http: %s '%s: %s'",
- (pn->action == NODE_ACTION_EXPECT) ? "expect" : "filter",
- pn->key, pn->value);
-
- /* Do not drop the entity */
- ret = PN_PASS;
-
- if (mark != -1 &&
- fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0) {
- cre->nodes[proot->id] = 1;
-
- /* Fail instantly */
- if (pn->action == NODE_ACTION_FILTER) {
- relay_close_http(con, 403,
- "rejecting request", pn->label);
- return (PN_FAIL);
- }
- }
- next = SIMPLEQ_NEXT(pn, entry);
- if (next == NULL || next->action != pn->action)
- cre->nodes[proot->id]++;
- break;
- case NODE_ACTION_HASH:
- DPRINTF("relay_handle_http: hash '%s: %s'",
- pn->key, pk->value);
- con->outkey = hash32_str(pk->value, con->outkey);
- ret = PN_PASS;
- break;
- case NODE_ACTION_LOG:
- DPRINTF("relay_handle_http: log '%s: %s'",
- pn->key, pk->value);
- ret = PN_PASS;
- break;
- case NODE_ACTION_MARK:
- DPRINTF("relay_handle_http: mark '%s: %s'",
- pn->key, pk->value);
- if (fnmatch(pn->value, pk->value, FNM_CASEFOLD) == 0)
- con->mark = pn->mark;
- ret = PN_PASS;
- break;
- case NODE_ACTION_NONE:
- return (PN_PASS);
- }
- if (mark != -1 && pn->flags & PNFLAG_LOG) {
- bzero(buf, sizeof(buf));
- if (snprintf(buf, sizeof(buf), " [%s: %s]",
- pk->key, pk->value) == -1 ||
- evbuffer_add(con->log, buf, strlen(buf)) == -1)
- goto fail;
- }
-
- return (ret);
- fail:
- relay_close_http(con, 500, strerror(errno), 0);
- return (PN_FAIL);
-}
-
-void
-relay_read_httpcontent(struct bufferevent *bev, void *arg)
-{
- struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
- struct session *con = (struct session *)cre->con;
- struct evbuffer *src = EVBUFFER_INPUT(bev);
- size_t size;
-
- if (gettimeofday(&con->tv_last, NULL))
- goto done;
- size = EVBUFFER_LENGTH(src);
- DPRINTF("relay_read_httpcontent: size %d, to read %d",
- size, cre->toread);
- if (!size)
- return;
- if (relay_bufferevent_write_buffer(cre->dst, src) == -1)
- goto fail;
- if (size >= cre->toread)
- bev->readcb = relay_read_http;
- cre->toread -= size;
- DPRINTF("relay_read_httpcontent: done, size %d, to read %d",
- size, cre->toread);
- if (con->done)
- goto done;
- if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_httpcontent)
- bev->readcb(bev, arg);
- bufferevent_enable(bev, EV_READ);
- return;
- done:
- relay_close(con, "last http content read");
- return;
- fail:
- relay_close(con, strerror(errno));
-}
-
-void
-relay_read_httpchunks(struct bufferevent *bev, void *arg)
-{
- struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
- struct session *con = (struct session *)cre->con;
- struct evbuffer *src = EVBUFFER_INPUT(bev);
- char *line, *ep;
- long lval;
- size_t size;
-
- if (gettimeofday(&con->tv_last, NULL))
- goto done;
- size = EVBUFFER_LENGTH(src);
- DPRINTF("relay_read_httpchunks: size %d, to read %d",
- size, cre->toread);
- if (!size)
- return;
-
- if (!cre->toread) {
- line = evbuffer_readline(src);
- if (line == NULL) {
- relay_close(con, "invalid chunk");
- return;
- }
-
- /* Read prepended chunk size in hex */
- errno = 0;
- lval = strtol(line, &ep, 16);
- if (line[0] == '\0' || *ep != '\0') {
- free(line);
- relay_close(con, "invalid chunk size");
- return;
- }
- if (errno == ERANGE &&
- (lval == LONG_MAX || lval == LONG_MIN)) {
- free(line);
- relay_close(con, "chunk size out of range");
- return;
- }
- if (relay_bufferevent_print(cre->dst, line) == -1 ||
- relay_bufferevent_print(cre->dst, "\r\n") == -1)
- goto fail;
- free(line);
-
- /* Last chunk is 0 bytes followed by an empty newline */
- if ((cre->toread = lval) == 0) {
- line = evbuffer_readline(src);
- if (line == NULL) {
- relay_close(con, "invalid chunk");
- return;
- }
- free(line);
- if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
- goto fail;
-
- /* Switch to HTTP header mode */
- bev->readcb = relay_read_http;
- }
- } else {
- /* Read chunk data */
- if (size > cre->toread)
- size = cre->toread;
- if (relay_bufferevent_write_chunk(cre->dst, src, size) == -1)
- goto fail;
- cre->toread -= size;
- DPRINTF("relay_read_httpchunks: done, size %d, to read %d",
- size, cre->toread);
-
- if (cre->toread == 0) {
- /* Chunk is terminated by an empty newline */
- line = evbuffer_readline(src);
- if (line == NULL || strlen(line)) {
- if (line != NULL)
- free(line);
- relay_close(con, "invalid chunk");
- return;
- }
- free(line);
- if (relay_bufferevent_print(cre->dst, "\r\n\r\n") == -1)
- goto fail;
- }
- }
-
- if (con->done)
- goto done;
- if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_httpchunks)
- bev->readcb(bev, arg);
- bufferevent_enable(bev, EV_READ);
- return;
-
- done:
- relay_close(con, "last http chunk read (done)");
- return;
- fail:
- relay_close(con, strerror(errno));
-}
-
-void
-relay_read_http(struct bufferevent *bev, void *arg)
-{
- struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
- struct session *con = (struct session *)cre->con;
- struct relay *rlay = (struct relay *)con->relay;
- struct protocol *proto = rlay->proto;
- struct evbuffer *src = EVBUFFER_INPUT(bev);
- struct protonode *pn, pk, *proot, *pnv = NULL, pkv;
- char *line;
- int header = 0, ret, pass = 0;
- const char *errstr;
- size_t size;
-
- if (gettimeofday(&con->tv_last, NULL))
- goto done;
- size = EVBUFFER_LENGTH(src);
- DPRINTF("relay_read_http: size %d, to read %d", size, cre->toread);
- if (!size)
- return;
-
- pk.type = NODE_TYPE_HEADER;
-
- while (!cre->done && (line = evbuffer_readline(src)) != NULL) {
- /*
- * An empty line indicates the end of the request.
- * libevent already stripped the \r\n for us.
- */
- if (!strlen(line)) {
- cre->done = 1;
- free(line);
- break;
- }
- pk.key = line;
-
- /*
- * The first line is the GET/POST/PUT/... request,
- * subsequent lines are HTTP headers.
- */
- if (++cre->line == 1) {
- pk.value = strchr(pk.key, ' ');
- } else
- pk.value = strchr(pk.key, ':');
- if (pk.value == NULL || strlen(pk.value) < 3) {
- if (cre->line == 1) {
- free(line);
- relay_close_http(con, 400, "malformed", 0);
- return;
- }
-
- DPRINTF("relay_read_http: request '%s'", line);
- /* Append line to the output buffer */
- if (relay_bufferevent_print(cre->dst, line) == -1 ||
- relay_bufferevent_print(cre->dst, "\r\n") == -1) {
- free(line);
- goto fail;
- }
- free(line);
- continue;
- }
- if (*pk.value == ':') {
- *pk.value++ = '\0';
- pk.value++;
- header = 1;
- } else {
- *pk.value++ = '\0';
- header = 0;
- }
-
- DPRINTF("relay_read_http: header '%s: %s'", pk.key, pk.value);
-
- /*
- * Identify and handle specific HTTP request methods
- */
- if (cre->line == 1) {
- if (cre->dir == RELAY_DIR_RESPONSE) {
- cre->method = HTTP_METHOD_RESPONSE;
- goto lookup;
- } else if (strcmp("GET", pk.key) == 0)
- cre->method = HTTP_METHOD_GET;
- else if (strcmp("HEAD", pk.key) == 0)
- cre->method = HTTP_METHOD_HEAD;
- else if (strcmp("POST", pk.key) == 0)
- cre->method = HTTP_METHOD_POST;
- else if (strcmp("PUT", pk.key) == 0)
- cre->method = HTTP_METHOD_PUT;
- else if (strcmp("DELETE", pk.key) == 0)
- cre->method = HTTP_METHOD_DELETE;
- else if (strcmp("OPTIONS", pk.key) == 0)
- cre->method = HTTP_METHOD_OPTIONS;
- else if (strcmp("TRACE", pk.key) == 0)
- cre->method = HTTP_METHOD_TRACE;
- else if (strcmp("CONNECT", pk.key) == 0)
- cre->method = HTTP_METHOD_CONNECT;
-
- /*
- * Decode the path and query
- */
- cre->path = strdup(pk.value);
- if (cre->path == NULL) {
- free(line);
- goto fail;
- }
- cre->version = strchr(cre->path, ' ');
- if (cre->version != NULL)
- *cre->version++ = '\0';
- cre->args = strchr(cre->path, '?');
- if (cre->args != NULL)
- *cre->args++ = '\0';
-#ifdef DEBUG
- char buf[BUFSIZ];
- if (snprintf(buf, sizeof(buf), " \"%s\"",
- cre->path) == -1 ||
- evbuffer_add(con->log, buf, strlen(buf)) == -1) {
- free(line);
- goto fail;
- }
-#endif
-
- /*
- * Lookup protocol handlers in the URL path
- */
- if ((proto->flags & F_LOOKUP_PATH) == 0)
- goto lookup;
-
- pkv.key = cre->path;
- pkv.type = NODE_TYPE_PATH;
- pkv.value = cre->args == NULL ? "" : cre->args;
-
- DPRINTF("relay_read_http: "
- "lookup path '%s: %s'", pkv.key, pkv.value);
-
- if ((proot = RB_FIND(proto_tree,
- cre->tree, &pkv)) == NULL)
- goto lookup;
-
- PROTONODE_FOREACH(pnv, proot, entry) {
- ret = relay_handle_http(cre, proot,
- pnv, &pkv, 0);
- if (ret == PN_FAIL)
- goto abort;
- }
- } else if ((cre->method == HTTP_METHOD_POST ||
- cre->method == HTTP_METHOD_PUT ||
- cre->method == HTTP_METHOD_RESPONSE) &&
- strcasecmp("Content-Length", pk.key) == 0) {
- /*
- * Need to read data from the client after the
- * HTTP header.
- * XXX What about non-standard clients not using
- * the carriage return? And some browsers seem to
- * include the line length in the content-length.
- */
- cre->toread = strtonum(pk.value, 1, INT_MAX, &errstr);
- if (errstr) {
- relay_close_http(con, 500, errstr, 0);
- goto abort;
- }
- }
- lookup:
- if (strcasecmp("Transfer-Encoding", pk.key) == 0 &&
- strcasecmp("chunked", pk.value) == 0)
- cre->chunked = 1;
-
- /* Match the HTTP header */
- if ((pn = RB_FIND(proto_tree, cre->tree, &pk)) == NULL)
- goto next;
-
- if (cre->dir == RELAY_DIR_RESPONSE)
- goto handle;
-
- if (pn->flags & PNFLAG_LOOKUP_URL) {
- /*
- * Lookup the URL of type example.com/path?args.
- * Either as a plain string or SHA1/MD5 digest.
- */
- if ((pn->flags & PNFLAG_LOOKUP_DIGEST(0)) &&
- relay_lookup_url(cre, pk.value,
- DIGEST_NONE) == PN_FAIL)
- goto abort;
- if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_SHA1)) &&
- relay_lookup_url(cre, pk.value,
- DIGEST_SHA1) == PN_FAIL)
- goto abort;
- if ((pn->flags & PNFLAG_LOOKUP_DIGEST(DIGEST_MD5)) &&
- relay_lookup_url(cre, pk.value,
- DIGEST_MD5) == PN_FAIL)
- goto abort;
- } else if (pn->flags & PNFLAG_LOOKUP_QUERY) {
- /* Lookup the HTTP query arguments */
- if (relay_lookup_query(cre) == PN_FAIL)
- goto abort;
- } else if (pn->flags & PNFLAG_LOOKUP_COOKIE) {
- /* Lookup the HTTP cookie */
- if (relay_lookup_cookie(cre, pk.value) == PN_FAIL)
- goto abort;
- }
-
- handle:
- pass = 0;
- PROTONODE_FOREACH(pnv, pn, entry) {
- ret = relay_handle_http(cre, pn, pnv, &pk, header);
- if (ret == PN_PASS)
- pass = 1;
- else if (ret == PN_FAIL)
- goto abort;
- }
-
- if (pass) {
- next:
- if (relay_bufferevent_print(cre->dst, pk.key) == -1 ||
- relay_bufferevent_print(cre->dst,
- header ? ": " : " ") == -1 ||
- relay_bufferevent_print(cre->dst, pk.value) == -1 ||
- relay_bufferevent_print(cre->dst, "\r\n") == -1) {
- free(line);
- goto fail;
- }
- }
- free(line);
- }
- if (cre->done) {
- RB_FOREACH(proot, proto_tree, cre->tree) {
- PROTONODE_FOREACH(pn, proot, entry)
- if (relay_resolve(cre, proot, pn) != 0)
- return;
- }
-
- switch (cre->method) {
- case HTTP_METHOD_CONNECT:
- /* Data stream */
- bev->readcb = relay_read;
- break;
- case HTTP_METHOD_POST:
- case HTTP_METHOD_PUT:
- case HTTP_METHOD_RESPONSE:
- /* HTTP request payload */
- if (cre->toread) {
- bev->readcb = relay_read_httpcontent;
- break;
- }
- /* FALLTHROUGH */
- default:
- /* HTTP handler */
- bev->readcb = relay_read_http;
- break;
- }
- if (cre->chunked) {
- /* Chunked transfer encoding */
- cre->toread = 0;
- bev->readcb = relay_read_httpchunks;
- }
-
- /* Write empty newline and switch to relay mode */
- if (relay_bufferevent_print(cre->dst, "\r\n") == -1)
- goto fail;
- cre->line = 0;
- cre->method = 0;
- cre->done = 0;
- cre->chunked = 0;
-
- if (cre->dir == RELAY_DIR_REQUEST &&
- proto->lateconnect && cre->dst->bev == NULL &&
- relay_connect(con) == -1) {
- relay_close_http(con, 502, "session failed", 0);
- return;
- }
- }
- if (con->done)
- goto done;
- if (EVBUFFER_LENGTH(src) && bev->readcb != relay_read_http)
- bev->readcb(bev, arg);
- bufferevent_enable(bev, EV_READ);
- return;
- done:
- relay_close(con, "last http read (done)");
- return;
- fail:
- relay_close_http(con, 500, strerror(errno), 0);
- return;
- abort:
- free(line);
-}
-
-static int
-_relay_lookup_url(struct ctl_relay_event *cre, char *host, char *path,
- char *query, enum digest_type type)
-{
- struct session *con = (struct session *)cre->con;
- struct protonode *proot, *pnv, pkv;
- char *val, *md = NULL;
- int ret = PN_FAIL;
-
- if (asprintf(&val, "%s%s%s%s",
- host, path,
- query == NULL ? "" : "?",
- query == NULL ? "" : query) == -1) {
- relay_close_http(con, 500, "failed to allocate URL", 0);
- return (PN_FAIL);
- }
-
- DPRINTF("_relay_lookup_url: %s", val);
-
- switch (type) {
- case DIGEST_SHA1:
- case DIGEST_MD5:
- if ((md = digeststr(type, val, strlen(val), NULL)) == NULL) {
- relay_close_http(con, 500,
- "failed to allocate digest", 0);
- goto fail;
- }
- pkv.key = md;
- break;
- case DIGEST_NONE:
- pkv.key = val;
- break;
- }
- pkv.type = NODE_TYPE_URL;
- pkv.value = "";
-
- if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL)
- goto done;
-
- PROTONODE_FOREACH(pnv, proot, entry) {
- ret = relay_handle_http(cre, proot, pnv, &pkv, 0);
- if (ret == PN_FAIL)
- goto fail;
- }
-
- done:
- ret = PN_PASS;
- fail:
- if (md != NULL)
- free(md);
- free(val);
- return (ret);
-}
-
-int
-relay_lookup_url(struct ctl_relay_event *cre, const char *str,
- enum digest_type type)
-{
- struct session *con = (struct session *)cre->con;
- int i, j, dots;
- char *hi[RELAY_MAXLOOKUPLEVELS], *p, *pp, *c, ch;
- char ph[MAXHOSTNAMELEN];
- int ret;
-
- if (cre->path == NULL)
- return (PN_PASS);
-
- /*
- * This is an URL lookup algorithm inspired by
- * http://code.google.com/apis/safebrowsing/
- * developers_guide.html#PerformingLookups
- */
-
- DPRINTF("relay_lookup_url: host: '%s', path: '%s', query: '%s'",
- str, cre->path, cre->args == NULL ? "" : cre->args);
-
- if (canonicalize_host(str, ph, sizeof(ph)) == NULL) {
- relay_close_http(con, 400, "invalid host name", 0);
- return (PN_FAIL);
- }
-
- bzero(hi, sizeof(hi));
- for (dots = -1, i = strlen(ph) - 1; i > 0; i--) {
- if (ph[i] == '.' && ++dots)
- hi[dots - 1] = &ph[i + 1];
- if (dots > (RELAY_MAXLOOKUPLEVELS - 2))
- break;
- }
- if (dots == -1)
- dots = 0;
- hi[dots] = ph;
-
- if ((pp = strdup(cre->path)) == NULL) {
- relay_close_http(con, 500, "failed to allocate path", 0);
- return (PN_FAIL);
- }
- for (i = (RELAY_MAXLOOKUPLEVELS - 1); i >= 0; i--) {
- if (hi[i] == NULL)
- continue;
-
- /* 1. complete path with query */
- if (cre->args != NULL)
- if ((ret = _relay_lookup_url(cre, hi[i],
- pp, cre->args, type)) != PN_PASS)
- goto done;
-
- /* 2. complete path without query */
- if ((ret = _relay_lookup_url(cre, hi[i],
- pp, NULL, type)) != PN_PASS)
- goto done;
-
- /* 3. traverse path */
- for (j = 0, p = strchr(pp, '/');
- p != NULL; p = strchr(p, '/'), j++) {
- if (j > (RELAY_MAXLOOKUPLEVELS - 2) || ++p == '\0')
- break;
- c = &pp[p - pp];
- ch = *c;
- *c = '\0';
- if ((ret = _relay_lookup_url(cre, hi[i],
- pp, NULL, type)) != PN_PASS)
- goto done;
- *c = ch;
- }
- }
-
- ret = PN_PASS;
- done:
- free(pp);
- return (ret);
-}
-
-int
-relay_lookup_query(struct ctl_relay_event *cre)
-{
- struct session *con = (struct session *)cre->con;
- struct protonode *proot, *pnv, pkv;
- char *val, *ptr;
- int ret;
-
- if (cre->path == NULL || cre->args == NULL || strlen(cre->args) < 2)
- return (PN_PASS);
- if ((val = strdup(cre->args)) == NULL) {
- relay_close_http(con, 500, "failed to allocate query", 0);
- return (PN_FAIL);
- }
-
- ptr = val;
- while (ptr != NULL && strlen(ptr)) {
- pkv.key = ptr;
- pkv.type = NODE_TYPE_QUERY;
- if ((ptr = strchr(ptr, '&')) != NULL)
- *ptr++ = '\0';
- if ((pkv.value =
- strchr(pkv.key, '=')) == NULL ||
- strlen(pkv.value) < 1)
- continue;
- *pkv.value++ = '\0';
-
- if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL)
- continue;
- PROTONODE_FOREACH(pnv, proot, entry) {
- ret = relay_handle_http(cre, proot,
- pnv, &pkv, 0);
- if (ret == PN_FAIL)
- goto done;
- }
- }
-
- ret = PN_PASS;
- done:
- free(val);
- return (ret);
-}
-
-int
-relay_lookup_cookie(struct ctl_relay_event *cre, const char *str)
-{
- struct session *con = (struct session *)cre->con;
- struct protonode *proot, *pnv, pkv;
- char *val, *ptr;
- int ret;
-
- if ((val = strdup(str)) == NULL) {
- relay_close_http(con, 500, "failed to allocate cookie", 0);
- return (PN_FAIL);
- }
-
- for (ptr = val; ptr != NULL && strlen(ptr);) {
- if (*ptr == ' ')
- *ptr++ = '\0';
- pkv.key = ptr;
- pkv.type = NODE_TYPE_COOKIE;
- if ((ptr = strchr(ptr, ';')) != NULL)
- *ptr++ = '\0';
- /*
- * XXX We do not handle attributes
- * ($Path, $Domain, or $Port)
- */
- if (*pkv.key == '$')
- continue;
-
- if ((pkv.value =
- strchr(pkv.key, '=')) == NULL ||
- strlen(pkv.value) < 1)
- continue;
- *pkv.value++ = '\0';
- if (*pkv.value == '"')
- *pkv.value++ = '\0';
- if (pkv.value[strlen(pkv.value) - 1] == '"')
- pkv.value[strlen(pkv.value) - 1] = '\0';
- if ((proot = RB_FIND(proto_tree, cre->tree, &pkv)) == NULL)
- continue;
- PROTONODE_FOREACH(pnv, proot, entry) {
- ret = relay_handle_http(cre, proot, pnv, &pkv, 0);
- if (ret == PN_FAIL)
- goto done;
- }
- }
-
- ret = PN_PASS;
- done:
- free(val);
- return (ret);
-}
-
-void
-relay_close_http(struct session *con, u_int code, const char *msg,
- u_int16_t labelid)
-{
- struct relay *rlay = (struct relay *)con->relay;
- struct bufferevent *bev = con->in.bev;
- const char *httperr = print_httperror(code), *text = "";
- char *httpmsg;
- time_t t;
- struct tm *lt;
- char tmbuf[32], hbuf[128];
- const char *style, *label = NULL;
-
- /* In some cases this function may be called from generic places */
- if (rlay->proto->type != RELAY_PROTO_HTTP ||
- (rlay->proto->flags & F_RETURN) == 0) {
- relay_close(con, msg);
- return;
- }
-
- if (bev == NULL)
- goto done;
-
- /* Some system information */
- if (print_host(&rlay->conf.ss, hbuf, sizeof(hbuf)) == NULL)
- goto done;
-
- /* RFC 2616 "tolerates" asctime() */
- time(&t);
- lt = localtime(&t);
- tmbuf[0] = '\0';
- if (asctime_r(lt, tmbuf) != NULL)
- tmbuf[strlen(tmbuf) - 1] = '\0'; /* skip final '\n' */
-
- /* Do not send details of the Internal Server Error */
- if (code != 500)
- text = msg;
- if (labelid != 0)
- label = pn_id2name(labelid);
-
- /* A CSS stylesheet allows minimal customization by the user */
- if ((style = rlay->proto->style) == NULL)
- style = "body { background-color: #a00000; color: white; }";
-
- /* Generate simple HTTP+HTML error document */
- if (asprintf(&httpmsg,
- "HTTP/1.x %03d %s\r\n"
- "Date: %s\r\n"
- "Server: %s\r\n"
- "Connection: close\r\n"
- "Content-Type: text/html\r\n"
- "\r\n"
- "<!DOCTYPE HTML PUBLIC "
- "\"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
- "<html>\n"
- "<head>\n"
- "<title>%03d %s</title>\n"
- "<style type=\"text/css\"><!--\n%s\n--></style>\n"
- "</head>\n"
- "<body>\n"
- "<h1>%s</h1>\n"
- "<div id='m'>%s</div>\n"
- "<div id='l'>%s</div>\n"
- "<hr><address>%s at %s port %d</address>\n"
- "</body>\n"
- "</html>\n",
- code, httperr, tmbuf, HOSTSTATED_SERVERNAME,
- code, httperr, style, httperr, text,
- label == NULL ? "" : label,
- HOSTSTATED_SERVERNAME, hbuf, ntohs(rlay->conf.port)) == -1)
- goto done;
-
- /* Dump the message without checking for success */
- relay_dump(&con->in, httpmsg, strlen(httpmsg));
- free(httpmsg);
-
- done:
- if (asprintf(&httpmsg, "%s (%03d %s)", msg, code, httperr) == -1)
- relay_close(con, msg);
- else {
- relay_close(con, httpmsg);
- free(httpmsg);
- }
-}
-
-void
-relay_error(struct bufferevent *bev, short error, void *arg)
-{
- struct ctl_relay_event *cre = (struct ctl_relay_event *)arg;
- struct session *con = (struct session *)cre->con;
- struct evbuffer *dst;
-
- if (error & EVBUFFER_TIMEOUT) {
- relay_close(con, "buffer event timeout");
- return;
- }
- if (error & (EVBUFFER_READ|EVBUFFER_WRITE|EVBUFFER_EOF)) {
- bufferevent_disable(bev, EV_READ|EV_WRITE);
-
- con->done = 1;
- if (cre->dst->bev != NULL) {
- dst = EVBUFFER_OUTPUT(cre->dst->bev);
- if (EVBUFFER_LENGTH(dst))
- return;
- }
-
- relay_close(con, "done");
- return;
- }
- relay_close(con, "buffer event error");
-}
-
-void
-relay_accept(int fd, short sig, void *arg)
-{
- struct relay *rlay = (struct relay *)arg;
- struct protocol *proto = rlay->proto;
- struct session *con = NULL;
- struct ctl_natlook *cnl = NULL;
- socklen_t slen;
- struct timeval tv;
- struct sockaddr_storage ss;
- int s = -1;
-
- slen = sizeof(ss);
- if ((s = accept(fd, (struct sockaddr *)&ss, (socklen_t *)&slen)) == -1)
- return;
-
- if (relay_sessions >= RELAY_MAX_SESSIONS ||
- rlay->conf.flags & F_DISABLE)
- goto err;
-
- if ((con = (struct session *)
- calloc(1, sizeof(struct session))) == NULL)
- goto err;
-
- con->in.s = s;
- con->in.ssl = NULL;
- con->out.s = -1;
- con->out.ssl = NULL;
- con->in.dst = &con->out;
- con->out.dst = &con->in;
- con->in.con = con;
- con->out.con = con;
- con->relay = rlay;
- con->id = ++relay_conid;
- con->relayid = rlay->conf.id;
- con->outkey = rlay->dstkey;
- con->in.tree = &proto->request_tree;
- con->out.tree = &proto->response_tree;
- con->in.dir = RELAY_DIR_REQUEST;
- con->out.dir = RELAY_DIR_RESPONSE;
- con->retry = rlay->conf.dstretry;
- if (gettimeofday(&con->tv_start, NULL))
- goto err;
- bcopy(&con->tv_start, &con->tv_last, sizeof(con->tv_last));
- bcopy(&ss, &con->in.ss, sizeof(con->in.ss));
- con->out.port = rlay->conf.dstport;
- switch (ss.ss_family) {
- case AF_INET:
- con->in.port = ((struct sockaddr_in *)&ss)->sin_port;
- break;
- case AF_INET6:
- con->in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
- break;
- }
-
- relay_sessions++;
- SPLAY_INSERT(session_tree, &rlay->sessions, con);
-
- /* Increment the per-relay session counter */
- rlay->stats[proc_id].last++;
-
- /* Pre-allocate output buffer */
- con->out.output = evbuffer_new();
- if (con->out.output == NULL) {
- relay_close(con, "failed to allocate output buffer");
- return;
- }
-
- /* Pre-allocate log buffer */
- con->log = evbuffer_new();
- if (con->log == NULL) {
- relay_close(con, "failed to allocate log buffer");
- return;
- }
-
- if (rlay->conf.flags & F_NATLOOK) {
- if ((cnl = (struct ctl_natlook *)
- calloc(1, sizeof(struct ctl_natlook))) == NULL) {
- relay_close(con, "failed to allocate nat lookup");
- return;
- }
- }
-
- if (rlay->conf.flags & F_NATLOOK && cnl != NULL) {
- con->cnl = cnl;;
- bzero(cnl, sizeof(*cnl));
- cnl->in = -1;
- cnl->id = con->id;
- cnl->proc = proc_id;
- bcopy(&con->in.ss, &cnl->src, sizeof(cnl->src));
- bcopy(&rlay->conf.ss, &cnl->dst, sizeof(cnl->dst));
- imsg_compose(ibuf_pfe, IMSG_NATLOOK, 0, 0, -1, cnl,
- sizeof(*cnl));
-
- /* Schedule timeout */
- evtimer_set(&con->ev, relay_natlook, con);
- bcopy(&rlay->conf.timeout, &tv, sizeof(tv));
- evtimer_add(&con->ev, &tv);
- return;
- }
-
- relay_session(con);
- return;
- err:
- if (s != -1) {
- close(s);
- if (con != NULL)
- free(con);
- }
-}
-
-u_int32_t
-relay_hash_addr(struct sockaddr_storage *ss, u_int32_t p)
-{
- struct sockaddr_in *sin4;
- struct sockaddr_in6 *sin6;
-
- if (ss->ss_family == AF_INET) {
- sin4 = (struct sockaddr_in *)ss;
- p = hash32_buf(&sin4->sin_addr,
- sizeof(struct in_addr), p);
- } else {
- sin6 = (struct sockaddr_in6 *)ss;
- p = hash32_buf(&sin6->sin6_addr,
- sizeof(struct in6_addr), p);
- }
-
- return (p);
-}
-
-int
-relay_from_table(struct session *con)
-{
- struct relay *rlay = (struct relay *)con->relay;
- struct host *host;
- struct table *table = rlay->dsttable;
- u_int32_t p = con->outkey;
- int idx = 0;
-
- if (rlay->conf.dstcheck && !table->up) {
- log_debug("relay_from_table: no active hosts");
- return (-1);
- }
-
- switch (rlay->conf.dstmode) {
- case RELAY_DSTMODE_ROUNDROBIN:
- if ((int)rlay->dstkey >= rlay->dstnhosts)
- rlay->dstkey = 0;
- idx = (int)rlay->dstkey;
- break;
- case RELAY_DSTMODE_LOADBALANCE:
- p = relay_hash_addr(&con->in.ss, p);
- /* FALLTHROUGH */
- case RELAY_DSTMODE_HASH:
- p = relay_hash_addr(&rlay->conf.ss, p);
- p = hash32_buf(&rlay->conf.port, sizeof(rlay->conf.port), p);
- if ((idx = p % rlay->dstnhosts) >= RELAY_MAXHOSTS)
- return (-1);
- }
- host = rlay->dsthost[idx];
- DPRINTF("relay_from_table: host %s, p 0x%08x, idx %d",
- host->conf.name, p, idx);
- while (host != NULL) {
- DPRINTF("relay_from_table: host %s", host->conf.name);
- if (!rlay->conf.dstcheck || host->up == HOST_UP)
- goto found;
- host = TAILQ_NEXT(host, entry);
- }
- TAILQ_FOREACH(host, &rlay->dsttable->hosts, entry) {
- DPRINTF("relay_from_table: next host %s", host->conf.name);
- if (!rlay->conf.dstcheck || host->up == HOST_UP)
- goto found;
- }
-
- /* Should not happen */
- fatalx("relay_from_table: no active hosts, desynchronized");
-
- found:
- if (rlay->conf.dstmode == RELAY_DSTMODE_ROUNDROBIN)
- rlay->dstkey = host->idx + 1;
- con->retry = host->conf.retry;
- con->out.port = table->conf.port;
- bcopy(&host->conf.ss, &con->out.ss, sizeof(con->out.ss));
-
- return (0);
-}
-
-void
-relay_natlook(int fd, short event, void *arg)
-{
- struct session *con = (struct session *)arg;
- struct relay *rlay = (struct relay *)con->relay;
- struct ctl_natlook *cnl = con->cnl;
-
- if (cnl == NULL)
- fatalx("invalid NAT lookup");
-
- if (con->out.ss.ss_family == AF_UNSPEC && cnl->in == -1 &&
- rlay->conf.dstss.ss_family == AF_UNSPEC && rlay->dsttable == NULL) {
- relay_close(con, "session NAT lookup failed");
- return;
- }
- if (cnl->in != -1) {
- bcopy(&cnl->rdst, &con->out.ss, sizeof(con->out.ss));
- con->out.port = cnl->rdport;
- }
- free(con->cnl);
- con->cnl = NULL;
-
- relay_session(con);
-}
-
-void
-relay_session(struct session *con)
-{
- struct relay *rlay = (struct relay *)con->relay;
- struct ctl_relay_event *in = &con->in, *out = &con->out;
-
- if (bcmp(&rlay->conf.ss, &out->ss, sizeof(out->ss)) == 0 &&
- out->port == rlay->conf.port) {
- log_debug("relay_session: session %d: looping",
- con->id);
- relay_close(con, "session aborted");
- return;
- }
-
- if (rlay->conf.flags & F_UDP) {
- /*
- * Call the UDP protocol-specific handler
- */
- if (rlay->proto->request == NULL)
- fatalx("invalide UDP session");
- if ((*rlay->proto->request)(con) == -1)
- relay_close(con, "session failed");
- return;
- }
-
- if ((rlay->conf.flags & F_SSL) && (in->ssl == NULL)) {
- relay_ssl_transaction(con);
- return;
- }
-
- if (!rlay->proto->lateconnect && relay_connect(con) == -1) {
- relay_close(con, "session failed");
- return;
- }
-
- relay_input(con);
-}
-
-int
-relay_connect(struct session *con)
-{
- struct relay *rlay = (struct relay *)con->relay;
-
- if (gettimeofday(&con->tv_start, NULL))
- return (-1);
-
- if (rlay->dsttable != NULL) {
- if (relay_from_table(con) != 0)
- return (-1);
- } else if (con->out.ss.ss_family == AF_UNSPEC) {
- bcopy(&rlay->conf.dstss, &con->out.ss, sizeof(con->out.ss));
- con->out.port = rlay->conf.dstport;
- }
-
- retry:
- if ((con->out.s = relay_socket_connect(&con->out.ss, con->out.port,
- rlay->proto)) == -1) {
- if (con->retry) {
- con->retry--;
- log_debug("relay_connect: session %d: "
- "forward failed: %s, %s",
- con->id, strerror(errno),
- con->retry ? "next retry" : "last retry");
- goto retry;
- }
- log_debug("relay_connect: session %d: forward failed: %s",
- con->id, strerror(errno));
- return (-1);
- }
-
- if (errno == EINPROGRESS)
- event_again(&con->ev, con->out.s, EV_WRITE|EV_TIMEOUT,
- relay_connected, &con->tv_start, &env->timeout, con);
- else
- relay_connected(con->out.s, EV_WRITE, con);
-
- return (0);
-}
-
-void
-relay_close(struct session *con, const char *msg)
-{
- struct relay *rlay = (struct relay *)con->relay;
- char ibuf[128], obuf[128], *ptr = NULL;
-
- SPLAY_REMOVE(session_tree, &rlay->sessions, con);
-
- event_del(&con->ev);
- if (con->in.bev != NULL)
- bufferevent_disable(con->in.bev, EV_READ|EV_WRITE);
- if (con->out.bev != NULL)
- bufferevent_disable(con->out.bev, EV_READ|EV_WRITE);
-
- if (env->opts & HOSTSTATED_OPT_LOGUPDATE) {
- bzero(&ibuf, sizeof(ibuf));
- bzero(&obuf, sizeof(obuf));
- (void)print_host(&con->in.ss, ibuf, sizeof(ibuf));
- (void)print_host(&con->out.ss, obuf, sizeof(obuf));
- if (EVBUFFER_LENGTH(con->log) &&
- evbuffer_add_printf(con->log, "\r\n") != -1)
- ptr = evbuffer_readline(con->log);
- log_info("relay %s, session %d (%d active), %d, %s -> %s:%d, "
- "%s%s%s", rlay->conf.name, con->id, relay_sessions,
- con->mark, ibuf, obuf, ntohs(con->out.port), msg,
- ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr);
- if (ptr != NULL)
- free(ptr);
- }
-
- if (con->in.bev != NULL)
- bufferevent_free(con->in.bev);
- else if (con->in.output != NULL)
- evbuffer_free(con->in.output);
- if (con->in.ssl != NULL) {
- /* XXX handle non-blocking shutdown */
- if (SSL_shutdown(con->in.ssl) == 0)
- SSL_shutdown(con->in.ssl);
- SSL_free(con->in.ssl);
- }
- if (con->in.s != -1)
- close(con->in.s);
- if (con->in.path != NULL)
- free(con->in.path);
- if (con->in.buf != NULL)
- free(con->in.buf);
- if (con->in.nodes != NULL)
- free(con->in.nodes);
-
- if (con->out.bev != NULL)
- bufferevent_free(con->out.bev);
- else if (con->out.output != NULL)
- evbuffer_free(con->out.output);
- if (con->out.s != -1)
- close(con->out.s);
- if (con->out.path != NULL)
- free(con->out.path);
- if (con->out.buf != NULL)
- free(con->out.buf);
- if (con->out.nodes != NULL)
- free(con->out.nodes);
-
- if (con->log != NULL)
- evbuffer_free(con->log);
-
- if (con->cnl != NULL) {
-#if 0
- imsg_compose(ibuf_pfe, IMSG_KILLSTATES, 0, 0, -1,
- cnl, sizeof(*cnl));
-#endif
- free(con->cnl);
- }
-
- free(con);
- relay_sessions--;
-}
-
-void
-relay_dispatch_pfe(int fd, short event, void *ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
- struct relay *rlay;
- struct session *con;
- struct ctl_natlook cnl;
- struct timeval tv;
- struct host *host;
- struct table *table;
- struct ctl_status st;
- objid_t id;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("relay_dispatch_pfe: imsg_read_error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("relay_dispatch_pfe: msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("relay_dispatch_pfe: unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("relay_dispatch_pfe: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_HOST_DISABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("relay_dispatch_pfe: desynchronized");
- if ((table = table_find(env, host->conf.tableid)) ==
- NULL)
- fatalx("relay_dispatch_pfe: invalid table id");
- if (host->up == HOST_UP)
- table->up--;
- host->flags |= F_DISABLE;
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_HOST_ENABLE:
- memcpy(&id, imsg.data, sizeof(id));
- if ((host = host_find(env, id)) == NULL)
- fatalx("relay_dispatch_pfe: desynchronized");
- host->flags &= ~(F_DISABLE);
- host->up = HOST_UNKNOWN;
- break;
- case IMSG_HOST_STATUS:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(st))
- fatalx("relay_dispatch_pfe: invalid request");
- memcpy(&st, imsg.data, sizeof(st));
- if ((host = host_find(env, st.id)) == NULL)
- fatalx("relay_dispatch_pfe: invalid host id");
- if (host->flags & F_DISABLE)
- break;
- if (host->up == st.up) {
- log_debug("relay_dispatch_pfe: host %d => %d",
- host->conf.id, host->up);
- fatalx("relay_dispatch_pfe: desynchronized");
- }
-
- if ((table = table_find(env, host->conf.tableid))
- == NULL)
- fatalx("relay_dispatch_pfe: invalid table id");
-
- DPRINTF("relay_dispatch_pfe: [%d] state %d for "
- "host %u %s", proc_id, st.up,
- host->conf.id, host->conf.name);
-
- if ((st.up == HOST_UNKNOWN && host->up == HOST_DOWN) ||
- (st.up == HOST_DOWN && host->up == HOST_UNKNOWN)) {
- host->up = st.up;
- break;
- }
- if (st.up == HOST_UP)
- table->up++;
- else
- table->up--;
- host->up = st.up;
- break;
- case IMSG_NATLOOK:
- bcopy(imsg.data, &cnl, sizeof(cnl));
- if ((con = session_find(env, cnl.id)) == NULL ||
- con->cnl == NULL) {
- log_debug("relay_dispatch_pfe: "
- "session expired");
- break;
- }
- bcopy(&cnl, con->cnl, sizeof(*con->cnl));
- evtimer_del(&con->ev);
- evtimer_set(&con->ev, relay_natlook, con);
- bzero(&tv, sizeof(tv));
- evtimer_add(&con->ev, &tv);
- break;
- case IMSG_CTL_SESSION:
- TAILQ_FOREACH(rlay, env->relays, entry)
- SPLAY_FOREACH(con, session_tree,
- &rlay->sessions)
- imsg_compose(ibuf, IMSG_CTL_SESSION,
- 0, 0, -1, con, sizeof(*con));
- imsg_compose(ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
- break;
- default:
- log_debug("relay_dispatch_msg: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-void
-relay_dispatch_parent(int fd, short event, void * ptr)
-{
- struct imsgbuf *ibuf;
- struct imsg imsg;
- ssize_t n;
-
- ibuf = ptr;
- switch (event) {
- case EV_READ:
- if ((n = imsg_read(ibuf)) == -1)
- fatal("relay_dispatch_parent: imsg_read error");
- if (n == 0) {
- /* this pipe is dead, so remove the event handler */
- event_del(&ibuf->ev);
- event_loopexit(NULL);
- return;
- }
- break;
- case EV_WRITE:
- if (msgbuf_write(&ibuf->w) == -1)
- fatal("relay_dispatch_parent: msgbuf_write");
- imsg_event_add(ibuf);
- return;
- default:
- fatalx("relay_dispatch_parent: unknown event");
- }
-
- for (;;) {
- if ((n = imsg_get(ibuf, &imsg)) == -1)
- fatal("relay_dispatch_parent: imsg_read error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- default:
- log_debug("relay_dispatch_parent: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- imsg_event_add(ibuf);
-}
-
-SSL_CTX *
-relay_ssl_ctx_create(struct relay *rlay)
-{
- struct protocol *proto = rlay->proto;
- SSL_CTX *ctx;
-
- ctx = SSL_CTX_new(SSLv23_method());
- if (ctx == NULL)
- goto err;
-
- /* Modify session timeout and cache size*/
- SSL_CTX_set_timeout(ctx, rlay->conf.timeout.tv_sec);
- if (proto->cache < -1) {
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
- } else if (proto->cache >= -1) {
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
- if (proto->cache >= 0)
- SSL_CTX_sess_set_cache_size(ctx, proto->cache);
- }
-
- /* Enable all workarounds and set SSL options */
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
- SSL_CTX_set_options(ctx,
- SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
-
- /* Set the allowed SSL protocols */
- if ((proto->sslflags & SSLFLAG_SSLV2) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
- if ((proto->sslflags & SSLFLAG_SSLV3) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
- if ((proto->sslflags & SSLFLAG_TLSV1) == 0)
- SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
-
- if (!SSL_CTX_set_cipher_list(ctx, proto->sslciphers))
- goto err;
-
- log_debug("relay_ssl_ctx_create: loading certificate");
- if (!ssl_ctx_use_certificate_chain(ctx,
- rlay->ssl_cert, rlay->ssl_cert_len))
- goto err;
-
- log_debug("relay_ssl_ctx_create: loading private key");
- if (!ssl_ctx_use_private_key(ctx, rlay->ssl_key, rlay->ssl_key_len))
- goto err;
- if (!SSL_CTX_check_private_key(ctx))
- goto err;
-
- /* Set session context to the local relay name */
- if (!SSL_CTX_set_session_id_context(ctx, rlay->conf.name,
- strlen(rlay->conf.name)))
- goto err;
-
- return (ctx);
-
- err:
- if (ctx != NULL)
- SSL_CTX_free(ctx);
- ssl_error(rlay->conf.name, "relay_ssl_ctx_create");
- return (NULL);
-}
-
-void
-relay_ssl_transaction(struct session *con)
-{
- struct relay *rlay = (struct relay *)con->relay;
- SSL *ssl;
-
- ssl = SSL_new(rlay->ssl_ctx);
- if (ssl == NULL)
- goto err;
-
- if (!SSL_set_ssl_method(ssl, SSLv23_server_method()))
- goto err;
- if (!SSL_set_fd(ssl, con->in.s))
- goto err;
- SSL_set_accept_state(ssl);
-
- con->in.ssl = ssl;
-
- event_again(&con->ev, con->in.s, EV_TIMEOUT|EV_READ,
- relay_ssl_accept, &con->tv_start, &env->timeout, con);
- return;
-
- err:
- if (ssl != NULL)
- SSL_free(ssl);
- ssl_error(rlay->conf.name, "relay_ssl_transaction");
-}
-
-void
-relay_ssl_accept(int fd, short event, void *arg)
-{
- struct session *con = (struct session *)arg;
- struct relay *rlay = (struct relay *)con->relay;
- int ret;
- int ssl_err;
- int retry_flag;
-
- if (event == EV_TIMEOUT) {
- relay_close(con, "SSL accept timeout");
- return;
- }
-
- retry_flag = ssl_err = 0;
-
- ret = SSL_accept(con->in.ssl);
- if (ret <= 0) {
- ssl_err = SSL_get_error(con->in.ssl, ret);
-
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- case SSL_ERROR_ZERO_RETURN:
- case SSL_ERROR_SYSCALL:
- if (ret == 0) {
- relay_close(con, "closed");
- return;
- }
- /* FALLTHROUGH */
- default:
- ssl_error(rlay->conf.name, "relay_ssl_accept");
- relay_close(con, "SSL accept error");
- return;
- }
- }
-
-
-#ifdef DEBUG
- log_info("relay %s, session %d established (%d active)",
- rlay->conf.name, con->id, relay_sessions);
-#else
- log_debug("relay %s, session %d established (%d active)",
- rlay->conf.name, con->id, relay_sessions);
-#endif
- relay_session(con);
- return;
-
-retry:
- DPRINTF("relay_ssl_accept: session %d: scheduling on %s", con->id,
- (retry_flag == EV_READ) ? "EV_READ" : "EV_WRITE");
- event_again(&con->ev, fd, EV_TIMEOUT|retry_flag, relay_ssl_accept,
- &con->tv_start, &env->timeout, con);
-}
-
-void
-relay_ssl_connected(struct ctl_relay_event *cre)
-{
- /*
- * Hack libevent - we overwrite the internal bufferevent I/O
- * functions to handle the SSL abstraction.
- */
- event_set(&cre->bev->ev_read, cre->s, EV_READ,
- relay_ssl_readcb, cre->bev);
- event_set(&cre->bev->ev_write, cre->s, EV_WRITE,
- relay_ssl_writecb, cre->bev);
-}
-
-void
-relay_ssl_readcb(int fd, short event, void *arg)
-{
- struct bufferevent *bufev = arg;
- struct ctl_relay_event *cre = (struct ctl_relay_event *)bufev->cbarg;
- struct session *con = (struct session *)cre->con;
- struct relay *rlay = (struct relay *)con->relay;
- int ret = 0, ssl_err = 0;
- short what = EVBUFFER_READ;
- size_t len;
- char rbuf[READ_BUF_SIZE];
- int howmuch = READ_BUF_SIZE;
-
- if (event == EV_TIMEOUT) {
- what |= EVBUFFER_TIMEOUT;
- goto err;
- }
-
- if (bufev->wm_read.high != 0)
- howmuch = MIN(sizeof(rbuf), bufev->wm_read.high);
-
- ret = SSL_read(cre->ssl, rbuf, howmuch);
- if (ret <= 0) {
- ssl_err = SSL_get_error(cre->ssl, ret);
-
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- DPRINTF("relay_ssl_readcb: session %d: "
- "want read", con->id);
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- DPRINTF("relay_ssl_readcb: session %d: "
- "want write", con->id);
- goto retry;
- default:
- if (ret == 0)
- what |= EVBUFFER_EOF;
- else {
- ssl_error(rlay->conf.name, "relay_ssl_readcb");
- what |= EVBUFFER_ERROR;
- }
- goto err;
- }
- }
-
- if (evbuffer_add(bufev->input, rbuf, ret) == -1) {
- what |= EVBUFFER_ERROR;
- goto err;
- }
-
- relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
-
- len = EVBUFFER_LENGTH(bufev->input);
- if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
- return;
- if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
- struct evbuffer *buf = bufev->input;
- event_del(&bufev->ev_read);
- evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
- return;
- }
-
- if (bufev->readcb != NULL)
- (*bufev->readcb)(bufev, bufev->cbarg);
- return;
-
- retry:
- relay_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
- return;
-
- err:
- (*bufev->errorcb)(bufev, what, bufev->cbarg);
-}
-
-void
-relay_ssl_writecb(int fd, short event, void *arg)
-{
- struct bufferevent *bufev = arg;
- struct ctl_relay_event *cre = (struct ctl_relay_event *)bufev->cbarg;
- struct session *con = (struct session *)cre->con;
- struct relay *rlay = (struct relay *)con->relay;
- int ret = 0, ssl_err;
- short what = EVBUFFER_WRITE;
-
- if (event == EV_TIMEOUT) {
- what |= EVBUFFER_TIMEOUT;
- goto err;
- }
-
- if (EVBUFFER_LENGTH(bufev->output)) {
- if (cre->buf == NULL) {
- cre->buflen = EVBUFFER_LENGTH(bufev->output);
- if ((cre->buf = malloc(cre->buflen)) == NULL) {
- what |= EVBUFFER_ERROR;
- goto err;
- }
- bcopy(EVBUFFER_DATA(bufev->output),
- cre->buf, cre->buflen);
- }
-
- ret = SSL_write(cre->ssl, cre->buf, cre->buflen);
- if (ret <= 0) {
- ssl_err = SSL_get_error(cre->ssl, ret);
-
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- DPRINTF("relay_ssl_writecb: session %d: "
- "want read", con->id);
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- DPRINTF("relay_ssl_writecb: session %d: "
- "want write", con->id);
- goto retry;
- default:
- if (ret == 0)
- what |= EVBUFFER_EOF;
- else {
- ssl_error(rlay->conf.name,
- "relay_ssl_writecb");
- what |= EVBUFFER_ERROR;
- }
- goto err;
- }
- }
- evbuffer_drain(bufev->output, ret);
- }
- if (cre->buf != NULL) {
- free(cre->buf);
- cre->buf = NULL;
- cre->buflen = 0;
- }
-
- if (EVBUFFER_LENGTH(bufev->output) != 0)
- relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
-
- if (bufev->writecb != NULL &&
- EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
- (*bufev->writecb)(bufev, bufev->cbarg);
- return;
-
- retry:
- if (cre->buflen != 0)
- relay_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
- return;
-
- err:
- if (cre->buf != NULL) {
- free(cre->buf);
- cre->buf = NULL;
- cre->buflen = 0;
- }
- (*bufev->errorcb)(bufev, what, bufev->cbarg);
-}
-
-int
-relay_bufferevent_add(struct event *ev, int timeout)
-{
- struct timeval tv, *ptv = NULL;
-
- if (timeout) {
- timerclear(&tv);
- tv.tv_sec = timeout;
- ptv = &tv;
- }
-
- return (event_add(ev, ptv));
-}
-
-#ifdef notyet
-int
-relay_bufferevent_printf(struct ctl_relay_event *cre, const char *fmt, ...)
-{
- int ret;
- va_list ap;
-
- va_start(ap, fmt);
- ret = evbuffer_add_vprintf(cre->output, fmt, ap);
- va_end(ap);
-
- if (cre->bev != NULL &&
- ret != -1 && EVBUFFER_LENGTH(cre->output) > 0 &&
- (cre->bev->enabled & EV_WRITE))
- bufferevent_enable(cre->bev, EV_WRITE);
-
- return (ret);
-}
-#endif
-
-int
-relay_bufferevent_print(struct ctl_relay_event *cre, char *str)
-{
- if (cre->bev == NULL)
- return (evbuffer_add(cre->output, str, strlen(str)));
- return (bufferevent_write(cre->bev, str, strlen(str)));
-}
-
-int
-relay_bufferevent_write_buffer(struct ctl_relay_event *cre,
- struct evbuffer *buf)
-{
- if (cre->bev == NULL)
- return (evbuffer_add_buffer(cre->output, buf));
- return (bufferevent_write_buffer(cre->bev, buf));
-}
-
-int
-relay_bufferevent_write_chunk(struct ctl_relay_event *cre,
- struct evbuffer *buf, size_t size)
-{
- int ret;
- ret = relay_bufferevent_write(cre, buf->buffer, size);
- if (ret != -1)
- evbuffer_drain(buf, size);
- return (ret);
-}
-
-int
-relay_bufferevent_write(struct ctl_relay_event *cre, void *data, size_t size)
-{
- if (cre->bev == NULL)
- return (evbuffer_add(cre->output, data, size));
- return (bufferevent_write(cre->bev, data, size));
-}
-
-int
-relay_cmp_af(struct sockaddr_storage *a, struct sockaddr_storage *b)
-{
- struct sockaddr_in ia, ib;
- struct sockaddr_in6 ia6, ib6;
-
- switch (a->ss_family) {
- case AF_INET:
- bcopy(a, &ia, sizeof(struct sockaddr_in));
- bcopy(b, &ib, sizeof(struct sockaddr_in));
-
- return (memcmp(&ia.sin_addr, &ib.sin_addr,
- sizeof(ia.sin_addr)) +
- memcmp(&ia.sin_port, &ib.sin_port,
- sizeof(ia.sin_port)));
- break;
- case AF_INET6:
- bcopy(a, &ia6, sizeof(struct sockaddr_in6));
- bcopy(b, &ib6, sizeof(struct sockaddr_in6));
-
- return (memcmp(&ia6.sin6_addr, &ib6.sin6_addr,
- sizeof(ia6.sin6_addr)) +
- memcmp(&ia6.sin6_port, &ib6.sin6_port,
- sizeof(ia6.sin6_port)));
- break;
- default:
- return (-1);
- }
-}
-
-char *
-relay_load_file(const char *name, off_t *len)
-{
- struct stat st;
- off_t size;
- u_int8_t *buf = NULL;
- int fd;
-
- if ((fd = open(name, O_RDONLY)) == -1)
- return (NULL);
- if (fstat(fd, &st) != 0)
- goto fail;
- size = st.st_size;
- if ((buf = (char *)calloc(1, size + 1)) == NULL)
- goto fail;
- if (read(fd, buf, size) != size)
- goto fail;
-
- close(fd);
-
- *len = size + 1;
- return (buf);
-
- fail:
- if (buf != NULL)
- free(buf);
- close(fd);
- return (NULL);
-}
-
-int
-relay_load_certfiles(struct relay *rlay)
-{
- char certfile[PATH_MAX];
- char hbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
-
- if ((rlay->conf.flags & F_SSL) == 0)
- return (0);
-
- if (print_host(&rlay->conf.ss, hbuf, sizeof(hbuf)) == NULL)
- return (-1);
-
- if (snprintf(certfile, sizeof(certfile),
- "/etc/ssl/%s.crt", hbuf) == -1)
- return (-1);
- if ((rlay->ssl_cert = relay_load_file(certfile,
- &rlay->ssl_cert_len)) == NULL)
- return (-1);
- log_debug("relay_load_certfile: using certificate %s", certfile);
-
- if (snprintf(certfile, sizeof(certfile),
- "/etc/ssl/private/%s.key", hbuf) == -1)
- return -1;
- if ((rlay->ssl_key = relay_load_file(certfile,
- &rlay->ssl_key_len)) == NULL)
- return (-1);
- log_debug("relay_load_certfile: using private key %s", certfile);
-
- return (0);
-}
-
-static __inline int
-relay_proto_cmp(struct protonode *a, struct protonode *b)
-{
- int ret;
- ret = strcasecmp(a->key, b->key);
- if (ret == 0)
- ret = (int)a->type - b->type;
- return (ret);
-}
-
-RB_GENERATE(proto_tree, protonode, nodes, relay_proto_cmp);
-
-int
-relay_session_cmp(struct session *a, struct session *b)
-{
- struct relay *rlay = (struct relay *)b->relay;
- struct protocol *proto = rlay->proto;
-
- if (proto != NULL && proto->cmp != NULL)
- return ((*proto->cmp)(a, b));
-
- return ((int)a->id - b->id);
-}
-
-SPLAY_GENERATE(session_tree, session, nodes, relay_session_cmp);
diff --git a/usr.sbin/hoststated/relay_udp.c b/usr.sbin/hoststated/relay_udp.c
deleted file mode 100644
index fce5779c3d4..00000000000
--- a/usr.sbin/hoststated/relay_udp.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/* $OpenBSD: relay_udp.c,v 1.2 2007/11/24 17:07:28 reyk Exp $ */
-
-/*
- * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.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/time.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/tree.h>
-#include <sys/hash.h>
-
-#include <net/if.h>
-#include <netinet/in_systm.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <err.h>
-#include <pwd.h>
-#include <event.h>
-#include <fnmatch.h>
-
-#include <openssl/ssl.h>
-
-#include "hoststated.h"
-
-extern volatile sig_atomic_t relay_sessions;
-extern objid_t relay_conid;
-extern int proc_id;
-extern struct imsgbuf *ibuf_pfe;
-extern int debug;
-
-extern void relay_close(struct session *, const char *);
-extern void relay_natlook(int, short, void *);
-extern void relay_session(struct session *);
-extern int relay_from_table(struct session *);
-extern int relay_socket_af(struct sockaddr_storage *, in_port_t);
-extern int relay_cmp_af(struct sockaddr_storage *,
- struct sockaddr_storage *);
-
-struct hoststated *env = NULL;
-
-int relay_udp_socket(struct sockaddr_storage *, in_port_t,
- struct protocol *);
-void relay_udp_request(struct session *);
-void relay_udp_timeout(int, short, void *);
-
-void relay_dns_log(struct session *, u_int8_t *);
-int relay_dns_validate(struct relay *, struct sockaddr_storage *,
- u_int8_t *, size_t, u_int32_t *);
-int relay_dns_request(struct session *);
-void relay_dns_response(struct session *, u_int8_t *, size_t);
-int relay_dns_cmp(struct session *, struct session *);
-
-void
-relay_udp_privinit(struct hoststated *x_env, struct relay *rlay)
-{
- struct protocol *proto = rlay->proto;
-
- if (env == NULL)
- env = x_env;
-
- if (rlay->conf.flags & F_SSL)
- fatalx("ssl over udp is not supported");
- rlay->conf.flags |= F_UDP;
-
- switch (proto->type) {
- case RELAY_PROTO_DNS:
- proto->validate = relay_dns_validate;
- proto->request = relay_dns_request;
- proto->cmp = relay_dns_cmp;
- break;
- default:
- fatalx("unsupported udp protocol");
- break;
- }
-}
-
-int
-relay_udp_bind(struct sockaddr_storage *ss, in_port_t port,
- struct protocol *proto)
-{
- int s;
-
- if ((s = relay_udp_socket(ss, port, proto)) == -1)
- return (-1);
-
- if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1)
- goto bad;
-
- return (s);
-
- bad:
- close(s);
- return (-1);
-}
-
-int
-relay_udp_socket(struct sockaddr_storage *ss, in_port_t port,
- struct protocol *proto)
-{
- int s = -1, val;
-
- if (relay_socket_af(ss, port) == -1)
- goto bad;
-
- if ((s = socket(ss->ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1)
- goto bad;
-
- /*
- * Socket options
- */
- if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
- goto bad;
- if (proto->tcpflags & TCPFLAG_BUFSIZ) {
- val = proto->tcpbufsiz;
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
- &val, sizeof(val)) == -1)
- goto bad;
- val = proto->tcpbufsiz;
- if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
- &val, sizeof(val)) == -1)
- goto bad;
- }
-
- /*
- * IP options
- */
- if (proto->tcpflags & TCPFLAG_IPTTL) {
- val = (int)proto->tcpipttl;
- if (setsockopt(s, IPPROTO_IP, IP_TTL,
- &val, sizeof(val)) == -1)
- goto bad;
- }
- if (proto->tcpflags & TCPFLAG_IPMINTTL) {
- val = (int)proto->tcpipminttl;
- if (setsockopt(s, IPPROTO_IP, IP_MINTTL,
- &val, sizeof(val)) == -1)
- goto bad;
- }
-
- return (s);
-
- bad:
- if (s != -1)
- close(s);
- return (-1);
-}
-
-void
-relay_udp_server(int fd, short sig, void *arg)
-{
- struct relay *rlay = (struct relay *)arg;
- struct protocol *proto = rlay->proto;
- struct session *con = NULL;
- struct ctl_natlook *cnl = NULL;
- socklen_t slen;
- struct timeval tv;
- struct sockaddr_storage ss;
- u_int8_t buf[READ_BUF_SIZE];
- u_int32_t key = 0;
- ssize_t len;
-
- if (relay_sessions >= RELAY_MAX_SESSIONS ||
- rlay->conf.flags & F_DISABLE)
- return;
-
- slen = sizeof(ss);
- if ((len = recvfrom(fd, buf, sizeof(buf), 0,
- (struct sockaddr*)&ss, &slen)) < 1)
- return;
-
- /* Parse and validate the packet header */
- if (proto->validate != NULL &&
- (*proto->validate)(rlay, &ss, buf, len, &key) != 0)
- return;
-
- if ((con = (struct session *)
- calloc(1, sizeof(struct session))) == NULL)
- return;
-
- con->key = key;
- con->in.s = -1;
- con->out.s = -1;
- con->in.dst = &con->out;
- con->out.dst = &con->in;
- con->in.con = con;
- con->out.con = con;
- con->relay = rlay;
- con->id = ++relay_conid;
- con->outkey = rlay->dstkey;
- con->in.tree = &proto->request_tree;
- con->out.tree = &proto->response_tree;
- con->in.dir = RELAY_DIR_REQUEST;
- con->out.dir = RELAY_DIR_RESPONSE;
- con->retry = rlay->conf.dstretry;
- gettimeofday(&con->tv_start, NULL);
- bcopy(&con->tv_start, &con->tv_last, sizeof(con->tv_last));
- bcopy(&ss, &con->in.ss, sizeof(con->in.ss));
- con->out.port = rlay->conf.dstport;
- switch (ss.ss_family) {
- case AF_INET:
- con->in.port = ((struct sockaddr_in *)&ss)->sin_port;
- break;
- case AF_INET6:
- con->in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
- break;
- }
-
- relay_sessions++;
- SPLAY_INSERT(session_tree, &rlay->sessions, con);
-
- /* Increment the per-relay session counter */
- rlay->stats[proc_id].last++;
-
- /* Pre-allocate output buffer */
- con->out.output = evbuffer_new();
- if (con->out.output == NULL) {
- relay_close(con, "failed to allocate output buffer");
- return;
- }
-
- /* Pre-allocate log buffer */
- con->log = evbuffer_new();
- if (con->log == NULL) {
- relay_close(con, "failed to allocate log buffer");
- return;
- }
-
- if (rlay->conf.flags & F_NATLOOK) {
- if ((cnl = (struct ctl_natlook *)
- calloc(1, sizeof(struct ctl_natlook))) == NULL) {
- relay_close(con, "failed to allocate natlookup");
- return;
- }
- }
-
- /* Save the received data */
- if (evbuffer_add(con->out.output, buf, len) == -1) {
- relay_close(con, "failed to store buffer");
- return;
- }
-
- if (rlay->conf.flags & F_NATLOOK && cnl != NULL) {
- con->cnl = cnl;;
- bzero(cnl, sizeof(*cnl));
- cnl->in = -1;
- cnl->id = con->id;
- cnl->proc = proc_id;
- bcopy(&con->in.ss, &cnl->src, sizeof(cnl->src));
- bcopy(&rlay->conf.ss, &cnl->dst, sizeof(cnl->dst));
- imsg_compose(ibuf_pfe, IMSG_NATLOOK, 0, 0, -1, cnl,
- sizeof(*cnl));
-
- /* Schedule timeout */
- evtimer_set(&con->ev, relay_natlook, con);
- bcopy(&rlay->conf.timeout, &tv, sizeof(tv));
- evtimer_add(&con->ev, &tv);
- return;
- }
-
- relay_session(con);
-}
-
-void
-relay_udp_timeout(int fd, short sig, void *arg)
-{
- struct session *con = (struct session *)arg;
-
- if (sig != EV_TIMEOUT)
- fatalx("invalid timeout event");
-
- relay_close(con, "udp timeout");
-}
-
-/*
- * Domain Name System support
- */
-
-struct relay_dnshdr {
- u_int16_t dns_id;
-
- u_int8_t dns_flags0;
-#define DNS_F0_QR 0x80 /* response flag */
-#define DNS_F0_OPCODE 0x78 /* message type */
-#define DNS_F0_AA 0x04 /* authorative answer */
-#define DNS_F0_TC 0x02 /* truncated message */
-#define DNS_F0_RD 0x01 /* recursion desired */
-
- u_int8_t dns_flags1;
-#define DNS_F1_RA 0x80 /* recursion available */
-#define DNS_F1_RES 0x40 /* reserved */
-#define DNS_F1_AD 0x20 /* authentic data */
-#define DNS_F1_CD 0x10 /* checking disabled */
-#define DNS_F1_RCODE 0x0f /* response code */
-
- u_int16_t dns_qdcount;
- u_int16_t dns_ancount;
- u_int16_t dns_nscount;
- u_int16_t dns_arcount;
-} __packed;
-
-void
-relay_dns_log(struct session *con, u_int8_t *buf)
-{
- struct relay_dnshdr *hdr = (struct relay_dnshdr *)buf;
-
- log_debug("relay_dns_log: session %d: %s id 0x%x "
- "flags 0x%x:0x%x qd %u an %u ns %u ar %u",
- con->id,
- hdr->dns_flags0 & DNS_F0_QR ? "response" : "request",
- ntohs(hdr->dns_id),
- hdr->dns_flags0,
- hdr->dns_flags1,
- ntohs(hdr->dns_qdcount),
- ntohs(hdr->dns_ancount),
- ntohs(hdr->dns_nscount),
- ntohs(hdr->dns_arcount));
-}
-
-int
-relay_dns_validate(struct relay *rlay, struct sockaddr_storage *ss,
- u_int8_t *buf, size_t len, u_int32_t *key)
-{
- struct relay_dnshdr *hdr = (struct relay_dnshdr *)buf;
- struct session *con, lookup;
-
- /* Validate the header length */
- if (len < sizeof(*hdr))
- return (-1);
-
- *key = ntohs(hdr->dns_id);
-
- /*
- * Check if the header has the response flag set, otherwise
- * return 0 to tell the UDP server to create a new session.
- */
- if ((hdr->dns_flags0 & DNS_F0_QR) == 0)
- return (0);
-
- /*
- * Lookup if this response is for a known session and if the
- * remote host matches the original destination of the request.
- */
- lookup.key = *key;
- if ((con = SPLAY_FIND(session_tree,
- &rlay->sessions, &lookup)) != NULL &&
- relay_cmp_af(ss, &con->out.ss) == 0)
- relay_dns_response(con, buf, len);
-
- /*
- * This is not a new session, ignore it in the UDP server.
- */
- return (-1);
-}
-
-int
-relay_dns_request(struct session *con)
-{
- struct relay *rlay = (struct relay *)con->relay;
- u_int8_t *buf = EVBUFFER_DATA(con->out.output);
- size_t len = EVBUFFER_LENGTH(con->out.output);
- struct relay_dnshdr *hdr;
- socklen_t slen;
-
- if (buf == NULL || len < 1)
- return (-1);
- if (debug)
- relay_dns_log(con, buf);
-
- if (gettimeofday(&con->tv_start, NULL))
- return (-1);
-
- if (rlay->dsttable != NULL) {
- if (relay_from_table(con) != 0)
- return (-1);
- } else if (con->out.ss.ss_family == AF_UNSPEC) {
- bcopy(&rlay->conf.dstss, &con->out.ss, sizeof(con->out.ss));
- con->out.port = rlay->conf.dstport;
- }
-
- if (relay_socket_af(&con->out.ss, con->out.port) == -1)
- return (-1);
- slen = con->out.ss.ss_len;
-
- /*
- * Replace the DNS request Id with a random Id.
- */
- hdr = (struct relay_dnshdr *)buf;
- con->outkey = con->key;
- con->key = arc4random() & 0xffff;
- hdr->dns_id = htons(con->key);
-
- retry:
- if (sendto(rlay->s, buf, len, 0,
- (struct sockaddr *)&con->out.ss, slen) == -1) {
- if (con->retry) {
- con->retry--;
- log_debug("relay_dns_request: session %d: "
- "forward failed: %s, %s",
- con->id, strerror(errno),
- con->retry ? "next retry" : "last retry");
- goto retry;
- }
- log_debug("relay_dns_request: session %d: forward failed: %s",
- con->id, strerror(errno));
- return (-1);
- }
-
- event_again(&con->ev, con->out.s, EV_TIMEOUT,
- relay_udp_timeout, &con->tv_start, &env->timeout, con);
-
- return (0);
-}
-
-void
-relay_dns_response(struct session *con, u_int8_t *buf, size_t len)
-{
- struct relay *rlay = (struct relay *)con->relay;
- struct relay_dnshdr *hdr;
- socklen_t slen;
-
- if (debug)
- relay_dns_log(con, buf);
-
- /*
- * Replace the random DNS request Id with the original Id
- */
- hdr = (struct relay_dnshdr *)buf;
- hdr->dns_id = htons(con->outkey);
-
- slen = con->out.ss.ss_len;
- if (sendto(rlay->s, buf, len, 0,
- (struct sockaddr *)&con->in.ss, slen) == -1) {
- relay_close(con, "response failed");
- return;
- }
-
- relay_close(con, "session closed");
-}
-
-int
-relay_dns_cmp(struct session *a, struct session *b)
-{
- return (memcmp(&a->key, &b->key, sizeof(a->key)));
-}
diff --git a/usr.sbin/hoststated/ssl.c b/usr.sbin/hoststated/ssl.c
deleted file mode 100644
index 3d572bd5bbc..00000000000
--- a/usr.sbin/hoststated/ssl.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* $OpenBSD: ssl.c,v 1.12 2007/12/05 23:02:05 reyk Exp $ */
-
-/*
- * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.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/param.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-
-#include <limits.h>
-#include <event.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/engine.h>
-
-#include "hoststated.h"
-
-void ssl_read(int, short, void *);
-void ssl_write(int, short, void *);
-void ssl_connect(int, short, void *);
-void ssl_cleanup(struct ctl_tcp_event *);
-
-void
-ssl_read(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int ret;
- int ssl_err;
- int retry_flag;
- char rbuf[SMALL_READ_BUF_SIZE];
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- ssl_cleanup(cte);
- hce_notify_done(cte->host, "ssl_read: timeout");
- return;
- }
-
- bzero(rbuf, sizeof(rbuf));
- ssl_err = 0;
- retry_flag = EV_READ;
-
- ret = SSL_read(cte->ssl, rbuf, sizeof(rbuf));
- if (ret <= 0) {
- ssl_err = SSL_get_error(cte->ssl, ret);
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- case SSL_ERROR_ZERO_RETURN: /* FALLTHROUGH */
- case SSL_ERROR_SYSCALL:
- if (ret == 0) {
- cte->host->up = HOST_DOWN;
- (void)cte->validate_close(cte);
- ssl_cleanup(cte);
- if (cte->host->up == HOST_UP)
- hce_notify_done(cte->host,
- "ssl_read: check succeeded");
- else
- hce_notify_done(cte->host,
- "ssl_read: check failed");
- return;
- }
- /* FALLTHROUGH */
- default:
- cte->host->up = HOST_DOWN;
- ssl_error(cte->host->conf.name, "cannot read");
- ssl_cleanup(cte);
- hce_notify_done(cte->host, "ssl_read: SSL error");
- break;
- }
- return;
- }
- if (buf_add(cte->buf, rbuf, ret) == -1)
- fatal("ssl_read: buf_add error");
- if (cte->validate_read != NULL) {
- if (cte->validate_read(cte) != 0)
- goto retry;
-
- ssl_cleanup(cte);
- if (cte->host->up == HOST_UP)
- hce_notify_done(cte->host, "ssl_read: check succeeded");
- else
- hce_notify_done(cte->host, "ssl_read: check failed");
- return;
- }
-
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_read,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-}
-
-void
-ssl_write(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int len;
- int ret;
- int ssl_err;
- int retry_flag;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- ssl_cleanup(cte);
- hce_notify_done(cte->host, "ssl_write: timeout");
- return;
- }
-
- len = strlen(cte->table->sendbuf);
- retry_flag = EV_WRITE;
-
- ret = SSL_write(cte->ssl, cte->table->sendbuf, len);
- if (ret <= 0) {
- ssl_err = SSL_get_error(cte->ssl, ret);
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- default:
- cte->host->up = HOST_DOWN;
- ssl_error(cte->host->conf.name, "cannot write");
- ssl_cleanup(cte);
- hce_notify_done(cte->host, "ssl_write: SSL error");
- return;
- }
- }
- if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
- fatalx("ssl_write: cannot create dynamic buffer");
-
- event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, ssl_read,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_write,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-void
-ssl_connect(int s, short event, void *arg)
-{
- struct ctl_tcp_event *cte = arg;
- int ret;
- int ssl_err;
- int retry_flag;
-
- if (event == EV_TIMEOUT) {
- cte->host->up = HOST_DOWN;
- hce_notify_done(cte->host, "ssl_connect: timeout");
- ssl_cleanup(cte);
- return;
- }
-
- retry_flag = ssl_err = 0;
-
- ret = SSL_connect(cte->ssl);
- if (ret <= 0) {
- ssl_err = SSL_get_error(cte->ssl, ret);
- switch (ssl_err) {
- case SSL_ERROR_WANT_READ:
- retry_flag = EV_READ;
- goto retry;
- case SSL_ERROR_WANT_WRITE:
- retry_flag = EV_WRITE;
- goto retry;
- default:
- cte->host->up = HOST_DOWN;
- ssl_error(cte->host->conf.name, "cannot connect");
- hce_notify_done(cte->host, "ssl_connect: SSL error");
- ssl_cleanup(cte);
- return;
- }
- }
-
- if (cte->table->conf.check == CHECK_TCP) {
- cte->host->up = HOST_UP;
- hce_notify_done(cte->host, "ssl_connect: connect successful");
- ssl_cleanup(cte);
- return;
- }
- if (cte->table->sendbuf != NULL) {
- event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, ssl_write,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
- }
-
- if ((cte->buf = buf_dynamic(SMALL_READ_BUF_SIZE, UINT_MAX)) == NULL)
- fatalx("ssl_connect: cannot create dynamic buffer");
- event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_READ, ssl_read,
- &cte->tv_start, &cte->table->conf.timeout, cte);
- return;
-
-retry:
- event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_connect,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-void
-ssl_cleanup(struct ctl_tcp_event *cte)
-{
- close(cte->s);
- if (cte->ssl != NULL)
- SSL_free(cte->ssl);
- if (cte->buf != NULL)
- buf_free(cte->buf);
-}
-
-void
-ssl_error(const char *where, const char *what)
-{
- unsigned long code;
- char errbuf[128];
- extern int debug;
-
- if (!debug)
- return;
- for (; (code = ERR_get_error()) != 0 ;) {
- ERR_error_string_n(code, errbuf, sizeof(errbuf));
- log_debug("SSL library error: %s: %s: %s", where, what, errbuf);
- }
-}
-
-void
-ssl_init(struct hoststated *env)
-{
- SSL_library_init();
- SSL_load_error_strings();
-
- /* Init hardware crypto engines. */
- ENGINE_load_builtin_engines();
- ENGINE_register_all_complete();
-}
-
-void
-ssl_transaction(struct ctl_tcp_event *cte)
-{
- cte->ssl = SSL_new(cte->table->ssl_ctx);
- if (cte->ssl == NULL) {
- ssl_error(cte->host->conf.name, "cannot create object");
- fatal("cannot create SSL object");
- }
-
- if (SSL_set_fd(cte->ssl, cte->s) == 0) {
- cte->host->up = HOST_UNKNOWN;
- ssl_error(cte->host->conf.name, "cannot set fd");
- ssl_cleanup(cte);
- hce_notify_done(cte->host,
- "ssl_transaction: cannot set SSL fd");
- return;
- }
- SSL_set_connect_state(cte->ssl);
-
- event_again(&cte->ev, cte->s, EV_TIMEOUT|EV_WRITE, ssl_connect,
- &cte->tv_start, &cte->table->conf.timeout, cte);
-}
-
-SSL_CTX *
-ssl_ctx_create(struct hoststated *env)
-{
- SSL_CTX *ctx;
-
- ctx = SSL_CTX_new(SSLv23_client_method());
- if (ctx == NULL) {
- ssl_error("ssl_ctx_create", "cannot create context");
- fatal("could not create SSL context");
- }
- return (ctx);
-}
diff --git a/usr.sbin/hoststated/ssl_privsep.c b/usr.sbin/hoststated/ssl_privsep.c
deleted file mode 100644
index ed01d55db5a..00000000000
--- a/usr.sbin/hoststated/ssl_privsep.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* $OpenBSD: ssl_privsep.c,v 1.6 2007/11/24 17:07:28 reyk Exp $ */
-
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-/*
- * SSL operations needed when running in a privilege separated environment.
- * Adapted from openssl's ssl_rsa.c by Pierre-Yves Ritschard .
- */
-
-#include <unistd.h>
-#include <stdio.h>
-
-#include <openssl/err.h>
-#include <openssl/bio.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-#include <openssl/ssl.h>
-
-int ssl_ctx_use_private_key(SSL_CTX *, char *, off_t);
-int ssl_ctx_use_certificate_chain(SSL_CTX *, char *, off_t);
-
-int
-ssl_ctx_use_private_key(SSL_CTX *ctx, char *buf, off_t len)
-{
- int ret;
- BIO *in;
- EVP_PKEY *pkey;
-
- ret = 0;
-
- if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_BUF_LIB);
- return 0;
- }
-
- pkey = PEM_read_bio_PrivateKey(in, NULL,
- ctx->default_passwd_callback,
- ctx->default_passwd_callback_userdata);
-
- if (pkey == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE, ERR_R_PEM_LIB);
- goto end;
- }
- ret = SSL_CTX_use_PrivateKey(ctx, pkey);
- EVP_PKEY_free(pkey);
-end:
- if (in != NULL)
- BIO_free(in);
- return ret;
-}
-
-
-int
-ssl_ctx_use_certificate_chain(SSL_CTX *ctx, char *buf, off_t len)
-{
- int ret;
- BIO *in;
- X509 *x;
- X509 *ca;
- unsigned long err;
-
- ret = 0;
- x = ca = NULL;
-
- if ((in = BIO_new_mem_buf(buf, len)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_BUF_LIB);
- goto end;
- }
-
- if ((x = PEM_read_bio_X509(in, NULL,
- ctx->default_passwd_callback,
- ctx->default_passwd_callback_userdata)) == NULL) {
- SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
- goto end;
- }
-
- if (!SSL_CTX_use_certificate(ctx, x) || ERR_peek_error() != 0)
- goto end;
-
- /* If we could set up our certificate, now proceed to
- * the CA certificates.
- */
-
- if (ctx->extra_certs != NULL) {
- sk_X509_pop_free(ctx->extra_certs, X509_free);
- ctx->extra_certs = NULL;
- }
-
- while ((ca = PEM_read_bio_X509(in, NULL,
- ctx->default_passwd_callback,
- ctx->default_passwd_callback_userdata)) != NULL) {
-
- if (!SSL_CTX_add_extra_chain_cert(ctx, ca))
- goto end;
- }
-
- err = ERR_peek_last_error();
- if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
- ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
- ERR_clear_error();
- else
- goto end;
-
- ret = 1;
-end:
- if (ca != NULL)
- X509_free(ca);
- if (x != NULL)
- X509_free(x);
- if (in != NULL)
- BIO_free(in);
- return (ret);
-}