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 assert(event_get_callback_arg(udp_request
->sendto_retry_timer
)
107 event_free(udp_request
->sendto_retry_timer
);
108 udp_request
->sendto_retry_timer
= NULL
;
116 err
= evutil_socket_geterror(udp_request
->client_proxy_handle
);
117 logger(udp_request
->proxy_context
, LOG_WARNING
,
118 "sendto: [%s]", evutil_socket_error_to_string(err
));
119 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
122 retriable
= (err
== WSAENOBUFS
||
123 err
== WSAEWOULDBLOCK
|| err
== WSAEINTR
);
125 retriable
= (err
== ENOBUFS
|| err
== ENOMEM
||
126 err
== EAGAIN
|| err
== EINTR
);
128 if (retriable
== 0) {
129 udp_request_kill(udp_request
);
132 COMPILER_ASSERT(DNS_QUERY_TIMEOUT
< UCHAR_MAX
);
133 if (++(udp_request
->retries
) > DNS_QUERY_TIMEOUT
) {
134 udp_request_kill(udp_request
);
137 if (udp_request
->sendto_retry_timer
!= NULL
) {
138 ctx_cb
= event_get_callback_arg(udp_request
->sendto_retry_timer
);
139 assert(ctx_cb
!= NULL
);
140 assert(ctx_cb
->udp_request
== ctx
->udp_request
);
141 assert(ctx_cb
->buffer
== ctx
->buffer
);
142 assert(ctx_cb
->cb
== ctx
->cb
);
144 if ((ctx_cb
= malloc(sizeof *ctx_cb
)) == NULL
) {
145 logger_error(udp_request
->proxy_context
, "malloc");
146 udp_request_kill(udp_request
);
149 if ((udp_request
->sendto_retry_timer
=
150 evtimer_new(udp_request
->proxy_context
->event_loop
,
151 sendto_with_retry_timer_cb
, ctx_cb
)) == NULL
) {
153 udp_request_kill(udp_request
);
157 event_get_callback_arg(udp_request
->sendto_retry_timer
));
160 const struct timeval tv
= {
161 .tv_sec
= (time_t) UDP_DELAY_BETWEEN_RETRIES
, .tv_usec
= 0
163 evtimer_add(udp_request
->sendto_retry_timer
, &tv
);
164 DNSCRYPT_PROXY_REQUEST_UDP_RETRY_SCHEDULED(udp_request
,
165 udp_request
->retries
);
170 resolver_to_proxy_cb(evutil_socket_t proxy_resolver_handle
, short ev_flags
,
171 void * const proxy_context_
)
173 uint8_t dns_reply
[DNS_MAX_PACKET_SIZE_UDP
];
174 ProxyContext
*proxy_context
= proxy_context_
;
175 UDPRequest
*scanned_udp_request
;
176 UDPRequest
*udp_request
= NULL
;
177 struct sockaddr_storage resolver_sockaddr
;
178 ev_socklen_t resolver_sockaddr_len
= sizeof resolver_sockaddr
;
180 size_t dns_reply_len
= (size_t) 0U;
184 nread
= recvfrom(proxy_resolver_handle
,
185 (void *) dns_reply
, sizeof dns_reply
, 0,
186 (struct sockaddr
*) &resolver_sockaddr
,
187 &resolver_sockaddr_len
);
188 if (nread
< (ssize_t
) 0) {
189 const int err
= evutil_socket_geterror(proxy_resolver_handle
);
190 logger(proxy_context
, LOG_WARNING
,
191 "recvfrom(resolver): [%s]", evutil_socket_error_to_string(err
));
192 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(NULL
);
195 if (evutil_sockaddr_cmp((const struct sockaddr
*) &resolver_sockaddr
,
196 (const struct sockaddr
*)
197 &proxy_context
->resolver_sockaddr
, 1) != 0) {
198 logger_noformat(proxy_context
, LOG_WARNING
,
199 "Received a resolver reply from a different resolver");
202 TAILQ_FOREACH(scanned_udp_request
,
203 &proxy_context
->udp_request_queue
, queue
) {
204 if (dnscrypt_cmp_client_nonce(scanned_udp_request
->client_nonce
,
205 dns_reply
, (size_t) nread
) == 0) {
206 udp_request
= scanned_udp_request
;
210 if (udp_request
== NULL
) {
211 logger(proxy_context
, LOG_DEBUG
,
212 "Received a reply that doesn't match any active query");
215 if (nread
< (ssize_t
) (DNS_HEADER_SIZE
+ dnscrypt_response_header_size()) ||
216 nread
> (ssize_t
) sizeof dns_reply
) {
217 logger_noformat(proxy_context
, LOG_WARNING
, "Short reply received");
218 udp_request_kill(udp_request
);
221 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_REPLIED(udp_request
);
222 dns_reply_len
= (size_t) nread
;
223 assert(dns_reply_len
<= sizeof dns_reply
);
225 uncurved_len
= dns_reply_len
;
226 DNSCRYPT_PROXY_REQUEST_UNCURVE_START(udp_request
, uncurved_len
);
227 if (dnscrypt_client_uncurve
228 (&udp_request
->proxy_context
->dnscrypt_client
,
229 udp_request
->client_nonce
, dns_reply
, &uncurved_len
) != 0) {
230 DNSCRYPT_PROXY_REQUEST_UNCURVE_ERROR(udp_request
);
231 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_GOT_INVALID_REPLY(udp_request
);
232 logger_noformat(udp_request
->proxy_context
, LOG_WARNING
,
233 "Received a suspicious reply from the resolver");
234 udp_request_kill(udp_request
);
237 DNSCRYPT_PROXY_REQUEST_UNCURVE_DONE(udp_request
, uncurved_len
);
238 memset(udp_request
->client_nonce
, 0, sizeof udp_request
->client_nonce
);
239 assert(uncurved_len
<= dns_reply_len
);
240 dns_reply_len
= uncurved_len
;
242 const size_t max_reply_size_for_filter
= sizeof dns_reply
;
243 DCPluginDNSPacket dcp_packet
= {
244 .client_sockaddr
= &udp_request
->client_sockaddr
,
245 .dns_packet
= dns_reply
,
246 .dns_packet_len_p
= &dns_reply_len
,
247 .client_sockaddr_len_s
= (size_t) udp_request
->client_sockaddr_len
,
248 .dns_packet_max_len
= max_reply_size_for_filter
250 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_START(udp_request
, dns_reply_len
,
251 max_reply_size_for_filter
);
252 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
253 const DCPluginSyncFilterResult res
=
254 plugin_support_context_apply_sync_post_filters
255 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
256 assert(dns_reply_len
> (size_t) 0U &&
257 dns_reply_len
<= sizeof dns_reply
&&
258 dns_reply_len
<= max_reply_size_for_filter
);
259 if (res
!= DCP_SYNC_FILTER_RESULT_OK
) {
260 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_ERROR(udp_request
, res
);
261 udp_request_kill(udp_request
);
264 DNSCRYPT_PROXY_REQUEST_PLUGINS_POST_DONE(udp_request
, dns_reply_len
,
265 max_reply_size_for_filter
);
267 sendto_with_retry(& (SendtoWithRetryCtx
) {
268 .udp_request
= udp_request
,
269 .handle
= udp_request
->client_proxy_handle
,
271 .length
= dns_reply_len
,
273 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
274 .dest_len
= udp_request
->client_sockaddr_len
,
275 .cb
= udp_request_kill
280 proxy_client_send_truncated(UDPRequest
* const udp_request
,
281 uint8_t dns_reply
[DNS_MAX_PACKET_SIZE_UDP
],
282 size_t dns_reply_len
)
284 DNSCRYPT_PROXY_REQUEST_UDP_TRUNCATED(udp_request
);
286 assert(dns_reply_len
> DNS_OFFSET_FLAGS2
);
287 dns_reply
[DNS_OFFSET_FLAGS
] |= DNS_FLAGS_TC
| DNS_FLAGS_QR
;
288 dns_reply
[DNS_OFFSET_FLAGS2
] |= DNS_FLAGS2_RA
;
289 sendto_with_retry(& (SendtoWithRetryCtx
) {
290 .udp_request
= udp_request
,
291 .handle
= udp_request
->client_proxy_handle
,
293 .length
= dns_reply_len
,
295 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
296 .dest_len
= udp_request
->client_sockaddr_len
,
297 .cb
= udp_request_kill
302 timeout_timer_cb(evutil_socket_t timeout_timer_handle
, short ev_flags
,
303 void * const udp_request_
)
305 UDPRequest
* const udp_request
= udp_request_
;
308 (void) timeout_timer_handle
;
309 DNSCRYPT_PROXY_REQUEST_UDP_TIMEOUT(udp_request
);
310 logger_noformat(udp_request
->proxy_context
, LOG_DEBUG
,
311 "resolver timeout (UDP)");
312 udp_request_kill(udp_request
);
315 #ifndef SO_RCVBUFFORCE
316 # define SO_RCVBUFFORCE SO_RCVBUF
318 #ifndef SO_SNDBUFFORCE
319 # define SO_SNDBUFFORCE SO_SNDBUF
323 udp_tune(evutil_socket_t
const handle
)
328 setsockopt(handle
, SOL_SOCKET
, SO_RCVBUFFORCE
,
329 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
330 setsockopt(handle
, SOL_SOCKET
, SO_SNDBUFFORCE
,
331 (void *) (int []) { UDP_BUFFER_SIZE
}, sizeof (int));
332 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
333 setsockopt(handle
, IPPROTO_IP
, IP_MTU_DISCOVER
,
334 (void *) (int []) { IP_PMTUDISC_DONT
}, sizeof (int));
335 #elif defined(IP_DONTFRAG)
336 setsockopt(handle
, IPPROTO_IP
, IP_DONTFRAG
,
337 (void *) (int []) { 0 }, sizeof (int));
342 client_to_proxy_cb_sendto_cb(UDPRequest
* const udp_request
)
345 DNSCRYPT_PROXY_REQUEST_UDP_PROXY_RESOLVER_START(udp_request
);
350 proxy_to_client_direct(UDPRequest
* const udp_request
,
351 const uint8_t * const dns_reply
,
352 const size_t dns_reply_len
)
354 sendto_with_retry(& (SendtoWithRetryCtx
) {
355 .udp_request
= udp_request
,
356 .handle
= udp_request
->client_proxy_handle
,
358 .length
= dns_reply_len
,
360 .dest_addr
= (struct sockaddr
*) &udp_request
->client_sockaddr
,
361 .dest_len
= udp_request
->client_sockaddr_len
,
362 .cb
= udp_request_kill
368 client_to_proxy_cb(evutil_socket_t client_proxy_handle
, short ev_flags
,
369 void * const proxy_context_
)
371 uint8_t dns_query
[DNS_MAX_PACKET_SIZE_UDP
];
372 ProxyContext
*proxy_context
= proxy_context_
;
373 UDPRequest
*udp_request
;
376 size_t dns_query_len
= (size_t) 0U;
377 size_t max_query_size
;
378 size_t request_edns_payload_size
;
381 assert(client_proxy_handle
== proxy_context
->udp_listener_handle
);
382 if ((udp_request
= calloc((size_t) 1U, sizeof *udp_request
)) == NULL
) {
385 udp_request
->proxy_context
= proxy_context
;
386 udp_request
->sendto_retry_timer
= NULL
;
387 udp_request
->timeout_timer
= NULL
;
388 udp_request
->client_proxy_handle
= client_proxy_handle
;
389 udp_request
->client_sockaddr_len
= sizeof udp_request
->client_sockaddr
;
390 nread
= recvfrom(client_proxy_handle
,
391 (void *) dns_query
, sizeof dns_query
, 0,
392 (struct sockaddr
*) &udp_request
->client_sockaddr
,
393 &udp_request
->client_sockaddr_len
);
394 if (nread
< (ssize_t
) 0) {
395 const int err
= evutil_socket_geterror(client_proxy_handle
);
396 logger(proxy_context
, LOG_WARNING
,
397 "recvfrom(client): [%s]", evutil_socket_error_to_string(err
));
398 DNSCRYPT_PROXY_REQUEST_UDP_NETWORK_ERROR(udp_request
);
399 udp_request_kill(udp_request
);
402 if (nread
< (ssize_t
) DNS_HEADER_SIZE
||
403 (size_t) nread
> sizeof dns_query
) {
404 logger_noformat(proxy_context
, LOG_WARNING
, "Short query received");
408 if (proxy_context
->connections_count
>=
409 proxy_context
->connections_count_max
) {
410 DNSCRYPT_PROXY_REQUEST_UDP_OVERLOADED();
411 if (udp_listener_kill_oldest_request(proxy_context
) != 0) {
412 tcp_listener_kill_oldest_request(proxy_context
);
415 proxy_context
->connections_count
++;
416 assert(proxy_context
->connections_count
417 <= proxy_context
->connections_count_max
);
418 DNSCRYPT_PROXY_STATUS_REQUESTS_ACTIVE(proxy_context
->connections_count
,
419 proxy_context
->connections_count_max
);
420 DNSCRYPT_PROXY_REQUEST_UDP_START(udp_request
);
421 TAILQ_INSERT_TAIL(&proxy_context
->udp_request_queue
,
423 memset(&udp_request
->status
, 0, sizeof udp_request
->status
);
424 udp_request
->status
.is_in_queue
= 1;
426 dns_query_len
= (size_t) nread
;
427 assert(dns_query_len
<= sizeof dns_query
);
429 edns_add_section(proxy_context
, dns_query
, &dns_query_len
,
430 sizeof dns_query
, &request_edns_payload_size
);
432 if (request_edns_payload_size
< DNS_MAX_PACKET_SIZE_UDP_SEND
) {
433 max_query_size
= DNS_MAX_PACKET_SIZE_UDP_SEND
;
435 max_query_size
= request_edns_payload_size
;
437 if (max_query_size
> sizeof dns_query
) {
438 max_query_size
= sizeof dns_query
;
440 assert(max_query_size
<= sizeof dns_query
);
441 if (udp_request
->proxy_context
->tcp_only
!= 0) {
442 proxy_client_send_truncated(udp_request
, dns_query
, dns_query_len
);
446 size_t max_query_size_for_filter
= dns_query_len
;
447 if (max_query_size
> DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size()) {
448 max_query_size_for_filter
= max_query_size
-
449 (DNSCRYPT_MAX_PADDING
+ dnscrypt_query_header_size());
451 DCPluginDNSPacket dcp_packet
= {
452 .client_sockaddr
= &udp_request
->client_sockaddr
,
453 .dns_packet
= dns_query
,
454 .dns_packet_len_p
= &dns_query_len
,
455 .client_sockaddr_len_s
= (size_t) udp_request
->client_sockaddr_len
,
456 .dns_packet_max_len
= max_query_size_for_filter
458 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_START(udp_request
, dns_query_len
,
459 max_query_size_for_filter
);
460 assert(proxy_context
->app_context
->dcps_context
!= NULL
);
461 const DCPluginSyncFilterResult res
=
462 plugin_support_context_apply_sync_pre_filters
463 (proxy_context
->app_context
->dcps_context
, &dcp_packet
);
464 assert(dns_query_len
> (size_t) 0U && dns_query_len
<= max_query_size
&&
465 dns_query_len
<= max_query_size_for_filter
);
467 case DCP_SYNC_FILTER_RESULT_OK
:
469 case DCP_SYNC_FILTER_RESULT_DIRECT
:
470 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(udp_request
, dns_query_len
,
471 max_query_size_for_filter
);
472 proxy_to_client_direct(udp_request
, dns_query
, dns_query_len
);
475 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_ERROR(udp_request
, res
);
476 udp_request_kill(udp_request
);
479 DNSCRYPT_PROXY_REQUEST_PLUGINS_PRE_DONE(udp_request
, dns_query_len
,
480 max_query_size_for_filter
);
482 assert(SIZE_MAX
- DNSCRYPT_MAX_PADDING
- dnscrypt_query_header_size()
484 size_t max_len
= dns_query_len
+ DNSCRYPT_MAX_PADDING
+
485 dnscrypt_query_header_size();
486 if (max_len
> max_query_size
) {
487 max_len
= max_query_size
;
489 if (dns_query_len
+ dnscrypt_query_header_size() > max_len
) {
490 proxy_client_send_truncated(udp_request
, dns_query
, dns_query_len
);
493 DNSCRYPT_PROXY_REQUEST_CURVE_START(udp_request
, dns_query_len
);
495 dnscrypt_client_curve(&udp_request
->proxy_context
->dnscrypt_client
,
496 udp_request
->client_nonce
, dns_query
,
497 dns_query_len
, max_len
);
498 if (curve_ret
<= (ssize_t
) 0) {
499 DNSCRYPT_PROXY_REQUEST_CURVE_ERROR(udp_request
);
502 dns_query_len
= (size_t) curve_ret
;
503 assert(dns_query_len
>= dnscrypt_query_header_size());
504 DNSCRYPT_PROXY_REQUEST_CURVE_DONE(udp_request
, dns_query_len
);
505 assert(dns_query_len
<= sizeof dns_query
);
507 udp_request
->timeout_timer
=
508 evtimer_new(udp_request
->proxy_context
->event_loop
,
509 timeout_timer_cb
, udp_request
);
510 if (udp_request
->timeout_timer
!= NULL
) {
511 const struct timeval tv
= {
512 .tv_sec
= (time_t) DNS_QUERY_TIMEOUT
, .tv_usec
= 0
514 evtimer_add(udp_request
->timeout_timer
, &tv
);
516 sendto_with_retry(& (SendtoWithRetryCtx
) {
517 .udp_request
= udp_request
,
518 .handle
= proxy_context
->udp_proxy_resolver_handle
,
520 .length
= dns_query_len
,
522 .dest_addr
= (struct sockaddr
*) &proxy_context
->resolver_sockaddr
,
523 .dest_len
= proxy_context
->resolver_sockaddr_len
,
524 .cb
= client_to_proxy_cb_sendto_cb
529 udp_listener_kill_oldest_request(ProxyContext
* const proxy_context
)
531 if (TAILQ_EMPTY(&proxy_context
->udp_request_queue
)) {
534 udp_request_kill(TAILQ_FIRST(&proxy_context
->udp_request_queue
));
540 udp_listener_bind(ProxyContext
* const proxy_context
)
542 assert(proxy_context
->udp_listener_handle
== -1);
543 if ((proxy_context
->udp_listener_handle
= socket
544 (proxy_context
->local_sockaddr
.ss_family
,
545 SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
546 logger(NULL
, LOG_ERR
, "Unable to create a socket (UDP)");
549 evutil_make_socket_closeonexec(proxy_context
->udp_listener_handle
);
550 evutil_make_socket_nonblocking(proxy_context
->udp_listener_handle
);
551 if (bind(proxy_context
->udp_listener_handle
,
552 (struct sockaddr
*) &proxy_context
->local_sockaddr
,
553 proxy_context
->local_sockaddr_len
) != 0) {
554 logger(NULL
, LOG_ERR
, "Unable to bind (UDP) [%s]",
555 evutil_socket_error_to_string
556 (evutil_socket_geterror(proxy_context
->udp_listener_handle
)));
557 evutil_closesocket(proxy_context
->udp_listener_handle
);
558 proxy_context
->udp_listener_handle
= -1;
561 udp_tune(proxy_context
->udp_listener_handle
);
563 if ((proxy_context
->udp_proxy_resolver_handle
= socket
564 (proxy_context
->resolver_sockaddr
.ss_family
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1) {
565 logger_noformat(proxy_context
, LOG_ERR
,
566 "Unable to create a socket to the resolver");
567 evutil_closesocket(proxy_context
->udp_listener_handle
);
568 proxy_context
->udp_listener_handle
= -1;
571 evutil_make_socket_closeonexec(proxy_context
->udp_proxy_resolver_handle
);
572 evutil_make_socket_nonblocking(proxy_context
->udp_proxy_resolver_handle
);
573 udp_tune(proxy_context
->udp_proxy_resolver_handle
);
575 TAILQ_INIT(&proxy_context
->udp_request_queue
);
581 udp_listener_start(ProxyContext
* const proxy_context
)
583 assert(proxy_context
->udp_listener_handle
!= -1);
584 if ((proxy_context
->udp_listener_event
=
585 event_new(proxy_context
->event_loop
,
586 proxy_context
->udp_listener_handle
, EV_READ
| EV_PERSIST
,
587 client_to_proxy_cb
, proxy_context
)) == NULL
) {
590 if (event_add(proxy_context
->udp_listener_event
, NULL
) != 0) {
591 udp_listener_stop(proxy_context
);
595 assert(proxy_context
->udp_proxy_resolver_handle
!= -1);
596 if ((proxy_context
->udp_proxy_resolver_event
=
597 event_new(proxy_context
->event_loop
,
598 proxy_context
->udp_proxy_resolver_handle
,
599 EV_READ
| EV_PERSIST
,
600 resolver_to_proxy_cb
, proxy_context
)) == NULL
) {
601 udp_listener_stop(proxy_context
);
604 if (event_add(proxy_context
->udp_proxy_resolver_event
, NULL
) != 0) {
605 udp_listener_stop(proxy_context
);
612 udp_listener_stop(ProxyContext
* const proxy_context
)
614 event_free(proxy_context
->udp_proxy_resolver_event
);
615 proxy_context
->udp_proxy_resolver_event
= NULL
;
616 while (udp_listener_kill_oldest_request(proxy_context
) != 0) { }
617 logger_noformat(proxy_context
, LOG_INFO
, "UDP listener shut down");