summaryrefslogtreecommitdiff
path: root/usr.sbin/relayd
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2008-05-08 02:27:59 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2008-05-08 02:27:59 +0000
commit4704fc6bbd2a784c0b2d7c7dfc6908cf5d3037a6 (patch)
tree633fae97ec332f132b065def17fa6846d302d4f1 /usr.sbin/relayd
parente583009078bed3a510608f33a7e9b9239be7eb58 (diff)
move the session keys used by dns in a protocol-specific private ptr.
Diffstat (limited to 'usr.sbin/relayd')
-rw-r--r--usr.sbin/relayd/relay.c10
-rw-r--r--usr.sbin/relayd/relay_udp.c69
-rw-r--r--usr.sbin/relayd/relayd.h10
3 files changed, 59 insertions, 30 deletions
diff --git a/usr.sbin/relayd/relay.c b/usr.sbin/relayd/relay.c
index edb66a83fda..a51ed7ab813 100644
--- a/usr.sbin/relayd/relay.c
+++ b/usr.sbin/relayd/relay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay.c,v 1.88 2008/05/05 12:33:55 pyr Exp $ */
+/* $OpenBSD: relay.c,v 1.89 2008/05/08 02:27:58 reyk Exp $ */
/*
* Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -1085,7 +1085,7 @@ relay_handle_http(struct ctl_relay_event *cre, struct protonode *proot,
case NODE_ACTION_HASH:
DPRINTF("relay_handle_http: hash '%s: %s'",
pn->key, pk->value);
- con->se_outkey = hash32_str(pk->value, con->se_outkey);
+ con->se_hashkey = hash32_str(pk->value, con->se_hashkey);
ret = PN_PASS;
break;
case NODE_ACTION_LOG:
@@ -1902,7 +1902,7 @@ relay_accept(int fd, short sig, void *arg)
con->se_relay = rlay;
con->se_id = ++relay_conid;
con->se_relayid = rlay->rl_conf.id;
- con->se_outkey = rlay->rl_dstkey;
+ con->se_hashkey = rlay->rl_dstkey;
con->se_in.tree = &proto->request_tree;
con->se_out.tree = &proto->response_tree;
con->se_in.dir = RELAY_DIR_REQUEST;
@@ -2003,7 +2003,7 @@ relay_from_table(struct session *con)
struct relay *rlay = (struct relay *)con->se_relay;
struct host *host;
struct table *table = rlay->rl_dsttable;
- u_int32_t p = con->se_outkey;
+ u_int32_t p = con->se_hashkey;
int idx = 0;
if (table->conf.check && !table->up) {
@@ -2188,6 +2188,8 @@ relay_close(struct session *con, const char *msg)
free(ptr);
}
+ if (con->se_priv != NULL)
+ free(con->se_priv);
if (con->se_in.bev != NULL)
bufferevent_free(con->se_in.bev);
else if (con->se_in.output != NULL)
diff --git a/usr.sbin/relayd/relay_udp.c b/usr.sbin/relayd/relay_udp.c
index a9f22f017de..f52c041257f 100644
--- a/usr.sbin/relayd/relay_udp.c
+++ b/usr.sbin/relayd/relay_udp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: relay_udp.c,v 1.10 2008/03/03 16:43:42 reyk Exp $ */
+/* $OpenBSD: relay_udp.c,v 1.11 2008/05/08 02:27:58 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -61,8 +61,8 @@ 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 *);
+void *relay_dns_validate(struct relay *, struct sockaddr_storage *,
+ u_int8_t *, size_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 *);
@@ -173,7 +173,7 @@ relay_udp_server(int fd, short sig, void *arg)
struct timeval tv;
struct sockaddr_storage ss;
u_int8_t buf[READ_BUF_SIZE];
- u_int32_t key = 0;
+ void *priv = NULL;
ssize_t len;
if (relay_sessions >= RELAY_MAX_SESSIONS ||
@@ -187,17 +187,19 @@ relay_udp_server(int fd, short sig, void *arg)
/* Parse and validate the packet header */
if (proto->validate != NULL &&
- (*proto->validate)(rlay, &ss, buf, len, &key) != 0)
+ (priv = (*proto->validate)(rlay, &ss, buf, len)) == NULL)
return;
if ((con = (struct session *)
- calloc(1, sizeof(struct session))) == NULL)
+ calloc(1, sizeof(struct session))) == NULL) {
+ free(priv);
return;
+ }
/*
* Replace the DNS request Id with a random Id.
*/
- con->se_key = arc4random() & 0xffff;
+ con->se_priv = priv;
con->se_in.s = -1;
con->se_out.s = -1;
con->se_in.dst = &con->se_out;
@@ -205,8 +207,8 @@ relay_udp_server(int fd, short sig, void *arg)
con->se_in.con = con;
con->se_out.con = con;
con->se_relay = rlay;
+ con->se_hashkey = rlay->rl_dstkey;
con->se_id = ++relay_conid;
- con->se_outkey = key;
con->se_in.tree = &proto->request_tree;
con->se_out.tree = &proto->response_tree;
con->se_in.dir = RELAY_DIR_REQUEST;
@@ -297,6 +299,11 @@ relay_udp_timeout(int fd, short sig, void *arg)
* Domain Name System support
*/
+struct relay_dns_priv {
+ u_int16_t dp_inkey;
+ u_int16_t dp_outkey;
+};
+
struct relay_dnshdr {
u_int16_t dns_id;
@@ -338,52 +345,62 @@ relay_dns_log(struct session *con, u_int8_t *buf)
ntohs(hdr->dns_arcount));
}
-int
+void *
relay_dns_validate(struct relay *rlay, struct sockaddr_storage *ss,
- u_int8_t *buf, size_t len, u_int32_t *key)
+ u_int8_t *buf, size_t len)
{
struct relay_dnshdr *hdr = (struct relay_dnshdr *)buf;
struct session *con, lookup;
+ u_int16_t key;
+ struct relay_dns_priv *priv, lpriv;
/* Validate the header length */
if (len < sizeof(*hdr))
- return (-1);
+ return (NULL);
- *key = ntohs(hdr->dns_id);
+ 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);
+ if ((hdr->dns_flags0 & DNS_F0_QR) == 0) {
+ priv = malloc(sizeof(struct relay_dns_priv));
+ if (priv == NULL)
+ return (NULL);
+ priv->dp_inkey = arc4random() & 0xffff;
+ priv->dp_outkey = key;
+ return ((void *)priv);
+ }
/*
* Lookup if this response is for a known session and if the
* remote host matches the original destination of the request.
*/
- lookup.se_key = *key;
+ lpriv.dp_inkey = key;
+ lookup.se_priv = &lpriv;
if ((con = SPLAY_FIND(session_tree,
- &rlay->rl_sessions, &lookup)) != NULL &&
+ &rlay->rl_sessions, &lookup)) != NULL && con->se_priv != NULL &&
relay_cmp_af(ss, &con->se_out.ss) == 0)
relay_dns_response(con, buf, len);
/*
* This is not a new session, ignore it in the UDP server.
*/
- return (-1);
+ return (NULL);
}
int
relay_dns_request(struct session *con)
{
struct relay *rlay = (struct relay *)con->se_relay;
+ struct relay_dns_priv *priv = (struct relay_dns_priv *)con->se_priv;
u_int8_t *buf = EVBUFFER_DATA(con->se_out.output);
size_t len = EVBUFFER_LENGTH(con->se_out.output);
struct relay_dnshdr *hdr;
socklen_t slen;
- if (buf == NULL || len < 1)
+ if (buf == NULL || priv == NULL || len < 1)
return (-1);
if (debug)
relay_dns_log(con, buf);
@@ -404,7 +421,7 @@ relay_dns_request(struct session *con)
slen = con->se_out.ss.ss_len;
hdr = (struct relay_dnshdr *)buf;
- hdr->dns_id = htons(con->se_key);
+ hdr->dns_id = htons(priv->dp_inkey);
retry:
if (sendto(rlay->rl_s, buf, len, 0,
@@ -432,9 +449,13 @@ void
relay_dns_response(struct session *con, u_int8_t *buf, size_t len)
{
struct relay *rlay = (struct relay *)con->se_relay;
+ struct relay_dns_priv *priv = (struct relay_dns_priv *)con->se_priv;
struct relay_dnshdr *hdr;
socklen_t slen;
+ if (priv == NULL)
+ fatalx("relay_dns_response: response to invalid session");
+
if (debug)
relay_dns_log(con, buf);
@@ -442,7 +463,7 @@ relay_dns_response(struct session *con, u_int8_t *buf, size_t len)
* Replace the random DNS request Id with the original Id
*/
hdr = (struct relay_dnshdr *)buf;
- hdr->dns_id = htons(con->se_outkey);
+ hdr->dns_id = htons(priv->dp_outkey);
slen = con->se_out.ss.ss_len;
if (sendto(rlay->rl_s, buf, len, 0,
@@ -457,5 +478,11 @@ relay_dns_response(struct session *con, u_int8_t *buf, size_t len)
int
relay_dns_cmp(struct session *a, struct session *b)
{
- return (memcmp(&a->se_key, &b->se_key, sizeof(a->se_key)));
+ struct relay_dns_priv *ap = (struct relay_dns_priv *)a->se_priv;
+ struct relay_dns_priv *bp = (struct relay_dns_priv *)b->se_priv;
+
+ if (ap == NULL || bp == NULL)
+ fatalx("relay_dns_cmp: invalid session");
+
+ return (memcmp(&ap->dp_inkey, &bp->dp_inkey, sizeof(u_int16_t)));
}
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index e6cd963a3bf..bfe368e4ec2 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.101 2008/05/07 01:49:29 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.102 2008/05/08 02:27:58 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -421,11 +421,11 @@ TAILQ_HEAD(rdrlist, rdr);
struct relay;
struct session {
objid_t se_id;
- u_int32_t se_key;
objid_t se_relayid;
struct ctl_relay_event se_in;
struct ctl_relay_event se_out;
- u_int32_t se_outkey;
+ void *se_priv;
+ u_int32_t se_hashkey;
struct event se_ev;
struct timeval se_timeout;
struct timeval se_tv_start;
@@ -541,9 +541,9 @@ struct protocol {
struct proto_tree response_tree;
int (*cmp)(struct session *, struct session *);
- int (*validate)(struct relay *,
+ void *(*validate)(struct relay *,
struct sockaddr_storage *,
- u_int8_t *, size_t, u_int32_t *);
+ u_int8_t *, size_t);
int (*request)(struct session *);
TAILQ_ENTRY(protocol) entry;