7 # include <sys/socket.h>
8 # include <arpa/inet.h>
9 # include <netinet/in.h>
19 #include <event2/event.h>
20 #include <event2/util.h>
22 #include "dnscrypt_client.h"
23 #include "dnscrypt_proxy.h"
28 #include "tcp_request.h"
29 #include "udp_request.h"
30 #include "udp_request_p.h"
33 # include "plugin_support.h"
37 udp_request_free(UDPRequest
* const udp_request
)
39 ProxyContext
*proxy_context
;
41 if (udp_request
->sendto_retry_timer
!= NULL
) {
42 free(event_get_callback_arg(udp_request
->sendto_retry_timer
));
43 event_free(udp_request
->sendto_retry_timer
);
44 udp_request
->sendto_retry_timer
= NULL
;
46 if (udp_request
->timeout_timer
!= NULL
) {
47 event_free(udp_request
->timeout_timer
);
48 udp_request
->timeout_timer
= NULL
;
50 DNSCRYPT_PROXY_REQUEST_UDP_DONE(udp_request
);
51 proxy_context
= udp_request
->proxy_context
;
52 if (udp_request
->status
.is_in_queue
!= 0) {
53 assert(! TAILQ_EMPTY(&proxy_context
->udp_request_queue
));
54 TAILQ_REMOVE(&proxy_context
->udp_request_queue
, udp_request
, queue
);
55 assert(proxy_context
->connections_count
> 0U);
56 proxy_context
->connections_count
--;
57 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
58 proxy_context
->connections_count_max
);
60 udp_request
->proxy_context
= NULL
;
65 udp_request_kill(UDPRequest
* const udp_request
)
67 if (udp_request
== NULL
|| udp_request
->status
.is_dying
) {
70 udp_request
->status
.is_dying
= 1;
71 udp_request_free(udp_request
);
74 static int sendto_with_retry(SendtoWithRetryCtx
* const ctx
);
77 sendto_with_retry_timer_cb(evutil_socket_t retry_timer_handle
, short ev_flags
,
80 SendtoWithRetryCtx
* const ctx
= ctx_
;
83 assert(retry_timer_handle
==
84 event_get_fd(ctx
->udp_request
->sendto_retry_timer
));
86 DNSCRYPT_PROXY_REQUEST_UDP_RETRY(ctx
->udp_request
,
87 ctx
->udp_request
->retries
);
88 sendto_with_retry(ctx
);
92 sendto_with_retry(SendtoWithRetryCtx
* const ctx
)
94 void (*cb
)(UDPRequest
*udp_request
);
95 SendtoWithRetryCtx
*ctx_cb
;
96 UDPRequest
*udp_request
= ctx
->udp_request
;
100 if (sendto(ctx
->handle
, ctx
->buffer
, ctx
->length
, ctx
->flags
,
101 ctx
->dest_addr
, ctx
->dest_len
) == (ssize_t
) ctx
->length
) {
103 if (udp_request
->sendto_retry_timer
!= NULL
) {
104 ctx_cb
= event_get_callback_arg(udp_request
->sendto_retry_timer
);
105 assert(ctx_cb
!= NULL
);
106 assert(ctx_cb
->udp_request
== ctx
->udp_request
);
107 assert(ctx_cb
->buffer
== ctx
->buffer
);
109 event_free(udp_request
->sendto_retry_timer
);
110 udp_request
->sendto_retry_timer
= NULL
;
118 err
= evutil_socket_geterror(udp_request
->client_proxy_handle
);
119 logger(udp_request
->proxy_context
, LOG_WARNING
,
120 "sendto: [%s]", evutil_socket_error_to_string(err
));
121 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
124 retriable
= (err
== WSAENOBUFS
||
125 err
== WSAEWOULDBLOCK
|| err
== WSAEINTR
);
127 retriable
= (err
== ENOBUFS
|| err
== ENOMEM
||
128 err
== EAGAIN
|| err
== EINTR
);
130 if (retriable
== 0) {
131 udp_request_kill(udp_request
);
134 COMPILER_ASSERT(DNS_QUERY_TIMEOUT
< UCHAR_MAX
);
135 if (++(udp_request
->retries
) > DNS_QUERY_TIMEOUT
) {
136 udp_request_kill(udp_request
);
139 if (udp_request
->sendto_retry_timer
!= NULL
) {
140 ctx_cb
= event_get_callback_arg(udp_request
->sendto_retry_timer
);
141 assert(ctx_cb
!= NULL
);
142 assert(ctx_cb
->udp_request
== ctx
->udp_request
);
143 assert(ctx_cb
->buffer
== ctx
->buffer
);
145 if ((ctx_cb
= malloc(sizeof *ctx_cb
)) == NULL
) {
146 logger_error(udp_request
->proxy_context
, "malloc");
147 udp_request_kill(udp_request
);
151 event_get_callback_arg(udp_request
->sendto_retry_timer
));
153 if ((udp_request
->sendto_retry_timer
=
154 evtimer_new(udp_request
->proxy_context
->event_loop
,
155 sendto_with_retry_timer_cb
, ctx_cb
)) == NULL
) {
157 udp_request_kill(udp_request
);
161 const struct timeval tv
= {
162 .tv_sec
= (time_t) UDP_DELAY_BETWEEN_RETRIES
, .tv_usec
= 0
164 evtimer_add(udp_request
->sendto_retry_timer
, &tv
);
165 DNSCRYPT_PROXY_REQUEST_UDP_RETRY_SCHEDULED(udp_request
,
166 udp_request
->retries
);
171 resolver_to_proxy_cb(evutil_socket_t proxy_resolver_handle
, short ev_flags
,
172 void * const proxy_context_
)
174 uint8_t dns_reply
[DNS_MAX_PACKET_SIZE_UDP
];
175 ProxyContext
*proxy_context
= proxy_context_
;
176 UDPRequest
*scanned_udp_request
;
177 UDPRequest
*udp_request
= NULL
;
178 struct sockaddr_storage resolver_sockaddr
;
179 ev_socklen_t resolver_sockaddr_len
= sizeof resolver_sockaddr
;
181 size_t dns_reply_len
= (size_t) 0U;
185 nread
= recvfrom(proxy_resolver_handle
,
186 (void *) dns_reply
, sizeof dns_reply
, 0,
187 (struct sockaddr
*) &resolver_sockaddr
,
188 &resolver_sockaddr_len
);
189 if (nread
< (ssize_t
) 0) {
190 const int err
= evutil_socket_geterror(proxy_resolver_handle
);
191 logger(proxy_context
, LOG_WARNING
,
192 "recvfrom(resolver): [%s]", evutil_socket_error_to_string(err
));
193 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(NULL
);
196 if (evutil_sockaddr_cmp((const struct sockaddr
*) &resolver_sockaddr
,
197 (const struct sockaddr
*)
198 &proxy_context
->resolver_sockaddr
, 1) != 0) {
199 logger_noformat(proxy_context
, LOG_DEBUG
,
200 "Received a resolver reply from a different resolver");
203 TAILQ_FOREACH(scanned_udp_request
,
204 &proxy_context
->udp_request_queue
, queue
) {
205 if (dnscrypt_cmp_client_nonce(scanned_udp_request
->client_nonce
,
206 dns_reply
, (size_t) nread
) == 0) {
207 udp_request
= scanned_udp_request
;
211 if (udp_request
== NULL
) {
212 logger(proxy_context
, LOG_DEBUG
,
213 "Received a reply that doesn't match any active query");
216 if (nread
< (ssize_t
) (DNS_HEADER_SIZE
+ dnscrypt_response_header_size()) ||
217 nread
> (ssize_t
) sizeof dns_reply
) {
218 logger_noformat(proxy_context
, LOG_WARNING
, "Short reply received");
219 udp_request_kill(udp_request
);
222 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_REPLIED(udp_request
);
223 dns_reply_len
= (size_t) nread
;
224 assert(dns_reply_len
<= sizeof dns_reply
);
226 uncurved_len
= dns_reply_len
;
227 DNSCRYPT_PROXY_REQUEST_UNCURVE_START(udp_request
, uncurved_len
);
228 if (dnscrypt_client_uncurve
229 (&udp_request
->proxy_context
->dnscrypt_client
,
230 udp_request
->client_nonce
, dns_reply
, &uncurved_len
) != 0) {
231 DNSCRYPT_PROXY_REQUEST_UNCURVE_ERROR(udp_request
);
232 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_GOT_INVALID_REPLY(udp_request
);
233 logger_noformat(udp_request
->proxy_context
, LOG_WARNING
,
234 "Received a suspicious reply from the resolver");
235 udp_request_kill(udp_request
);
238 DNSCRYPT_PROXY_REQUEST_UNCURVE_DONE(udp_request
, uncurved_len
);
239 memset(udp_request
->client_nonce
, 0, sizeof udp_request
->client_nonce
);
240 assert(uncurved_len
<= dns_reply_len
);
241 dns_reply_len
= uncurved_len
;
243 assert(dns_reply_len
>= DNS_HEADER_SIZE
);
244 COMPILER_ASSERT(DNS_OFFSET_FLAGS
< DNS_HEADER_SIZE
);
245 if ((dns_reply
[DNS_OFFSET_FLAGS
] & DNS_FLAGS_TC
) != 0) {
246 if (proxy_context
->udp_current_max_size
<
247 proxy_context
->udp_max_size
) {
248 COMPILER_ASSERT(DNS_MAX_PACKET_SIZE_UDP_NO_EDNS_SEND
>=
249 DNSCRYPT_BLOCK_SIZE
);
250 if (proxy_context
->udp_max_size
-
251 proxy_context
->udp_current_max_size
> DNSCRYPT_BLOCK_SIZE
) {
252 proxy_context
->udp_current_max_size
+= DNSCRYPT_BLOCK_SIZE
;
254 proxy_context
->udp_current_max_size
=
255 proxy_context
->udp_max_size
;
261 const size_t max_reply_size_for_filter
= sizeof dns_reply
;
262 DCPluginDNSPacket dcp_packet
= {
263 .client_sockaddr
= &udp_request
->client_sockaddr
,
264 .dns_packet
= dns_reply
,
265 .dns_packet_len_p
= &dns_reply_len
,
266 .client_sockaddr_len_s
= (size_t) udp_request
->client_sockaddr_len
,
267 .dns_packet_max_len
= max_reply_size_for_filter
269 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_START(udp_request
, dns_reply_len
,
270 max_reply_size_for_filter
);
271 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
272 const DCPluginSyncFilterResult res
=
273 plugin_support_context_apply_sync_post_filters
274 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
275 assert(dns_reply_len
> (size_t) 0U &&
276 dns_reply_len
<= sizeof dns_reply
&&
277 dns_reply_len
<= max_reply_size_for_filter
);
278 if (res
!= DCP_SYNC_FILTER_RESULT_OK
) {
279 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_ERROR(udp_request
, res
);
280 udp_request_kill(udp_request
);
283 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_DONE(udp_request
, dns_reply_len
,
284 max_reply_size_for_filter
);
286 sendto_with_retry(& (SendtoWithRetryCtx
) {
287 .udp_request
= udp_request
,
288 .handle
= udp_request
->client_proxy_handle
,
290 .length
= dns_reply_len
,
292 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
293 .dest_len
= udp_request
->client_sockaddr_len
,
294 .cb
= udp_request_kill
299 proxy_client_send_truncated(UDPRequest
* const udp_request
,
300 uint8_t dns_reply
[DNS_MAX_PACKET_SIZE_UDP
],
301 size_t dns_reply_len
)
303 DNSCRYPT_PROXY_REQUEST_UDP_TRUNCATED(udp_request
);
305 assert(dns_reply_len
> DNS_OFFSET_FLAGS2
);
306 dns_reply
[DNS_OFFSET_FLAGS
] |= DNS_FLAGS_TC
| DNS_FLAGS_QR
;
307 dns_reply
[DNS_OFFSET_FLAGS2
] |= DNS_FLAGS2_RA
;
308 sendto_with_retry(& (SendtoWithRetryCtx
) {
309 .udp_request
= udp_request
,
310 .handle
= udp_request
->client_proxy_handle
,
312 .length
= dns_reply_len
,
314 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
315 .dest_len
= udp_request
->client_sockaddr_len
,
316 .cb
= udp_request_kill
321 timeout_timer_cb(evutil_socket_t timeout_timer_handle
, short ev_flags
,
322 void * const udp_request_
)
324 UDPRequest
* const udp_request
= udp_request_
;
327 (void) timeout_timer_handle
;
328 DNSCRYPT_PROXY_REQUEST_UDP_TIMEOUT(udp_request
);
329 logger_noformat(udp_request
->proxy_context
, LOG_DEBUG
,
330 "resolver timeout (UDP)");
331 udp_request_kill(udp_request
);
334 #ifndef SO_RCVBUFFORCE
335 # define SO_RCVBUFFORCE SO_RCVBUF
337 #ifndef SO_SNDBUFFORCE
338 # define SO_SNDBUFFORCE SO_SNDBUF
342 udp_tune(evutil_socket_t
const handle
)
347 setsockopt(handle
, SOL_SOCKET
, SO_RCVBUFFORCE
,
348 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
349 setsockopt(handle
, SOL_SOCKET
, SO_SNDBUFFORCE
,
350 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
351 #if defined(IP_PMTUDISC_OMIT)
352 setsockopt(handle
, IPPROTO_IP
, IP_MTU_DISCOVER
,
353 (void *) (int []) { IP_PMTUDISC_OMIT
}, sizeof (int));
354 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
355 setsockopt(handle
, IPPROTO_IP
, IP_MTU_DISCOVER
,
356 (void *) (int []) { IP_PMTUDISC_DONT
}, sizeof (int));
357 #elif defined(IP_DONTFRAG)
358 setsockopt(handle
, IPPROTO_IP
, IP_DONTFRAG
,
359 (void *) (int []) { 0 }, sizeof (int));
364 client_to_proxy_cb_sendto_cb(UDPRequest
* const udp_request
)
367 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_START(udp_request
);
372 proxy_to_client_direct(UDPRequest
* const udp_request
,
373 const uint8_t * const dns_reply
,
374 const size_t dns_reply_len
)
376 sendto_with_retry(& (SendtoWithRetryCtx
) {
377 .udp_request
= udp_request
,
378 .handle
= udp_request
->client_proxy_handle
,
380 .length
= dns_reply_len
,
382 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
383 .dest_len
= udp_request
->client_sockaddr_len
,
384 .cb
= udp_request_kill
390 client_to_proxy_cb(evutil_socket_t client_proxy_handle
, short ev_flags
,
391 void * const proxy_context_
)
393 uint8_t dns_query
[DNS_MAX_PACKET_SIZE_UDP
];
394 ProxyContext
*proxy_context
= proxy_context_
;
395 UDPRequest
*udp_request
;
398 size_t dns_query_len
= (size_t) 0U;
399 size_t max_query_size
;
400 size_t request_edns_payload_size
;
403 assert(client_proxy_handle
== proxy_context
->udp_listener_handle
);
404 if ((udp_request
= calloc((size_t) 1U, sizeof *udp_request
)) == NULL
) {
407 udp_request
->proxy_context
= proxy_context
;
408 udp_request
->sendto_retry_timer
= NULL
;
409 udp_request
->timeout_timer
= NULL
;
410 udp_request
->client_proxy_handle
= client_proxy_handle
;
411 udp_request
->client_sockaddr_len
= sizeof udp_request
->client_sockaddr
;
412 nread
= recvfrom(client_proxy_handle
,
413 (void *) dns_query
, sizeof dns_query
, 0,
414 (struct sockaddr
*) &udp_request
->client_sockaddr
,
415 &udp_request
->client_sockaddr_len
);
416 if (nread
< (ssize_t
) 0) {
417 const int err
= evutil_socket_geterror(client_proxy_handle
);
418 logger(proxy_context
, LOG_WARNING
,
419 "recvfrom(client): [%s]", evutil_socket_error_to_string(err
));
420 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
421 udp_request_kill(udp_request
);
424 if (nread
< (ssize_t
) DNS_HEADER_SIZE
||
425 (size_t) nread
> sizeof dns_query
) {
426 logger_noformat(proxy_context
, LOG_WARNING
, "Short query received");
430 if (proxy_context
->connections_count
>=
431 proxy_context
->connections_count_max
) {
432 DNSCRYPT_PROXY_REQUEST_UDP_OVERLOADED();
433 if (udp_listener_kill_oldest_request(proxy_context
) != 0) {
434 tcp_listener_kill_oldest_request(proxy_context
);
437 proxy_context
->connections_count
++;
438 assert(proxy_context
->connections_count
439 <= proxy_context
->connections_count_max
);
440 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
441 proxy_context
->connections_count_max
);
442 DNSCRYPT_PROXY_REQUEST_UDP_START(udp_request
);
443 TAILQ_INSERT_TAIL(&proxy_context
->udp_request_queue
,
445 memset(&udp_request
->status
, 0, sizeof udp_request
->status
);
446 udp_request
->status
.is_in_queue
= 1;
448 dns_query_len
= (size_t) nread
;
449 assert(dns_query_len
<= sizeof dns_query
);
451 edns_add_section(proxy_context
, dns_query
, &dns_query_len
,
452 sizeof dns_query
, &request_edns_payload_size
);
454 if (request_edns_payload_size
< DNS_MAX_PACKET_SIZE_UDP_NO_EDNS_SEND
) {
455 max_query_size
= DNS_MAX_PACKET_SIZE_UDP_NO_EDNS_SEND
;
457 max_query_size
= request_edns_payload_size
;
459 if (max_query_size
> sizeof dns_query
) {
460 max_query_size
= sizeof dns_query
;
462 assert(max_query_size
<= sizeof dns_query
);
463 if (udp_request
->proxy_context
->tcp_only
!= 0) {
464 proxy_client_send_truncated(udp_request
, dns_query
, dns_query_len
);
468 size_t max_query_size_for_filter
= dns_query_len
;
469 if (max_query_size
> DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size()) {
470 max_query_size_for_filter
= max_query_size
-
471 (DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size());
473 DCPluginDNSPacket dcp_packet
= {
474 .client_sockaddr
= &udp_request
->client_sockaddr
,
475 .dns_packet
= dns_query
,
476 .dns_packet_len_p
= &dns_query_len
,
477 .client_sockaddr_len_s
= (size_t) udp_request
->client_sockaddr_len
,
478 .dns_packet_max_len
= max_query_size_for_filter
480 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_START(udp_request
, dns_query_len
,
481 max_query_size_for_filter
);
482 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
483 const DCPluginSyncFilterResult res
=
484 plugin_support_context_apply_sync_pre_filters
485 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
486 assert(dns_query_len
> (size_t) 0U && dns_query_len
<= max_query_size
&&
487 dns_query_len
<= max_query_size_for_filter
);
489 case DCP_SYNC_FILTER_RESULT_OK
:
491 case DCP_SYNC_FILTER_RESULT_DIRECT
:
492 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(udp_request
, dns_query_len
,
493 max_query_size_for_filter
);
494 proxy_to_client_direct(udp_request
, dns_query
, dns_query_len
);
497 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_ERROR(udp_request
, res
);
498 udp_request_kill(udp_request
);
501 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(udp_request
, dns_query_len
,
502 max_query_size_for_filter
);
504 assert(SIZE_MAX
- DNSCRYPT_MAX_PADDING
- dnscrypt_query_header_size()
508 max_len
= proxy_context
->udp_current_max_size
;
509 if (max_len
> max_query_size
) {
510 max_len
= max_query_size
;
512 if (dns_query_len
+ dnscrypt_query_header_size() > max_len
) {
513 proxy_client_send_truncated(udp_request
, dns_query
, dns_query_len
);
516 DNSCRYPT_PROXY_REQUEST_CURVE_START(udp_request
, dns_query_len
);
518 dnscrypt_client_curve(&udp_request
->proxy_context
->dnscrypt_client
,
519 udp_request
->client_nonce
, dns_query
,
520 dns_query_len
, max_len
);
521 if (curve_ret
<= (ssize_t
) 0) {
522 DNSCRYPT_PROXY_REQUEST_CURVE_ERROR(udp_request
);
525 dns_query_len
= (size_t) curve_ret
;
526 assert(dns_query_len
>= dnscrypt_query_header_size());
527 DNSCRYPT_PROXY_REQUEST_CURVE_DONE(udp_request
, dns_query_len
);
528 assert(dns_query_len
<= sizeof dns_query
);
530 udp_request
->timeout_timer
=
531 evtimer_new(udp_request
->proxy_context
->event_loop
,
532 timeout_timer_cb
, udp_request
);
533 if (udp_request
->timeout_timer
!= NULL
) {
534 const struct timeval tv
= {
535 .tv_sec
= (time_t) DNS_QUERY_TIMEOUT
, .tv_usec
= 0
537 evtimer_add(udp_request
->timeout_timer
, &tv
);
539 sendto_with_retry(& (SendtoWithRetryCtx
) {
540 .udp_request
= udp_request
,
541 .handle
= proxy_context
->udp_proxy_resolver_handle
,
543 .length
= dns_query_len
,
545 .dest_addr
= (struct sockaddr
*) &proxy_context
->resolver_sockaddr
,
546 .dest_len
= proxy_context
->resolver_sockaddr_len
,
547 .cb
= client_to_proxy_cb_sendto_cb
552 udp_listener_kill_oldest_request(ProxyContext
* const proxy_context
)
554 if (TAILQ_EMPTY(&proxy_context
->udp_request_queue
)) {
557 udp_request_kill(TAILQ_FIRST(&proxy_context
->udp_request_queue
));
563 udp_listener_bind(ProxyContext
* const proxy_context
)
565 assert(proxy_context
->udp_listener_handle
== -1);
566 if ((proxy_context
->udp_listener_handle
= socket
567 (proxy_context
->local_sockaddr
.ss_family
,
568 SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
569 logger(NULL
, LOG_ERR
, "Unable to create a socket (UDP)");
572 evutil_make_socket_closeonexec(proxy_context
->udp_listener_handle
);
573 evutil_make_socket_nonblocking(proxy_context
->udp_listener_handle
);
574 if (bind(proxy_context
->udp_listener_handle
,
575 (struct sockaddr
*) &proxy_context
->local_sockaddr
,
576 proxy_context
->local_sockaddr_len
) != 0) {
577 logger(NULL
, LOG_ERR
, "Unable to bind (UDP) [%s]",
578 evutil_socket_error_to_string
579 (evutil_socket_geterror(proxy_context
->udp_listener_handle
)));
580 evutil_closesocket(proxy_context
->udp_listener_handle
);
581 proxy_context
->udp_listener_handle
= -1;
584 udp_tune(proxy_context
->udp_listener_handle
);
586 if ((proxy_context
->udp_proxy_resolver_handle
= socket
587 (proxy_context
->resolver_sockaddr
.ss_family
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
588 logger_noformat(proxy_context
, LOG_ERR
,
589 "Unable to create a socket to the resolver");
590 evutil_closesocket(proxy_context
->udp_listener_handle
);
591 proxy_context
->udp_listener_handle
= -1;
594 evutil_make_socket_closeonexec(proxy_context
->udp_proxy_resolver_handle
);
595 evutil_make_socket_nonblocking(proxy_context
->udp_proxy_resolver_handle
);
596 udp_tune(proxy_context
->udp_proxy_resolver_handle
);
598 TAILQ_INIT(&proxy_context
->udp_request_queue
);
604 udp_listener_start(ProxyContext
* const proxy_context
)
606 assert(proxy_context
->udp_listener_handle
!= -1);
607 if ((proxy_context
->udp_listener_event
=
608 event_new(proxy_context
->event_loop
,
609 proxy_context
->udp_listener_handle
, EV_READ
| EV_PERSIST
,
610 client_to_proxy_cb
, proxy_context
)) == NULL
) {
613 if (event_add(proxy_context
->udp_listener_event
, NULL
) != 0) {
614 udp_listener_stop(proxy_context
);
618 assert(proxy_context
->udp_proxy_resolver_handle
!= -1);
619 if ((proxy_context
->udp_proxy_resolver_event
=
620 event_new(proxy_context
->event_loop
,
621 proxy_context
->udp_proxy_resolver_handle
,
622 EV_READ
| EV_PERSIST
,
623 resolver_to_proxy_cb
, proxy_context
)) == NULL
) {
624 udp_listener_stop(proxy_context
);
627 if (event_add(proxy_context
->udp_proxy_resolver_event
, NULL
) != 0) {
628 udp_listener_stop(proxy_context
);
635 udp_listener_stop(ProxyContext
* const proxy_context
)
637 event_free(proxy_context
->udp_proxy_resolver_event
);
638 proxy_context
->udp_proxy_resolver_event
= NULL
;
639 while (udp_listener_kill_oldest_request(proxy_context
) != 0) { }
640 logger_noformat(proxy_context
, LOG_INFO
, "UDP listener shut down");