summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/relayd/relay_udp.c77
-rw-r--r--usr.sbin/relayd/relayd.h4
2 files changed, 59 insertions, 22 deletions
diff --git a/usr.sbin/relayd/relay_udp.c b/usr.sbin/relayd/relay_udp.c
index f52c041257f..91083706f34 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.11 2008/05/08 02:27:58 reyk Exp $ */
+/* $OpenBSD: relay_udp.c,v 1.12 2008/07/09 10:50:34 reyk Exp $ */
/*
* Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -61,10 +61,12 @@ void relay_udp_request(struct session *);
void relay_udp_timeout(int, short, void *);
void relay_dns_log(struct session *, u_int8_t *);
-void *relay_dns_validate(struct relay *, struct sockaddr_storage *,
+void *relay_dns_validate(struct session *,
+ 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);
+void relay_udp_response(int, short, void *);
+void relay_dns_result(struct session *, u_int8_t *, size_t);
int relay_dns_cmp(struct session *, struct session *);
void
@@ -163,6 +165,37 @@ relay_udp_socket(struct sockaddr_storage *ss, in_port_t port,
}
void
+relay_udp_response(int fd, short sig, void *arg)
+{
+ struct session *con = (struct session *)arg;
+ struct relay *rlay = con->se_relay;
+ struct protocol *proto = rlay->rl_proto;
+ struct sockaddr_storage ss;
+ u_int8_t buf[READ_BUF_SIZE];
+ ssize_t len;
+ socklen_t slen;
+
+ if (sig == EV_TIMEOUT) {
+ relay_udp_timeout(fd, sig, arg);
+ return;
+ }
+
+ if (relay_sessions >= RELAY_MAX_SESSIONS ||
+ rlay->rl_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)(con, rlay, &ss, buf, len) == NULL)
+ return;
+}
+
+void
relay_udp_server(int fd, short sig, void *arg)
{
struct relay *rlay = (struct relay *)arg;
@@ -185,9 +218,8 @@ relay_udp_server(int fd, short sig, void *arg)
(struct sockaddr*)&ss, &slen)) < 1)
return;
- /* Parse and validate the packet header */
if (proto->validate != NULL &&
- (priv = (*proto->validate)(rlay, &ss, buf, len)) == NULL)
+ (priv = (*proto->validate)(NULL, rlay, &ss, buf, len)) == NULL)
return;
if ((con = (struct session *)
@@ -346,11 +378,11 @@ relay_dns_log(struct session *con, u_int8_t *buf)
}
void *
-relay_dns_validate(struct relay *rlay, struct sockaddr_storage *ss,
- u_int8_t *buf, size_t len)
+relay_dns_validate(struct session *con, struct relay *rlay,
+ struct sockaddr_storage *ss, u_int8_t *buf, size_t len)
{
struct relay_dnshdr *hdr = (struct relay_dnshdr *)buf;
- struct session *con, lookup;
+ struct session lookup;
u_int16_t key;
struct relay_dns_priv *priv, lpriv;
@@ -377,12 +409,16 @@ relay_dns_validate(struct relay *rlay, struct sockaddr_storage *ss,
* Lookup if this response is for a known session and if the
* remote host matches the original destination of the request.
*/
- lpriv.dp_inkey = key;
- lookup.se_priv = &lpriv;
- if ((con = SPLAY_FIND(session_tree,
- &rlay->rl_sessions, &lookup)) != NULL && con->se_priv != NULL &&
- relay_cmp_af(ss, &con->se_out.ss) == 0)
- relay_dns_response(con, buf, len);
+ if (con == NULL) {
+ lpriv.dp_inkey = key;
+ lookup.se_priv = &lpriv;
+ if ((con = SPLAY_FIND(session_tree,
+ &rlay->rl_sessions, &lookup)) != NULL &&
+ con->se_priv != NULL &&
+ relay_cmp_af(ss, &con->se_out.ss) == 0)
+ relay_dns_result(con, buf, len);
+ } else
+ relay_dns_result(con, buf, len);
/*
* This is not a new session, ignore it in the UDP server.
@@ -416,7 +452,8 @@ relay_dns_request(struct session *con)
con->se_out.port = rlay->rl_conf.dstport;
}
- if (relay_socket_af(&con->se_out.ss, con->se_out.port) == -1)
+ if ((con->se_out.s = relay_udp_socket(&con->se_out.ss,
+ con->se_out.port, rlay->rl_proto)) == -1)
return (-1);
slen = con->se_out.ss.ss_len;
@@ -424,7 +461,7 @@ relay_dns_request(struct session *con)
hdr->dns_id = htons(priv->dp_inkey);
retry:
- if (sendto(rlay->rl_s, buf, len, 0,
+ if (sendto(con->se_out.s, buf, len, 0,
(struct sockaddr *)&con->se_out.ss, slen) == -1) {
if (con->se_retry) {
con->se_retry--;
@@ -439,14 +476,14 @@ relay_dns_request(struct session *con)
return (-1);
}
- event_again(&con->se_ev, con->se_out.s, EV_TIMEOUT,
- relay_udp_timeout, &con->se_tv_start, &env->sc_timeout, con);
+ event_again(&con->se_ev, con->se_out.s, EV_TIMEOUT|EV_READ,
+ relay_udp_response, &con->se_tv_start, &env->sc_timeout, con);
return (0);
}
void
-relay_dns_response(struct session *con, u_int8_t *buf, size_t len)
+relay_dns_result(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;
@@ -454,7 +491,7 @@ relay_dns_response(struct session *con, u_int8_t *buf, size_t len)
socklen_t slen;
if (priv == NULL)
- fatalx("relay_dns_response: response to invalid session");
+ fatalx("relay_dns_result: response to invalid session");
if (debug)
relay_dns_log(con, buf);
diff --git a/usr.sbin/relayd/relayd.h b/usr.sbin/relayd/relayd.h
index c30812f05d2..432f4606204 100644
--- a/usr.sbin/relayd/relayd.h
+++ b/usr.sbin/relayd/relayd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: relayd.h,v 1.103 2008/06/11 18:21:20 reyk Exp $ */
+/* $OpenBSD: relayd.h,v 1.104 2008/07/09 10:50:34 reyk Exp $ */
/*
* Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -558,7 +558,7 @@ struct protocol {
struct proto_tree response_tree;
int (*cmp)(struct session *, struct session *);
- void *(*validate)(struct relay *,
+ void *(*validate)(struct session *, struct relay *,
struct sockaddr_storage *,
u_int8_t *, size_t);
int (*request)(struct session *);