summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd/relayd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/relayd/relayd.c')
-rw-r--r--usr.sbin/relayd/relayd.c123
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);
+}