summaryrefslogtreecommitdiff
path: root/usr.sbin/hoststated/relay.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/hoststated/relay.c')
-rw-r--r--usr.sbin/hoststated/relay.c75
1 files changed, 61 insertions, 14 deletions
diff --git a/usr.sbin/hoststated/relay.c b/usr.sbin/hoststated/relay.c
index ee7926ba114..d407e8d1047 100644
--- a/usr.sbin/hoststated/relay.c
+++ b/usr.sbin/hoststated/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.13 2007/02/26 16:10:24 reyk Exp $ */
+/* $OpenBSD: relay.c,v 1.14 2007/02/27 13:38:58 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Reyk Floeter <reyk@openbsd.org>
@@ -273,6 +273,8 @@ relay_protodebug(struct relay *rlay)
{
struct protocol *proto = rlay->proto;
struct protonode *pn;
+ struct proto_tree *tree;
+ const char *name;
fprintf(stderr, "protocol %d: name %s\n", proto->id, proto->name);
fprintf(stderr, "\tflags: 0x%04x\n", proto->flags);
@@ -287,9 +289,15 @@ relay_protodebug(struct relay *rlay)
fprintf(stderr, "http\n");
break;
}
- RB_FOREACH(pn, proto_tree, &proto->tree) {
+
+ name = "request";
+ tree = &proto->request_tree;
+ show:
+ RB_FOREACH(pn, proto_tree, tree) {
fprintf(stderr, "\t\t");
+ fprintf(stderr, "%s ", name);
+
switch (pn->type) {
case NODE_TYPE_HEADER:
break;
@@ -334,6 +342,11 @@ relay_protodebug(struct relay *rlay)
}
fprintf(stderr, "\n");
}
+ if (tree == &proto->request_tree) {
+ name = "response";
+ tree = &proto->response_tree;
+ goto show;
+ }
}
void
@@ -597,6 +610,7 @@ 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;
@@ -609,6 +623,25 @@ relay_connected(int fd, short sig, void *arg)
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(con, "failed to allocate nodes");
+ return;
+ }
+ }
+ break;
+ case RELAY_PROTO_TCP:
+ /* Use defaults */
+ break;
+ default:
+ fatalx("relay_input: unknown protocol");
+ }
+
/*
* Relay <-> Server
*/
@@ -639,11 +672,14 @@ relay_input(struct session *con)
switch (rlay->proto->type) {
case RELAY_PROTO_HTTP:
/* Check the client's HTTP request */
- inrd = relay_read_http;
- if ((con->in.nodes = calloc(proto->nodecount,
- sizeof(u_int8_t))) == NULL) {
- relay_close(con, "failed to allocate node buffer");
- return;
+ 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:
@@ -1038,7 +1074,9 @@ relay_read_http(struct bufferevent *bev, void *arg)
* Identify and handle specific HTTP request methods
*/
if (cre->line == 1) {
- if (strcmp("GET", pk.key) == 0)
+ if (cre->dir == RELAY_DIR_RESPONSE)
+ cre->method = HTTP_METHOD_RESPONSE;
+ else if (strcmp("GET", pk.key) == 0)
cre->method = HTTP_METHOD_GET;
else if (strcmp("HEAD", pk.key) == 0)
cre->method = HTTP_METHOD_HEAD;
@@ -1055,7 +1093,8 @@ relay_read_http(struct bufferevent *bev, void *arg)
else if (strcmp("CONNECT", pk.key) == 0)
cre->method = HTTP_METHOD_CONNECT;
} else if ((cre->method == HTTP_METHOD_POST ||
- cre->method == HTTP_METHOD_PUT) &&
+ 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
@@ -1077,11 +1116,12 @@ relay_read_http(struct bufferevent *bev, void *arg)
cre->chunked = 1;
/* Match the HTTP header */
- if ((pn = RB_FIND(proto_tree, &proto->tree, &pk)) == NULL)
+ if ((pn = RB_FIND(proto_tree, cre->tree, &pk)) == NULL)
goto next;
/* Decode the URL */
- if (pn->flags & PNFLAG_LOOKUP_URL) {
+ if (pn->flags & PNFLAG_LOOKUP_URL &&
+ cre->dir == RELAY_DIR_REQUEST) {
url = strdup(pk.value);
if (url == NULL)
goto next;
@@ -1105,7 +1145,7 @@ relay_read_http(struct bufferevent *bev, void *arg)
continue;
*pkv.value++ = '\0';
if ((pnv = RB_FIND(proto_tree,
- &proto->tree, &pkv)) == NULL)
+ cre->tree, &pkv)) == NULL)
continue;
ret = relay_handle_http(cre, pnv, &pkv, 0);
if (ret == 1)
@@ -1140,7 +1180,7 @@ next:
continue;
}
if (cre->done) {
- RB_FOREACH(pn, proto_tree, &proto->tree) {
+ RB_FOREACH(pn, proto_tree, cre->tree) {
if (cre->nodes[pn->id]) {
cre->nodes[pn->id] = 0;
continue;
@@ -1194,6 +1234,7 @@ next:
break;
case HTTP_METHOD_POST:
case HTTP_METHOD_PUT:
+ case HTTP_METHOD_RESPONSE:
/* HTTP request payload */
if (cre->toread) {
bev->readcb = relay_read_httpcontent;
@@ -1220,7 +1261,8 @@ next:
cre->done = 0;
cre->chunked = 0;
- if (proto->lateconnect && cre->dst->bev == NULL &&
+ if (cre->dir == RELAY_DIR_REQUEST &&
+ proto->lateconnect && cre->dst->bev == NULL &&
relay_connect(con) == -1) {
relay_close(con, "session failed");
return;
@@ -1284,6 +1326,7 @@ 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;
@@ -1313,6 +1356,10 @@ relay_accept(int fd, short sig, void *arg)
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;
if (gettimeofday(&con->tv_start, NULL))
goto err;
bcopy(&con->tv_start, &con->tv_last, sizeof(con->tv_last));