diff options
Diffstat (limited to 'usr.sbin/relayd/relayd.c')
-rw-r--r-- | usr.sbin/relayd/relayd.c | 123 |
1 files changed, 122 insertions, 1 deletions
diff --git a/usr.sbin/relayd/relayd.c b/usr.sbin/relayd/relayd.c index b903c393819..570ad2a13aa 100644 --- a/usr.sbin/relayd/relayd.c +++ b/usr.sbin/relayd/relayd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: relayd.c,v 1.70 2008/02/11 10:42:50 reyk Exp $ */ +/* $OpenBSD: relayd.c,v 1.71 2008/02/13 11:02:37 reyk Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -1012,3 +1012,124 @@ canonicalize_host(const char *host, char *name, size_t len) errno = EINVAL; return (NULL); } + +struct protonode * +protonode_header(enum direction dir, struct protocol *proto, + struct protonode *pk) +{ + struct protonode *pn; + struct proto_tree *tree; + + if (dir == RELAY_DIR_RESPONSE) + tree = &proto->response_tree; + else + tree = &proto->request_tree; + + pn = RB_FIND(proto_tree, tree, pk); + if (pn != NULL) + return (pn); + if ((pn = (struct protonode *)calloc(1, sizeof(*pn))) == NULL) { + log_warn("out of memory"); + return (NULL); + } + pn->key = strdup(pk->key); + if (pn->key == NULL) { + log_warn("out of memory"); + return (NULL); + } + pn->value = NULL; + pn->action = NODE_ACTION_NONE; + pn->type = pk->type; + SIMPLEQ_INIT(&pn->head); + if (dir == RELAY_DIR_RESPONSE) + pn->id = + proto->response_nodes++; + else + pn->id = proto->request_nodes++; + if (pn->id == INT_MAX) { + log_warnx("too many protocol " + "nodes defined"); + return (NULL); + } + RB_INSERT(proto_tree, tree, pn); + return (pn); +} + +int +protonode_add(enum direction dir, struct protocol *proto, + struct protonode *node) +{ + struct protonode *pn, *proot, pk; + struct proto_tree *tree; + + if (dir == RELAY_DIR_RESPONSE) + tree = &proto->response_tree; + else + tree = &proto->request_tree; + + if ((pn = calloc(1, sizeof (*pn))) == NULL) { + log_warn("out of memory"); + return (-1); + } + bcopy(node, pn, sizeof(*pn)); + pn->key = node->key; + pn->value = node->value; + pn->type = node->type; + pn->label = node->label; + SIMPLEQ_INIT(&pn->head); + if (dir == RELAY_DIR_RESPONSE) + pn->id = proto->response_nodes++; + else + pn->id = proto->request_nodes++; + pn->flags = node->flags; + if (pn->id == INT_MAX) { + log_warnx("too many protocol nodes defined"); + free(pn); + return (-1); + } + 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 = protonode_header(dir, proto, &pk); + if (pn == NULL) + return (-1); + 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; + } + } + + return (0); +} |