Blame


1 6b5c4000 2026-03-02 rsadowski /* $OpenBSD: relay_udp.c,v 1.52 2026/03/02 19:28:01 rsadowski Exp $ */
2 7ba7514d 2007-09-10 reyk
3 7ba7514d 2007-09-10 reyk /*
4 dc2f787f 2014-06-25 reyk * Copyright (c) 2007 - 2013 Reyk Floeter <reyk@openbsd.org>
5 7ba7514d 2007-09-10 reyk *
6 7ba7514d 2007-09-10 reyk * Permission to use, copy, modify, and distribute this software for any
7 7ba7514d 2007-09-10 reyk * purpose with or without fee is hereby granted, provided that the above
8 7ba7514d 2007-09-10 reyk * copyright notice and this permission notice appear in all copies.
9 7ba7514d 2007-09-10 reyk *
10 7ba7514d 2007-09-10 reyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 7ba7514d 2007-09-10 reyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 7ba7514d 2007-09-10 reyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 7ba7514d 2007-09-10 reyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 7ba7514d 2007-09-10 reyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 7ba7514d 2007-09-10 reyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 7ba7514d 2007-09-10 reyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 7ba7514d 2007-09-10 reyk */
18 7ba7514d 2007-09-10 reyk
19 7ba7514d 2007-09-10 reyk #include <sys/types.h>
20 e1f9d231 2007-11-24 reyk #include <sys/queue.h>
21 7ba7514d 2007-09-10 reyk #include <sys/time.h>
22 7ba7514d 2007-09-10 reyk #include <sys/socket.h>
23 7ba7514d 2007-09-10 reyk #include <sys/tree.h>
24 7ba7514d 2007-09-10 reyk
25 7ba7514d 2007-09-10 reyk #include <netinet/in.h>
26 d93c36af 2015-01-22 reyk #include <arpa/inet.h>
27 7ba7514d 2007-09-10 reyk
28 2f6ec04d 2015-01-16 deraadt #include <signal.h>
29 7ba7514d 2007-09-10 reyk #include <errno.h>
30 7ba7514d 2007-09-10 reyk #include <fcntl.h>
31 7ba7514d 2007-09-10 reyk #include <stdlib.h>
32 7ba7514d 2007-09-10 reyk #include <string.h>
33 7ba7514d 2007-09-10 reyk #include <unistd.h>
34 7ba7514d 2007-09-10 reyk #include <stdio.h>
35 7ba7514d 2007-09-10 reyk #include <event.h>
36 d93c36af 2015-01-22 reyk #include <imsg.h>
37 7ba7514d 2007-09-10 reyk
38 6d0767ae 2007-12-07 reyk #include "relayd.h"
39 6b5c4000 2026-03-02 rsadowski #include "log.h"
40 7ba7514d 2007-09-10 reyk
41 7ba7514d 2007-09-10 reyk extern volatile sig_atomic_t relay_sessions;
42 7ba7514d 2007-09-10 reyk extern objid_t relay_conid;
43 7ba7514d 2007-09-10 reyk
44 69fde657 2014-07-09 reyk static struct relayd *env = NULL;
45 c0255773 2008-07-09 reyk struct shuffle relay_shuffle;
46 7ba7514d 2007-09-10 reyk
47 7ba7514d 2007-09-10 reyk int relay_udp_socket(struct sockaddr_storage *, in_port_t,
48 7ba7514d 2007-09-10 reyk struct protocol *);
49 7ba7514d 2007-09-10 reyk void relay_udp_timeout(int, short, void *);
50 7ba7514d 2007-09-10 reyk
51 61afd4d6 2009-08-07 reyk void relay_dns_log(struct rsession *, u_int8_t *, size_t);
52 61afd4d6 2009-08-07 reyk void *relay_dns_validate(struct rsession *,
53 4068a26b 2008-07-09 reyk struct relay *, struct sockaddr_storage *,
54 6e9314ae 2008-05-08 reyk u_int8_t *, size_t);
55 61afd4d6 2009-08-07 reyk int relay_dns_request(struct rsession *);
56 4068a26b 2008-07-09 reyk void relay_udp_response(int, short, void *);
57 61afd4d6 2009-08-07 reyk void relay_dns_result(struct rsession *, u_int8_t *, size_t);
58 61afd4d6 2009-08-07 reyk int relay_dns_cmp(struct rsession *, struct rsession *);
59 7ba7514d 2007-09-10 reyk
60 7ba7514d 2007-09-10 reyk void
61 a2811280 2017-07-04 benno relay_udp_privinit(struct relay *rlay)
62 7ba7514d 2007-09-10 reyk {
63 096ff28b 2014-12-12 reyk if (rlay->rl_conf.flags & F_TLS)
64 096ff28b 2014-12-12 reyk fatalx("tls over udp is not supported");
65 146643ba 2008-01-31 reyk rlay->rl_conf.flags |= F_UDP;
66 c0255773 2008-07-09 reyk }
67 7ba7514d 2007-09-10 reyk
68 c0255773 2008-07-09 reyk void
69 a2811280 2017-07-04 benno relay_udp_init(struct relayd *x_env, struct relay *rlay)
70 c0255773 2008-07-09 reyk {
71 c0255773 2008-07-09 reyk struct protocol *proto = rlay->rl_proto;
72 c0255773 2008-07-09 reyk
73 a2811280 2017-07-04 benno if (env == NULL)
74 a2811280 2017-07-04 benno env = x_env;
75 a2811280 2017-07-04 benno
76 7ba7514d 2007-09-10 reyk switch (proto->type) {
77 7ba7514d 2007-09-10 reyk case RELAY_PROTO_DNS:
78 7ba7514d 2007-09-10 reyk proto->validate = relay_dns_validate;
79 7ba7514d 2007-09-10 reyk proto->request = relay_dns_request;
80 7ba7514d 2007-09-10 reyk proto->cmp = relay_dns_cmp;
81 c0255773 2008-07-09 reyk shuffle_init(&relay_shuffle);
82 7ba7514d 2007-09-10 reyk break;
83 7ba7514d 2007-09-10 reyk default:
84 7ba7514d 2007-09-10 reyk fatalx("unsupported udp protocol");
85 7ba7514d 2007-09-10 reyk break;
86 7ba7514d 2007-09-10 reyk }
87 7ba7514d 2007-09-10 reyk }
88 7ba7514d 2007-09-10 reyk
89 7ba7514d 2007-09-10 reyk int
90 7ba7514d 2007-09-10 reyk relay_udp_bind(struct sockaddr_storage *ss, in_port_t port,
91 7ba7514d 2007-09-10 reyk struct protocol *proto)
92 7ba7514d 2007-09-10 reyk {
93 7ba7514d 2007-09-10 reyk int s;
94 7ba7514d 2007-09-10 reyk
95 7ba7514d 2007-09-10 reyk if ((s = relay_udp_socket(ss, port, proto)) == -1)
96 7ba7514d 2007-09-10 reyk return (-1);
97 7ba7514d 2007-09-10 reyk
98 7ba7514d 2007-09-10 reyk if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1)
99 7ba7514d 2007-09-10 reyk goto bad;
100 7ba7514d 2007-09-10 reyk
101 7ba7514d 2007-09-10 reyk return (s);
102 7ba7514d 2007-09-10 reyk
103 7ba7514d 2007-09-10 reyk bad:
104 7ba7514d 2007-09-10 reyk close(s);
105 7ba7514d 2007-09-10 reyk return (-1);
106 7ba7514d 2007-09-10 reyk }
107 7ba7514d 2007-09-10 reyk
108 7ba7514d 2007-09-10 reyk int
109 7ba7514d 2007-09-10 reyk relay_udp_socket(struct sockaddr_storage *ss, in_port_t port,
110 7ba7514d 2007-09-10 reyk struct protocol *proto)
111 7ba7514d 2007-09-10 reyk {
112 7ba7514d 2007-09-10 reyk int s = -1, val;
113 7ba7514d 2007-09-10 reyk
114 7ba7514d 2007-09-10 reyk if (relay_socket_af(ss, port) == -1)
115 7ba7514d 2007-09-10 reyk goto bad;
116 7ba7514d 2007-09-10 reyk
117 24dcf092 2015-11-28 reyk if ((s = socket(ss->ss_family, SOCK_DGRAM | SOCK_NONBLOCK,
118 24dcf092 2015-11-28 reyk IPPROTO_UDP)) == -1)
119 7ba7514d 2007-09-10 reyk goto bad;
120 7ba7514d 2007-09-10 reyk
121 7ba7514d 2007-09-10 reyk /*
122 7ba7514d 2007-09-10 reyk * Socket options
123 7ba7514d 2007-09-10 reyk */
124 7ba7514d 2007-09-10 reyk if (proto->tcpflags & TCPFLAG_BUFSIZ) {
125 7ba7514d 2007-09-10 reyk val = proto->tcpbufsiz;
126 7ba7514d 2007-09-10 reyk if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
127 7ba7514d 2007-09-10 reyk &val, sizeof(val)) == -1)
128 7ba7514d 2007-09-10 reyk goto bad;
129 7ba7514d 2007-09-10 reyk val = proto->tcpbufsiz;
130 7ba7514d 2007-09-10 reyk if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
131 7ba7514d 2007-09-10 reyk &val, sizeof(val)) == -1)
132 7ba7514d 2007-09-10 reyk goto bad;
133 7ba7514d 2007-09-10 reyk }
134 7ba7514d 2007-09-10 reyk
135 7ba7514d 2007-09-10 reyk /*
136 7ba7514d 2007-09-10 reyk * IP options
137 7ba7514d 2007-09-10 reyk */
138 7ba7514d 2007-09-10 reyk if (proto->tcpflags & TCPFLAG_IPTTL) {
139 7ba7514d 2007-09-10 reyk val = (int)proto->tcpipttl;
140 99857652 2016-11-10 jca switch (ss->ss_family) {
141 99857652 2016-11-10 jca case AF_INET:
142 99857652 2016-11-10 jca if (setsockopt(s, IPPROTO_IP, IP_TTL,
143 99857652 2016-11-10 jca &val, sizeof(val)) == -1)
144 99857652 2016-11-10 jca goto bad;
145 99857652 2016-11-10 jca break;
146 99857652 2016-11-10 jca case AF_INET6:
147 99857652 2016-11-10 jca if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
148 99857652 2016-11-10 jca &val, sizeof(val)) == -1)
149 99857652 2016-11-10 jca goto bad;
150 99857652 2016-11-10 jca break;
151 99857652 2016-11-10 jca }
152 7ba7514d 2007-09-10 reyk }
153 7ba7514d 2007-09-10 reyk if (proto->tcpflags & TCPFLAG_IPMINTTL) {
154 7ba7514d 2007-09-10 reyk val = (int)proto->tcpipminttl;
155 99857652 2016-11-10 jca switch (ss->ss_family) {
156 99857652 2016-11-10 jca case AF_INET:
157 99857652 2016-11-10 jca if (setsockopt(s, IPPROTO_IP, IP_MINTTL,
158 99857652 2016-11-10 jca &val, sizeof(val)) == -1)
159 99857652 2016-11-10 jca goto bad;
160 99857652 2016-11-10 jca break;
161 99857652 2016-11-10 jca case AF_INET6:
162 99857652 2016-11-10 jca if (setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT,
163 99857652 2016-11-10 jca &val, sizeof(val)) == -1)
164 99857652 2016-11-10 jca goto bad;
165 99857652 2016-11-10 jca break;
166 99857652 2016-11-10 jca }
167 7ba7514d 2007-09-10 reyk }
168 7ba7514d 2007-09-10 reyk
169 7ba7514d 2007-09-10 reyk return (s);
170 7ba7514d 2007-09-10 reyk
171 7ba7514d 2007-09-10 reyk bad:
172 7ba7514d 2007-09-10 reyk if (s != -1)
173 7ba7514d 2007-09-10 reyk close(s);
174 7ba7514d 2007-09-10 reyk return (-1);
175 7ba7514d 2007-09-10 reyk }
176 7ba7514d 2007-09-10 reyk
177 7ba7514d 2007-09-10 reyk void
178 4068a26b 2008-07-09 reyk relay_udp_response(int fd, short sig, void *arg)
179 4068a26b 2008-07-09 reyk {
180 6e65a975 2013-01-17 bluhm struct rsession *con = arg;
181 4068a26b 2008-07-09 reyk struct relay *rlay = con->se_relay;
182 4068a26b 2008-07-09 reyk struct protocol *proto = rlay->rl_proto;
183 c7b7c92e 2008-07-09 reyk void *priv = NULL;
184 4068a26b 2008-07-09 reyk struct sockaddr_storage ss;
185 fb0e4fa0 2010-05-26 nicm u_int8_t buf[IBUF_READ_SIZE];
186 4068a26b 2008-07-09 reyk ssize_t len;
187 4068a26b 2008-07-09 reyk socklen_t slen;
188 4068a26b 2008-07-09 reyk
189 4068a26b 2008-07-09 reyk if (sig == EV_TIMEOUT) {
190 4068a26b 2008-07-09 reyk relay_udp_timeout(fd, sig, arg);
191 4068a26b 2008-07-09 reyk return;
192 4068a26b 2008-07-09 reyk }
193 4068a26b 2008-07-09 reyk
194 62110500 2018-04-18 claudio if (rlay->rl_conf.flags & F_DISABLE)
195 4068a26b 2008-07-09 reyk return;
196 4068a26b 2008-07-09 reyk
197 4068a26b 2008-07-09 reyk slen = sizeof(ss);
198 4068a26b 2008-07-09 reyk if ((len = recvfrom(fd, buf, sizeof(buf), 0,
199 4068a26b 2008-07-09 reyk (struct sockaddr*)&ss, &slen)) < 1)
200 4068a26b 2008-07-09 reyk return;
201 4068a26b 2008-07-09 reyk
202 4068a26b 2008-07-09 reyk /* Parse and validate the packet header */
203 4068a26b 2008-07-09 reyk if (proto->validate != NULL &&
204 c7b7c92e 2008-07-09 reyk (priv = (*proto->validate)(con, rlay, &ss, buf, len)) == NULL)
205 4068a26b 2008-07-09 reyk return;
206 c7b7c92e 2008-07-09 reyk
207 37ed6014 2018-08-06 benno relay_close(con, "unknown response", 1);
208 ba24b6a0 2015-12-07 mmcc free(priv);
209 4068a26b 2008-07-09 reyk }
210 4068a26b 2008-07-09 reyk
211 4068a26b 2008-07-09 reyk void
212 7ba7514d 2007-09-10 reyk relay_udp_server(int fd, short sig, void *arg)
213 7ba7514d 2007-09-10 reyk {
214 b14526d5 2016-09-02 reyk struct privsep *ps = env->sc_ps;
215 6e65a975 2013-01-17 bluhm struct relay *rlay = arg;
216 146643ba 2008-01-31 reyk struct protocol *proto = rlay->rl_proto;
217 61afd4d6 2009-08-07 reyk struct rsession *con = NULL;
218 7ba7514d 2007-09-10 reyk struct ctl_natlook *cnl = NULL;
219 7ba7514d 2007-09-10 reyk socklen_t slen;
220 7ba7514d 2007-09-10 reyk struct timeval tv;
221 7ba7514d 2007-09-10 reyk struct sockaddr_storage ss;
222 fb0e4fa0 2010-05-26 nicm u_int8_t buf[IBUF_READ_SIZE];
223 6e9314ae 2008-05-08 reyk void *priv = NULL;
224 7ba7514d 2007-09-10 reyk ssize_t len;
225 7ba7514d 2007-09-10 reyk
226 58721a38 2014-08-08 reyk event_add(&rlay->rl_ev, NULL);
227 58721a38 2014-08-08 reyk
228 62110500 2018-04-18 claudio if (rlay->rl_conf.flags & F_DISABLE)
229 7ba7514d 2007-09-10 reyk return;
230 7ba7514d 2007-09-10 reyk
231 7ba7514d 2007-09-10 reyk slen = sizeof(ss);
232 7ba7514d 2007-09-10 reyk if ((len = recvfrom(fd, buf, sizeof(buf), 0,
233 7ba7514d 2007-09-10 reyk (struct sockaddr*)&ss, &slen)) < 1)
234 7ba7514d 2007-09-10 reyk return;
235 7ba7514d 2007-09-10 reyk
236 7ba7514d 2007-09-10 reyk if (proto->validate != NULL &&
237 4068a26b 2008-07-09 reyk (priv = (*proto->validate)(NULL, rlay, &ss, buf, len)) == NULL)
238 7ba7514d 2007-09-10 reyk return;
239 7ba7514d 2007-09-10 reyk
240 6e65a975 2013-01-17 bluhm if ((con = calloc(1, sizeof(*con))) == NULL) {
241 6e9314ae 2008-05-08 reyk free(priv);
242 7ba7514d 2007-09-10 reyk return;
243 6e9314ae 2008-05-08 reyk }
244 7ba7514d 2007-09-10 reyk
245 ac536058 2008-03-03 reyk /*
246 ac536058 2008-03-03 reyk * Replace the DNS request Id with a random Id.
247 ac536058 2008-03-03 reyk */
248 6e9314ae 2008-05-08 reyk con->se_priv = priv;
249 aa79f3aa 2008-01-31 thib con->se_in.s = -1;
250 aa79f3aa 2008-01-31 thib con->se_out.s = -1;
251 aa79f3aa 2008-01-31 thib con->se_in.dst = &con->se_out;
252 aa79f3aa 2008-01-31 thib con->se_out.dst = &con->se_in;
253 aa79f3aa 2008-01-31 thib con->se_in.con = con;
254 aa79f3aa 2008-01-31 thib con->se_out.con = con;
255 aa79f3aa 2008-01-31 thib con->se_relay = rlay;
256 aa79f3aa 2008-01-31 thib con->se_id = ++relay_conid;
257 aa79f3aa 2008-01-31 thib con->se_in.dir = RELAY_DIR_REQUEST;
258 aa79f3aa 2008-01-31 thib con->se_out.dir = RELAY_DIR_RESPONSE;
259 aa79f3aa 2008-01-31 thib con->se_retry = rlay->rl_conf.dstretry;
260 aa79f3aa 2008-01-31 thib con->se_out.port = rlay->rl_conf.dstport;
261 7ba7514d 2007-09-10 reyk switch (ss.ss_family) {
262 7ba7514d 2007-09-10 reyk case AF_INET:
263 aa79f3aa 2008-01-31 thib con->se_in.port = ((struct sockaddr_in *)&ss)->sin_port;
264 7ba7514d 2007-09-10 reyk break;
265 7ba7514d 2007-09-10 reyk case AF_INET6:
266 aa79f3aa 2008-01-31 thib con->se_in.port = ((struct sockaddr_in6 *)&ss)->sin6_port;
267 7ba7514d 2007-09-10 reyk break;
268 7ba7514d 2007-09-10 reyk }
269 b7f7a948 2013-03-10 reyk bcopy(&ss, &con->se_in.ss, sizeof(con->se_in.ss));
270 7ba7514d 2007-09-10 reyk
271 b7f7a948 2013-03-10 reyk getmonotime(&con->se_tv_start);
272 b7f7a948 2013-03-10 reyk bcopy(&con->se_tv_start, &con->se_tv_last, sizeof(con->se_tv_last));
273 b7f7a948 2013-03-10 reyk
274 7ba7514d 2007-09-10 reyk relay_sessions++;
275 146643ba 2008-01-31 reyk SPLAY_INSERT(session_tree, &rlay->rl_sessions, con);
276 28bd28ce 2014-11-19 blambert relay_session_publish(con);
277 7ba7514d 2007-09-10 reyk
278 7ba7514d 2007-09-10 reyk /* Increment the per-relay session counter */
279 b14526d5 2016-09-02 reyk rlay->rl_stats[ps->ps_instance].last++;
280 7ba7514d 2007-09-10 reyk
281 7ba7514d 2007-09-10 reyk /* Pre-allocate output buffer */
282 aa79f3aa 2008-01-31 thib con->se_out.output = evbuffer_new();
283 aa79f3aa 2008-01-31 thib if (con->se_out.output == NULL) {
284 37ed6014 2018-08-06 benno relay_close(con, "failed to allocate output buffer", 1);
285 7ba7514d 2007-09-10 reyk return;
286 7ba7514d 2007-09-10 reyk }
287 7ba7514d 2007-09-10 reyk
288 7ba7514d 2007-09-10 reyk /* Pre-allocate log buffer */
289 c72024a8 2014-07-13 benno con->se_haslog = 0;
290 aa79f3aa 2008-01-31 thib con->se_log = evbuffer_new();
291 aa79f3aa 2008-01-31 thib if (con->se_log == NULL) {
292 37ed6014 2018-08-06 benno relay_close(con, "failed to allocate log buffer", 1);
293 7ba7514d 2007-09-10 reyk return;
294 7ba7514d 2007-09-10 reyk }
295 7ba7514d 2007-09-10 reyk
296 146643ba 2008-01-31 reyk if (rlay->rl_conf.flags & F_NATLOOK) {
297 6e65a975 2013-01-17 bluhm if ((cnl = calloc(1, sizeof(*cnl))) == NULL) {
298 37ed6014 2018-08-06 benno relay_close(con, "failed to allocate natlookup", 1);
299 7ba7514d 2007-09-10 reyk return;
300 7ba7514d 2007-09-10 reyk }
301 7ba7514d 2007-09-10 reyk }
302 7ba7514d 2007-09-10 reyk
303 7ba7514d 2007-09-10 reyk /* Save the received data */
304 aa79f3aa 2008-01-31 thib if (evbuffer_add(con->se_out.output, buf, len) == -1) {
305 37ed6014 2018-08-06 benno relay_close(con, "failed to store buffer", 1);
306 ba24b6a0 2015-12-07 mmcc free(cnl);
307 7ba7514d 2007-09-10 reyk return;
308 7ba7514d 2007-09-10 reyk }
309 7ba7514d 2007-09-10 reyk
310 d89b4c88 2012-12-18 reyk if (cnl != NULL) {
311 aa79f3aa 2008-01-31 thib con->se_cnl = cnl;
312 7ba7514d 2007-09-10 reyk bzero(cnl, sizeof(*cnl));
313 7ba7514d 2007-09-10 reyk cnl->in = -1;
314 aa79f3aa 2008-01-31 thib cnl->id = con->se_id;
315 b14526d5 2016-09-02 reyk cnl->proc = ps->ps_instance;
316 555b1b20 2008-07-09 reyk cnl->proto = IPPROTO_UDP;
317 aa79f3aa 2008-01-31 thib bcopy(&con->se_in.ss, &cnl->src, sizeof(cnl->src));
318 146643ba 2008-01-31 reyk bcopy(&rlay->rl_conf.ss, &cnl->dst, sizeof(cnl->dst));
319 141b9058 2015-12-02 reyk proc_compose(env->sc_ps, PROC_PFE,
320 141b9058 2015-12-02 reyk IMSG_NATLOOK, cnl, sizeof(*cnl));
321 7ba7514d 2007-09-10 reyk
322 7ba7514d 2007-09-10 reyk /* Schedule timeout */
323 aa79f3aa 2008-01-31 thib evtimer_set(&con->se_ev, relay_natlook, con);
324 146643ba 2008-01-31 reyk bcopy(&rlay->rl_conf.timeout, &tv, sizeof(tv));
325 aa79f3aa 2008-01-31 thib evtimer_add(&con->se_ev, &tv);
326 7ba7514d 2007-09-10 reyk return;
327 7ba7514d 2007-09-10 reyk }
328 7ba7514d 2007-09-10 reyk
329 7ba7514d 2007-09-10 reyk relay_session(con);
330 7ba7514d 2007-09-10 reyk }
331 7ba7514d 2007-09-10 reyk
332 7ba7514d 2007-09-10 reyk void
333 7ba7514d 2007-09-10 reyk relay_udp_timeout(int fd, short sig, void *arg)
334 7ba7514d 2007-09-10 reyk {
335 6e65a975 2013-01-17 bluhm struct rsession *con = arg;
336 7ba7514d 2007-09-10 reyk
337 7ba7514d 2007-09-10 reyk if (sig != EV_TIMEOUT)
338 7ba7514d 2007-09-10 reyk fatalx("invalid timeout event");
339 7ba7514d 2007-09-10 reyk
340 37ed6014 2018-08-06 benno relay_close(con, "udp timeout", 1);
341 7ba7514d 2007-09-10 reyk }
342 7ba7514d 2007-09-10 reyk
343 7ba7514d 2007-09-10 reyk /*
344 7ba7514d 2007-09-10 reyk * Domain Name System support
345 7ba7514d 2007-09-10 reyk */
346 7ba7514d 2007-09-10 reyk
347 6e9314ae 2008-05-08 reyk struct relay_dns_priv {
348 6e9314ae 2008-05-08 reyk u_int16_t dp_inkey;
349 6e9314ae 2008-05-08 reyk u_int16_t dp_outkey;
350 6e9314ae 2008-05-08 reyk };
351 6e9314ae 2008-05-08 reyk
352 7ba7514d 2007-09-10 reyk struct relay_dnshdr {
353 7ba7514d 2007-09-10 reyk u_int16_t dns_id;
354 7ba7514d 2007-09-10 reyk
355 7ba7514d 2007-09-10 reyk u_int8_t dns_flags0;
356 7ba7514d 2007-09-10 reyk #define DNS_F0_QR 0x80 /* response flag */
357 7ba7514d 2007-09-10 reyk #define DNS_F0_OPCODE 0x78 /* message type */
358 57122c1b 2022-12-28 jmc #define DNS_F0_AA 0x04 /* authoritative answer */
359 7ba7514d 2007-09-10 reyk #define DNS_F0_TC 0x02 /* truncated message */
360 7ba7514d 2007-09-10 reyk #define DNS_F0_RD 0x01 /* recursion desired */
361 7ba7514d 2007-09-10 reyk
362 7ba7514d 2007-09-10 reyk u_int8_t dns_flags1;
363 7ba7514d 2007-09-10 reyk #define DNS_F1_RA 0x80 /* recursion available */
364 7ba7514d 2007-09-10 reyk #define DNS_F1_RES 0x40 /* reserved */
365 7ba7514d 2007-09-10 reyk #define DNS_F1_AD 0x20 /* authentic data */
366 7ba7514d 2007-09-10 reyk #define DNS_F1_CD 0x10 /* checking disabled */
367 7ba7514d 2007-09-10 reyk #define DNS_F1_RCODE 0x0f /* response code */
368 7ba7514d 2007-09-10 reyk
369 7ba7514d 2007-09-10 reyk u_int16_t dns_qdcount;
370 7ba7514d 2007-09-10 reyk u_int16_t dns_ancount;
371 7ba7514d 2007-09-10 reyk u_int16_t dns_nscount;
372 7ba7514d 2007-09-10 reyk u_int16_t dns_arcount;
373 7ba7514d 2007-09-10 reyk } __packed;
374 7ba7514d 2007-09-10 reyk
375 7ba7514d 2007-09-10 reyk void
376 61afd4d6 2009-08-07 reyk relay_dns_log(struct rsession *con, u_int8_t *buf, size_t len)
377 7ba7514d 2007-09-10 reyk {
378 7ba7514d 2007-09-10 reyk struct relay_dnshdr *hdr = (struct relay_dnshdr *)buf;
379 7ba7514d 2007-09-10 reyk
380 2b52c839 2008-07-23 reyk /* Validate the header length */
381 2b52c839 2008-07-23 reyk if (len < sizeof(*hdr)) {
382 666bd316 2011-05-05 reyk log_debug("%s: session %d: short dns packet", __func__,
383 2b52c839 2008-07-23 reyk con->se_id);
384 2b52c839 2008-07-23 reyk return;
385 2b52c839 2008-07-23 reyk }
386 2b52c839 2008-07-23 reyk
387 666bd316 2011-05-05 reyk log_debug("%s: session %d: %s id 0x%x "
388 666bd316 2011-05-05 reyk "flags 0x%x:0x%x qd %u an %u ns %u ar %u", __func__,
389 aa79f3aa 2008-01-31 thib con->se_id,
390 7ba7514d 2007-09-10 reyk hdr->dns_flags0 & DNS_F0_QR ? "response" : "request",
391 7ba7514d 2007-09-10 reyk ntohs(hdr->dns_id),
392 7ba7514d 2007-09-10 reyk hdr->dns_flags0,
393 7ba7514d 2007-09-10 reyk hdr->dns_flags1,
394 7ba7514d 2007-09-10 reyk ntohs(hdr->dns_qdcount),
395 7ba7514d 2007-09-10 reyk ntohs(hdr->dns_ancount),
396 7ba7514d 2007-09-10 reyk ntohs(hdr->dns_nscount),
397 7ba7514d 2007-09-10 reyk ntohs(hdr->dns_arcount));
398 7ba7514d 2007-09-10 reyk }
399 7ba7514d 2007-09-10 reyk
400 6e9314ae 2008-05-08 reyk void *
401 61afd4d6 2009-08-07 reyk relay_dns_validate(struct rsession *con, struct relay *rlay,
402 4068a26b 2008-07-09 reyk struct sockaddr_storage *ss, u_int8_t *buf, size_t len)
403 7ba7514d 2007-09-10 reyk {
404 7ba7514d 2007-09-10 reyk struct relay_dnshdr *hdr = (struct relay_dnshdr *)buf;
405 61afd4d6 2009-08-07 reyk struct rsession lookup;
406 6e9314ae 2008-05-08 reyk u_int16_t key;
407 6e9314ae 2008-05-08 reyk struct relay_dns_priv *priv, lpriv;
408 7ba7514d 2007-09-10 reyk
409 7ba7514d 2007-09-10 reyk /* Validate the header length */
410 7ba7514d 2007-09-10 reyk if (len < sizeof(*hdr))
411 6e9314ae 2008-05-08 reyk return (NULL);
412 7ba7514d 2007-09-10 reyk
413 6e9314ae 2008-05-08 reyk key = ntohs(hdr->dns_id);
414 7ba7514d 2007-09-10 reyk
415 7ba7514d 2007-09-10 reyk /*
416 7ba7514d 2007-09-10 reyk * Check if the header has the response flag set, otherwise
417 7ba7514d 2007-09-10 reyk * return 0 to tell the UDP server to create a new session.
418 7ba7514d 2007-09-10 reyk */
419 6e9314ae 2008-05-08 reyk if ((hdr->dns_flags0 & DNS_F0_QR) == 0) {
420 6e9314ae 2008-05-08 reyk priv = malloc(sizeof(struct relay_dns_priv));
421 6e9314ae 2008-05-08 reyk if (priv == NULL)
422 6e9314ae 2008-05-08 reyk return (NULL);
423 c0255773 2008-07-09 reyk priv->dp_inkey = shuffle_generate16(&relay_shuffle);
424 6e9314ae 2008-05-08 reyk priv->dp_outkey = key;
425 6e9314ae 2008-05-08 reyk return ((void *)priv);
426 6e9314ae 2008-05-08 reyk }
427 7ba7514d 2007-09-10 reyk
428 7ba7514d 2007-09-10 reyk /*
429 7ba7514d 2007-09-10 reyk * Lookup if this response is for a known session and if the
430 7ba7514d 2007-09-10 reyk * remote host matches the original destination of the request.
431 7ba7514d 2007-09-10 reyk */
432 4068a26b 2008-07-09 reyk if (con == NULL) {
433 4068a26b 2008-07-09 reyk lpriv.dp_inkey = key;
434 4068a26b 2008-07-09 reyk lookup.se_priv = &lpriv;
435 4068a26b 2008-07-09 reyk if ((con = SPLAY_FIND(session_tree,
436 4068a26b 2008-07-09 reyk &rlay->rl_sessions, &lookup)) != NULL &&
437 4068a26b 2008-07-09 reyk con->se_priv != NULL &&
438 4068a26b 2008-07-09 reyk relay_cmp_af(ss, &con->se_out.ss) == 0)
439 4068a26b 2008-07-09 reyk relay_dns_result(con, buf, len);
440 c7b7c92e 2008-07-09 reyk } else {
441 6e65a975 2013-01-17 bluhm priv = con->se_priv;
442 c7b7c92e 2008-07-09 reyk if (priv == NULL || key != priv->dp_inkey) {
443 37ed6014 2018-08-06 benno relay_close(con, "invalid response", 1);
444 c7b7c92e 2008-07-09 reyk return (NULL);
445 c7b7c92e 2008-07-09 reyk }
446 4068a26b 2008-07-09 reyk relay_dns_result(con, buf, len);
447 c7b7c92e 2008-07-09 reyk }
448 7ba7514d 2007-09-10 reyk
449 7ba7514d 2007-09-10 reyk /*
450 7ba7514d 2007-09-10 reyk * This is not a new session, ignore it in the UDP server.
451 7ba7514d 2007-09-10 reyk */
452 6e9314ae 2008-05-08 reyk return (NULL);
453 7ba7514d 2007-09-10 reyk }
454 7ba7514d 2007-09-10 reyk
455 7ba7514d 2007-09-10 reyk int
456 61afd4d6 2009-08-07 reyk relay_dns_request(struct rsession *con)
457 7ba7514d 2007-09-10 reyk {
458 6e65a975 2013-01-17 bluhm struct relay *rlay = con->se_relay;
459 6e65a975 2013-01-17 bluhm struct relay_dns_priv *priv = con->se_priv;
460 aa79f3aa 2008-01-31 thib u_int8_t *buf = EVBUFFER_DATA(con->se_out.output);
461 aa79f3aa 2008-01-31 thib size_t len = EVBUFFER_LENGTH(con->se_out.output);
462 7ba7514d 2007-09-10 reyk struct relay_dnshdr *hdr;
463 7ba7514d 2007-09-10 reyk socklen_t slen;
464 7ba7514d 2007-09-10 reyk
465 6e9314ae 2008-05-08 reyk if (buf == NULL || priv == NULL || len < 1)
466 7ba7514d 2007-09-10 reyk return (-1);
467 afbe8d84 2017-01-09 reyk if (log_getverbose() > 1)
468 2b52c839 2008-07-23 reyk relay_dns_log(con, buf, len);
469 7ba7514d 2007-09-10 reyk
470 b7f7a948 2013-03-10 reyk getmonotime(&con->se_tv_start);
471 7ba7514d 2007-09-10 reyk
472 0f7a5e2e 2012-10-03 reyk if (!TAILQ_EMPTY(&rlay->rl_tables)) {
473 7ba7514d 2007-09-10 reyk if (relay_from_table(con) != 0)
474 7ba7514d 2007-09-10 reyk return (-1);
475 aa79f3aa 2008-01-31 thib } else if (con->se_out.ss.ss_family == AF_UNSPEC) {
476 e8962295 2008-09-29 reyk bcopy(&rlay->rl_conf.dstss, &con->se_out.ss,
477 e8962295 2008-09-29 reyk sizeof(con->se_out.ss));
478 aa79f3aa 2008-01-31 thib con->se_out.port = rlay->rl_conf.dstport;
479 7ba7514d 2007-09-10 reyk }
480 7ba7514d 2007-09-10 reyk
481 4068a26b 2008-07-09 reyk if ((con->se_out.s = relay_udp_socket(&con->se_out.ss,
482 4068a26b 2008-07-09 reyk con->se_out.port, rlay->rl_proto)) == -1)
483 7ba7514d 2007-09-10 reyk return (-1);
484 aa79f3aa 2008-01-31 thib slen = con->se_out.ss.ss_len;
485 7ba7514d 2007-09-10 reyk
486 7ba7514d 2007-09-10 reyk hdr = (struct relay_dnshdr *)buf;
487 6e9314ae 2008-05-08 reyk hdr->dns_id = htons(priv->dp_inkey);
488 7ba7514d 2007-09-10 reyk
489 7ba7514d 2007-09-10 reyk retry:
490 4068a26b 2008-07-09 reyk if (sendto(con->se_out.s, buf, len, 0,
491 aa79f3aa 2008-01-31 thib (struct sockaddr *)&con->se_out.ss, slen) == -1) {
492 aa79f3aa 2008-01-31 thib if (con->se_retry) {
493 aa79f3aa 2008-01-31 thib con->se_retry--;
494 666bd316 2011-05-05 reyk log_debug("%s: session %d: "
495 666bd316 2011-05-05 reyk "forward failed: %s, %s", __func__,
496 aa79f3aa 2008-01-31 thib con->se_id, strerror(errno),
497 aa79f3aa 2008-01-31 thib con->se_retry ? "next retry" : "last retry");
498 7ba7514d 2007-09-10 reyk goto retry;
499 7ba7514d 2007-09-10 reyk }
500 666bd316 2011-05-05 reyk log_debug("%s: session %d: forward failed: %s", __func__,
501 aa79f3aa 2008-01-31 thib con->se_id, strerror(errno));
502 7ba7514d 2007-09-10 reyk return (-1);
503 7ba7514d 2007-09-10 reyk }
504 7ba7514d 2007-09-10 reyk
505 4068a26b 2008-07-09 reyk event_again(&con->se_ev, con->se_out.s, EV_TIMEOUT|EV_READ,
506 58721a38 2014-08-08 reyk relay_udp_response, &con->se_tv_start, &rlay->rl_conf.timeout, con);
507 7ba7514d 2007-09-10 reyk
508 7ba7514d 2007-09-10 reyk return (0);
509 7ba7514d 2007-09-10 reyk }
510 7ba7514d 2007-09-10 reyk
511 7ba7514d 2007-09-10 reyk void
512 61afd4d6 2009-08-07 reyk relay_dns_result(struct rsession *con, u_int8_t *buf, size_t len)
513 7ba7514d 2007-09-10 reyk {
514 6e65a975 2013-01-17 bluhm struct relay *rlay = con->se_relay;
515 6e65a975 2013-01-17 bluhm struct relay_dns_priv *priv = con->se_priv;
516 7ba7514d 2007-09-10 reyk struct relay_dnshdr *hdr;
517 7ba7514d 2007-09-10 reyk socklen_t slen;
518 7ba7514d 2007-09-10 reyk
519 6e9314ae 2008-05-08 reyk if (priv == NULL)
520 09e53fee 2017-05-28 benno fatalx("%s: response to invalid session", __func__);
521 6e9314ae 2008-05-08 reyk
522 afbe8d84 2017-01-09 reyk if (log_getverbose() > 1)
523 2b52c839 2008-07-23 reyk relay_dns_log(con, buf, len);
524 7ba7514d 2007-09-10 reyk
525 7ba7514d 2007-09-10 reyk /*
526 7ba7514d 2007-09-10 reyk * Replace the random DNS request Id with the original Id
527 7ba7514d 2007-09-10 reyk */
528 7ba7514d 2007-09-10 reyk hdr = (struct relay_dnshdr *)buf;
529 6e9314ae 2008-05-08 reyk hdr->dns_id = htons(priv->dp_outkey);
530 7ba7514d 2007-09-10 reyk
531 aa79f3aa 2008-01-31 thib slen = con->se_out.ss.ss_len;
532 146643ba 2008-01-31 reyk if (sendto(rlay->rl_s, buf, len, 0,
533 aa79f3aa 2008-01-31 thib (struct sockaddr *)&con->se_in.ss, slen) == -1) {
534 37ed6014 2018-08-06 benno relay_close(con, "response failed", 1);
535 7ba7514d 2007-09-10 reyk return;
536 7ba7514d 2007-09-10 reyk }
537 7ba7514d 2007-09-10 reyk
538 37ed6014 2018-08-06 benno relay_close(con, "session closed", 0);
539 7ba7514d 2007-09-10 reyk }
540 7ba7514d 2007-09-10 reyk
541 7ba7514d 2007-09-10 reyk int
542 61afd4d6 2009-08-07 reyk relay_dns_cmp(struct rsession *a, struct rsession *b)
543 7ba7514d 2007-09-10 reyk {
544 6e65a975 2013-01-17 bluhm struct relay_dns_priv *ap = a->se_priv;
545 6e65a975 2013-01-17 bluhm struct relay_dns_priv *bp = b->se_priv;
546 6e9314ae 2008-05-08 reyk
547 6e9314ae 2008-05-08 reyk if (ap == NULL || bp == NULL)
548 09e53fee 2017-05-28 benno fatalx("%s: invalid session", __func__);
549 6e9314ae 2008-05-08 reyk
550 6e9314ae 2008-05-08 reyk return (memcmp(&ap->dp_inkey, &bp->dp_inkey, sizeof(u_int16_t)));
551 7ba7514d 2007-09-10 reyk }