7 # include <sys/socket.h>
8 # include <arpa/inet.h>
9 # include <netinet/in.h>
18 #include <event2/event.h>
19 #include <event2/util.h>
21 #include "dnscrypt_client.h"
22 #include "dnscrypt_proxy.h"
27 #include "tcp_request.h"
28 #include "udp_request.h"
29 #include "udp_request_p.h"
33 udp_request_free(UDPRequest
* const udp_request
)
35 ProxyContext
*proxy_context
;
37 if (udp_request
->sendto_retry_timer
!= NULL
) {
38 free(event_get_callback_arg(udp_request
->sendto_retry_timer
));
39 event_free(udp_request
->sendto_retry_timer
);
40 udp_request
->sendto_retry_timer
= NULL
;
42 if (udp_request
->timeout_timer
!= NULL
) {
43 event_free(udp_request
->timeout_timer
);
44 udp_request
->timeout_timer
= NULL
;
46 DNSCRYPT_PROXY_REQUEST_UDP_DONE(udp_request
);
47 proxy_context
= udp_request
->proxy_context
;
48 if (udp_request
->status
.is_in_queue
!= 0) {
49 assert(! TAILQ_EMPTY(&proxy_context
->udp_request_queue
));
50 TAILQ_REMOVE(&proxy_context
->udp_request_queue
, udp_request
, queue
);
51 assert(proxy_context
->connections_count
> 0U);
52 proxy_context
->connections_count
--;
53 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
54 proxy_context
->connections_count_max
);
56 udp_request
->proxy_context
= NULL
;
61 udp_request_kill(UDPRequest
* const udp_request
)
63 if (udp_request
== NULL
|| udp_request
->status
.is_dying
) {
66 udp_request
->status
.is_dying
= 1;
67 udp_request_free(udp_request
);
70 static int sendto_with_retry(SendtoWithRetryCtx
* const ctx
);
72 #ifndef UDP_REQUEST_NO_RETRIES
74 sendto_with_retry_timer_cb(evutil_socket_t retry_timer_handle
, short ev_flags
,
77 SendtoWithRetryCtx
* const ctx
= ctx_
;
80 assert(retry_timer_handle
==
81 event_get_fd(ctx
->udp_request
->sendto_retry_timer
));
83 DNSCRYPT_PROXY_REQUEST_UDP_RETRY(ctx
->udp_request
,
84 ctx
->udp_request
->retries
);
85 sendto_with_retry(ctx
);
90 sendto_with_retry(SendtoWithRetryCtx
* const ctx
)
92 SendtoWithRetryCtx
*ctx_cb
;
93 UDPRequest
*udp_request
= ctx
->udp_request
;
97 if (sendto(ctx
->handle
, ctx
->buffer
, ctx
->length
, ctx
->flags
,
98 ctx
->dest_addr
, ctx
->dest_len
) == (ssize_t
) ctx
->length
) {
100 ctx
->cb(udp_request
);
102 if (udp_request
->sendto_retry_timer
!= NULL
) {
103 assert(event_get_callback_arg(udp_request
->sendto_retry_timer
)
106 event_free(udp_request
->sendto_retry_timer
);
107 udp_request
->sendto_retry_timer
= NULL
;
112 err
= evutil_socket_geterror(udp_request
->client_proxy_handle
);
113 logger(udp_request
->proxy_context
, LOG_WARNING
,
114 "sendto: [%s]", evutil_socket_error_to_string(err
));
115 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
117 #ifdef UDP_REQUEST_NO_RETRIES
120 udp_request_kill(udp_request
);
127 retriable
= (err
== WSAENOBUFS
||
128 err
== WSAEWOULDBLOCK
|| err
== WSAEINTR
);
130 retriable
= (err
== ENOBUFS
|| err
== ENOMEM
||
131 err
== EAGAIN
|| err
== EINTR
);
133 if (retriable
== 0) {
134 udp_request_kill(udp_request
);
137 COMPILER_ASSERT(DNS_QUERY_TIMEOUT
< UCHAR_MAX
);
138 if (++(udp_request
->retries
) > DNS_QUERY_TIMEOUT
) {
139 udp_request_kill(udp_request
);
142 if (udp_request
->sendto_retry_timer
!= NULL
) {
143 ctx_cb
= event_get_callback_arg(udp_request
->sendto_retry_timer
);
144 assert(ctx_cb
!= NULL
);
145 assert(ctx_cb
->udp_request
== ctx
->udp_request
);
146 assert(ctx_cb
->buffer
== ctx
->buffer
);
147 assert(ctx_cb
->cb
== ctx
->cb
);
149 if ((ctx_cb
= malloc(sizeof *ctx_cb
)) == NULL
) {
150 logger_error(udp_request
->proxy_context
, "malloc");
151 udp_request_kill(udp_request
);
154 if ((udp_request
->sendto_retry_timer
=
155 evtimer_new(udp_request
->proxy_context
->event_loop
,
156 sendto_with_retry_timer_cb
, ctx_cb
)) == NULL
) {
158 udp_request_kill(udp_request
);
162 event_get_callback_arg(udp_request
->sendto_retry_timer
));
165 const struct timeval tv
= {
166 .tv_sec
= (time_t) UDP_DELAY_BETWEEN_RETRIES
, .tv_usec
= 0
168 evtimer_add(udp_request
->sendto_retry_timer
, &tv
);
169 DNSCRYPT_PROXY_REQUEST_UDP_RETRY_SCHEDULED(udp_request
,
170 udp_request
->retries
);
176 resolver_to_proxy_cb(evutil_socket_t proxy_resolver_handle
, short ev_flags
,
177 void * const proxy_context_
)
179 uint8_t dns_packet
[DNS_MAX_PACKET_SIZE_UDP
];
180 ProxyContext
*proxy_context
= proxy_context_
;
181 UDPRequest
*scanned_udp_request
;
182 UDPRequest
*udp_request
= NULL
;
183 struct sockaddr_storage resolver_sockaddr
;
184 ev_socklen_t resolver_sockaddr_len
= sizeof resolver_sockaddr
;
186 size_t dns_packet_len
= (size_t) 0U;
190 nread
= recvfrom(proxy_resolver_handle
,
191 (void *) dns_packet
, sizeof dns_packet
, 0,
192 (struct sockaddr
*) &resolver_sockaddr
,
193 &resolver_sockaddr_len
);
194 if (nread
< (ssize_t
) 0) {
195 const int err
= evutil_socket_geterror(proxy_resolver_handle
);
196 logger(proxy_context
, LOG_WARNING
,
197 "recvfrom(resolver): [%s]", evutil_socket_error_to_string(err
));
198 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(NULL
);
201 if (evutil_sockaddr_cmp((const struct sockaddr
*) &resolver_sockaddr
,
202 (const struct sockaddr
*)
203 &proxy_context
->resolver_sockaddr
, 1) != 0) {
204 logger_noformat(proxy_context
, LOG_WARNING
,
205 "Received a resolver reply from a different resolver");
208 TAILQ_FOREACH(scanned_udp_request
,
209 &proxy_context
->udp_request_queue
, queue
) {
210 if (dnscrypt_cmp_client_nonce(scanned_udp_request
->client_nonce
,
211 dns_packet
, (size_t) nread
) == 0) {
212 udp_request
= scanned_udp_request
;
216 if (udp_request
== NULL
) {
217 logger(proxy_context
, LOG_DEBUG
,
218 "Received a reply that doesn't match any active query");
221 if (nread
< (ssize_t
) (DNS_HEADER_SIZE
+ dnscrypt_response_header_size()) ||
222 nread
> (ssize_t
) sizeof dns_packet
) {
223 udp_request_kill(udp_request
);
226 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_REPLIED(udp_request
);
227 dns_packet_len
= (size_t) nread
;
228 assert(dns_packet_len
<= sizeof dns_packet
);
230 uncurved_len
= dns_packet_len
;
231 DNSCRYPT_PROXY_REQUEST_UNCURVE_START(udp_request
, uncurved_len
);
232 if (dnscrypt_client_uncurve
233 (&udp_request
->proxy_context
->dnscrypt_client
,
234 udp_request
->client_nonce
, dns_packet
, &uncurved_len
) != 0) {
235 DNSCRYPT_PROXY_REQUEST_UNCURVE_ERROR(udp_request
);
236 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_GOT_INVALID_REPLY(udp_request
);
237 logger_noformat(udp_request
->proxy_context
, LOG_WARNING
,
238 "Received a suspicious reply from the resolver");
239 udp_request_kill(udp_request
);
242 DNSCRYPT_PROXY_REQUEST_UNCURVE_DONE(udp_request
, uncurved_len
);
243 memset(udp_request
->client_nonce
, 0, sizeof udp_request
->client_nonce
);
244 assert(uncurved_len
<= dns_packet_len
);
245 dns_packet_len
= uncurved_len
;
246 sendto_with_retry(& (SendtoWithRetryCtx
) {
247 .udp_request
= udp_request
,
248 .handle
= udp_request
->client_proxy_handle
,
249 .buffer
= dns_packet
,
250 .length
= dns_packet_len
,
252 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
253 .dest_len
= udp_request
->client_sockaddr_len
,
254 .cb
= udp_request_kill
259 proxy_client_send_truncated(UDPRequest
* const udp_request
,
260 uint8_t dns_packet
[DNS_MAX_PACKET_SIZE_UDP
],
261 size_t dns_packet_len
)
263 DNSCRYPT_PROXY_REQUEST_UDP_TRUNCATED(udp_request
);
265 assert(dns_packet_len
> DNS_OFFSET_FLAGS2
);
266 dns_packet
[DNS_OFFSET_FLAGS
] |= DNS_FLAGS_TC
| DNS_FLAGS_QR
;
267 dns_packet
[DNS_OFFSET_FLAGS2
] |= DNS_FLAGS2_RA
;
268 sendto_with_retry(& (SendtoWithRetryCtx
) {
269 .udp_request
= udp_request
,
270 .handle
= udp_request
->client_proxy_handle
,
271 .buffer
= dns_packet
,
272 .length
= dns_packet_len
,
274 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
275 .dest_len
= udp_request
->client_sockaddr_len
,
276 .cb
= udp_request_kill
281 timeout_timer_cb(evutil_socket_t timeout_timer_handle
, short ev_flags
,
282 void * const udp_request_
)
284 UDPRequest
* const udp_request
= udp_request_
;
287 (void) timeout_timer_handle
;
288 DNSCRYPT_PROXY_REQUEST_UDP_TIMEOUT(udp_request
);
289 logger_noformat(udp_request
->proxy_context
, LOG_DEBUG
,
290 "resolver timeout (UDP)");
291 udp_request_kill(udp_request
);
294 #ifndef SO_RCVBUFFORCE
295 # define SO_RCVBUFFORCE SO_RCVBUF
297 #ifndef SO_SNDBUFFORCE
298 # define SO_SNDBUFFORCE SO_SNDBUF
302 udp_tune(evutil_socket_t
const handle
)
307 setsockopt(handle
, SOL_SOCKET
, SO_RCVBUFFORCE
,
308 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
309 setsockopt(handle
, SOL_SOCKET
, SO_SNDBUFFORCE
,
310 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
311 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
312 setsockopt(handle
, IPPROTO_IP
, IP_MTU_DISCOVER
,
313 (void *) (int []) { IP_PMTUDISC_DONT
}, sizeof (int));
314 #elif defined(IP_DONTFRAG)
315 setsockopt(handle
, IPPROTO_IP
, IP_DONTFRAG
,
316 (void *) (int []) { 0 }, sizeof (int));
321 client_to_proxy_cb_sendto_cb(UDPRequest
* const udp_request
)
324 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_START(udp_request
);
328 client_to_proxy_cb(evutil_socket_t client_proxy_handle
, short ev_flags
,
329 void * const proxy_context_
)
331 uint8_t dns_packet
[DNS_MAX_PACKET_SIZE_UDP
];
332 ProxyContext
*proxy_context
= proxy_context_
;
333 UDPRequest
*udp_request
;
336 size_t dns_packet_len
= (size_t) 0U;
337 size_t max_packet_size
;
338 size_t request_edns_payload_size
;
341 assert(client_proxy_handle
== proxy_context
->udp_listener_handle
);
342 if ((udp_request
= calloc((size_t) 1U, sizeof *udp_request
)) == NULL
) {
345 udp_request
->proxy_context
= proxy_context
;
346 udp_request
->sendto_retry_timer
= NULL
;
347 udp_request
->timeout_timer
= NULL
;
348 udp_request
->client_proxy_handle
= client_proxy_handle
;
349 udp_request
->client_sockaddr_len
= sizeof udp_request
->client_sockaddr
;
350 nread
= recvfrom(client_proxy_handle
,
351 (void *) dns_packet
, sizeof dns_packet
, 0,
352 (struct sockaddr
*) &udp_request
->client_sockaddr
,
353 &udp_request
->client_sockaddr_len
);
354 if (nread
< (ssize_t
) 0) {
355 const int err
= evutil_socket_geterror(client_proxy_handle
);
356 logger(proxy_context
, LOG_WARNING
,
357 "recvfrom(client): [%s]", evutil_socket_error_to_string(err
));
358 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
359 udp_request_kill(udp_request
);
362 if (nread
< (ssize_t
) DNS_HEADER_SIZE
||
363 (size_t) nread
> sizeof dns_packet
) {
364 logger_noformat(proxy_context
, LOG_WARNING
, "Short query received");
368 if (proxy_context
->connections_count
>=
369 proxy_context
->connections_count_max
) {
370 DNSCRYPT_PROXY_REQUEST_UDP_OVERLOADED();
371 if (udp_listener_kill_oldest_request(proxy_context
) != 0) {
372 tcp_listener_kill_oldest_request(proxy_context
);
375 proxy_context
->connections_count
++;
376 assert(proxy_context
->connections_count
377 <= proxy_context
->connections_count_max
);
378 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
379 proxy_context
->connections_count_max
);
380 DNSCRYPT_PROXY_REQUEST_UDP_START(udp_request
);
381 TAILQ_INSERT_TAIL(&proxy_context
->udp_request_queue
,
383 memset(&udp_request
->status
, 0, sizeof udp_request
->status
);
384 udp_request
->status
.is_in_queue
= 1;
386 dns_packet_len
= (size_t) nread
;
387 assert(dns_packet_len
<= sizeof dns_packet
);
389 edns_add_section(proxy_context
, dns_packet
, &dns_packet_len
,
390 sizeof dns_packet
, &request_edns_payload_size
);
392 if (request_edns_payload_size
< DNS_MAX_PACKET_SIZE_UDP_SEND
) {
393 max_packet_size
= DNS_MAX_PACKET_SIZE_UDP_SEND
;
395 max_packet_size
= request_edns_payload_size
;
397 if (max_packet_size
> sizeof dns_packet
) {
398 max_packet_size
= sizeof dns_packet
;
400 assert(max_packet_size
<= sizeof dns_packet
);
401 assert(SIZE_MAX
- DNSCRYPT_MAX_PADDING
- dnscrypt_query_header_size()
403 size_t max_len
= dns_packet_len
+ DNSCRYPT_MAX_PADDING
+
404 dnscrypt_query_header_size();
405 if (max_len
> max_packet_size
) {
406 max_len
= max_packet_size
;
408 if (udp_request
->proxy_context
->tcp_only
!= 0 ||
409 dns_packet_len
+ dnscrypt_query_header_size() > max_len
) {
410 proxy_client_send_truncated(udp_request
, dns_packet
, dns_packet_len
);
413 DNSCRYPT_PROXY_REQUEST_CURVE_START(udp_request
, dns_packet_len
);
415 dnscrypt_client_curve(&udp_request
->proxy_context
->dnscrypt_client
,
416 udp_request
->client_nonce
, dns_packet
,
417 dns_packet_len
, max_len
);
418 if (curve_ret
<= (ssize_t
) 0) {
419 DNSCRYPT_PROXY_REQUEST_CURVE_ERROR(udp_request
);
422 dns_packet_len
= (size_t) curve_ret
;
423 assert(dns_packet_len
>= dnscrypt_query_header_size());
424 DNSCRYPT_PROXY_REQUEST_CURVE_DONE(udp_request
, dns_packet_len
);
425 assert(dns_packet_len
<= sizeof dns_packet
);
427 udp_request
->timeout_timer
=
428 evtimer_new(udp_request
->proxy_context
->event_loop
,
429 timeout_timer_cb
, udp_request
);
430 if (udp_request
->timeout_timer
!= NULL
) {
431 const struct timeval tv
= {
432 .tv_sec
= (time_t) DNS_QUERY_TIMEOUT
, .tv_usec
= 0
434 evtimer_add(udp_request
->timeout_timer
, &tv
);
436 sendto_with_retry(& (SendtoWithRetryCtx
) {
437 .udp_request
= udp_request
,
438 .handle
= proxy_context
->udp_proxy_resolver_handle
,
439 .buffer
= dns_packet
,
440 .length
= dns_packet_len
,
442 .dest_addr
= (struct sockaddr
*) &proxy_context
->resolver_sockaddr
,
443 .dest_len
= proxy_context
->resolver_sockaddr_len
,
444 .cb
= client_to_proxy_cb_sendto_cb
449 udp_listener_kill_oldest_request(ProxyContext
* const proxy_context
)
451 if (TAILQ_EMPTY(&proxy_context
->udp_request_queue
)) {
454 udp_request_kill(TAILQ_FIRST(&proxy_context
->udp_request_queue
));
460 udp_listener_bind(ProxyContext
* const proxy_context
)
462 assert(proxy_context
->udp_listener_handle
== -1);
463 if ((proxy_context
->udp_listener_handle
= socket
464 (proxy_context
->local_sockaddr
.ss_family
,
465 SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
466 logger(NULL
, LOG_ERR
, "Unable to create a socket (UDP)");
469 evutil_make_socket_closeonexec(proxy_context
->udp_listener_handle
);
470 evutil_make_socket_nonblocking(proxy_context
->udp_listener_handle
);
471 if (bind(proxy_context
->udp_listener_handle
,
472 (struct sockaddr
*) &proxy_context
->local_sockaddr
,
473 proxy_context
->local_sockaddr_len
) != 0) {
474 logger(NULL
, LOG_ERR
, "Unable to bind (UDP) [%s]",
475 evutil_socket_error_to_string
476 (evutil_socket_geterror(proxy_context
->udp_listener_handle
)));
477 evutil_closesocket(proxy_context
->udp_listener_handle
);
478 proxy_context
->udp_listener_handle
= -1;
481 udp_tune(proxy_context
->udp_listener_handle
);
483 if ((proxy_context
->udp_proxy_resolver_handle
= socket
484 (proxy_context
->resolver_sockaddr
.ss_family
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
485 logger_noformat(proxy_context
, LOG_ERR
,
486 "Unable to create a socket to the resolver");
487 evutil_closesocket(proxy_context
->udp_listener_handle
);
488 proxy_context
->udp_listener_handle
= -1;
491 evutil_make_socket_closeonexec(proxy_context
->udp_proxy_resolver_handle
);
492 evutil_make_socket_nonblocking(proxy_context
->udp_proxy_resolver_handle
);
493 udp_tune(proxy_context
->udp_proxy_resolver_handle
);
495 TAILQ_INIT(&proxy_context
->udp_request_queue
);
501 udp_listener_start(ProxyContext
* const proxy_context
)
503 assert(proxy_context
->udp_listener_handle
!= -1);
504 if ((proxy_context
->udp_listener_event
=
505 event_new(proxy_context
->event_loop
,
506 proxy_context
->udp_listener_handle
, EV_READ
| EV_PERSIST
,
507 client_to_proxy_cb
, proxy_context
)) == NULL
) {
510 if (event_add(proxy_context
->udp_listener_event
, NULL
) != 0) {
511 udp_listener_stop(proxy_context
);
515 assert(proxy_context
->udp_proxy_resolver_handle
!= -1);
516 if ((proxy_context
->udp_proxy_resolver_event
=
517 event_new(proxy_context
->event_loop
,
518 proxy_context
->udp_proxy_resolver_handle
,
519 EV_READ
| EV_PERSIST
,
520 resolver_to_proxy_cb
, proxy_context
)) == NULL
) {
521 udp_listener_stop(proxy_context
);
524 if (event_add(proxy_context
->udp_proxy_resolver_event
, NULL
) != 0) {
525 udp_listener_stop(proxy_context
);
532 udp_listener_stop(ProxyContext
* const proxy_context
)
534 event_free(proxy_context
->udp_proxy_resolver_event
);
535 proxy_context
->udp_proxy_resolver_event
= NULL
;
536 while (udp_listener_kill_oldest_request(proxy_context
) != 0) { }
537 logger_noformat(proxy_context
, LOG_INFO
, "UDP listener shut down");