1 #include "dnscrypt.h"
2 #include "block.h"
3 
4 typedef struct SendtoWithRetryCtx_ {
5     void (*cb) (UDPRequest *udp_request);
6     const void *buffer;
7     UDPRequest *udp_request;
8     const struct sockaddr *dest_addr;
9     evutil_socket_t handle;
10     size_t length;
11     ev_socklen_t dest_len;
12     int flags;
13 } SendtoWithRetryCtx;
14 
15 /* Forward declarations. */
16 static int sendto_with_retry(SendtoWithRetryCtx *const ctx);
17 
18 #ifndef UDP_BUFFER_SIZE
19 # define UDP_BUFFER_SIZE 2097152
20 #endif
21 #ifndef UDP_DELAY_BETWEEN_RETRIES
22 # define UDP_DELAY_BETWEEN_RETRIES 1
23 #endif
24 
25 #ifndef SO_RCVBUFFORCE
26 # define SO_RCVBUFFORCE SO_RCVBUF
27 #endif
28 #ifndef SO_SNDBUFFORCE
29 # define SO_SNDBUFFORCE SO_SNDBUF
30 #endif
31 
32 #ifndef EVUTIL_ERR_RW_RETRIABLE
33 # ifndef _WIN32
34 #  define EVUTIL_ERR_RW_RETRIABLE(e) ((e) == EINTR || (e) == EAGAIN)
35 # else
36 #  define EVUTIL_ERR_RW_RETRIABLE(e) ((e) == WSAEWOULDBLOCK || (e) == WSAEINTR)
37 # endif
38 #endif
39 
udp_request_cmp(const UDPRequest * r1,const UDPRequest * r2)40 static int udp_request_cmp(const UDPRequest *r1, const UDPRequest *r2) {
41     if (r1->hash < r2->hash) {
42         return -1;
43     } else if (r1->hash > r2->hash) {
44         return 1;
45     } else if (r1->id < r2->id) {
46         return -1;
47     } else if (r1->id > r2->id) {
48         return 1;
49     } else if (r1->gen < r2->gen) {
50         return -1;
51     } else if (r1->gen > r2->gen) {
52         return 1;
53     }
54     return 0;
55 }
56 
RB_GENERATE_STATIC(UDPRequestQueue_,UDPRequest_,queue,udp_request_cmp)57 RB_GENERATE_STATIC(UDPRequestQueue_, UDPRequest_, queue, udp_request_cmp)
58 
59 static void
60 udp_tune(evutil_socket_t const handle)
61 {
62     if (handle == -1) {
63         return;
64     }
65     setsockopt(handle, IPPROTO_IP, IP_TOS, (void *) (int []) {
66                        0x70}, sizeof(int));
67     setsockopt(handle, SOL_SOCKET, SO_RCVBUFFORCE, (void *)(int[]) {
68                UDP_BUFFER_SIZE}, sizeof(int));
69     setsockopt(handle, SOL_SOCKET, SO_SNDBUFFORCE, (void *)(int[]) {
70                UDP_BUFFER_SIZE}, sizeof(int));
71 #if defined(IP_PMTUDISC_OMIT)
72     setsockopt(handle, IPPROTO_IP, IP_MTU_DISCOVER,
73                (void *) (int []) { IP_PMTUDISC_OMIT }, sizeof (int));
74 #elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
75     setsockopt(handle, IPPROTO_IP, IP_MTU_DISCOVER, (void *)(int[]) {
76                IP_PMTUDISC_DONT}, sizeof(int));
77 #elif defined(IP_DONTFRAG)
78     setsockopt(handle, IPPROTO_IP, IP_DONTFRAG, (void *)(int[]) {
79                0}, sizeof(int));
80 #endif
81 #if defined(__linux__) && defined(SO_REUSEPORT)
82     setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, (void *)(int[]) {
83                1}, sizeof(int));
84 #endif
85 }
86 
87 static void
client_to_proxy_cb_sendto_cb(UDPRequest * const udp_request)88 client_to_proxy_cb_sendto_cb(UDPRequest *const udp_request)
89 {
90     (void)udp_request;
91 }
92 
93 static void
udp_request_kill(UDPRequest * const udp_request)94 udp_request_kill(UDPRequest *const udp_request)
95 {
96     if (udp_request == NULL || udp_request->status.is_dying)
97         return;
98 
99     udp_request->status.is_dying = 1;
100 
101     // free
102     struct context *c;
103     if (udp_request->sendto_retry_timer != NULL) {
104         free(event_get_callback_arg(udp_request->sendto_retry_timer));
105         event_free(udp_request->sendto_retry_timer);
106         udp_request->sendto_retry_timer = NULL;
107     }
108     if (udp_request->timeout_timer != NULL) {
109         event_free(udp_request->timeout_timer);
110         udp_request->timeout_timer = NULL;
111     }
112 
113     c = udp_request->context;
114     if (udp_request->status.is_in_queue != 0) {
115         assert(!RB_EMPTY(&c->udp_request_queue));
116         RB_REMOVE(UDPRequestQueue_, &c->udp_request_queue, udp_request);
117         assert(c->connections > 0);
118         c->connections--;
119     }
120 
121     udp_request->context = NULL;
122     free(udp_request);
123 }
124 
125 int
udp_listener_kill_oldest_request(struct context * c)126 udp_listener_kill_oldest_request(struct context *c)
127 {
128     if (RB_EMPTY(&c->udp_request_queue))
129         return -1;
130 
131     udp_request_kill(RB_MIN(UDPRequestQueue_, &c->udp_request_queue));
132 
133     return 0;
134 }
135 
136 static void
sendto_with_retry_timer_cb(evutil_socket_t retry_timer_handle,short ev_flags,void * const ctx_)137 sendto_with_retry_timer_cb(evutil_socket_t retry_timer_handle, short ev_flags,
138                            void *const ctx_)
139 {
140     SendtoWithRetryCtx *const ctx = ctx_;
141 
142     (void)ev_flags;
143     assert(retry_timer_handle ==
144            event_get_fd(ctx->udp_request->sendto_retry_timer));
145 
146     sendto_with_retry(ctx);
147 }
148 
149 static int
sendto_with_retry(SendtoWithRetryCtx * const ctx)150 sendto_with_retry(SendtoWithRetryCtx *const ctx)
151 {
152     void (*cb) (UDPRequest *udp_request);
153     SendtoWithRetryCtx *ctx_cb;
154     UDPRequest *udp_request = ctx->udp_request;
155     int err;
156     bool retriable;
157 
158     if (sendto(ctx->handle, ctx->buffer, ctx->length, ctx->flags,
159                ctx->dest_addr, ctx->dest_len) == (ssize_t) ctx->length) {
160         cb = ctx->cb;
161         if (udp_request->sendto_retry_timer != NULL) {
162             ctx_cb = event_get_callback_arg(udp_request->sendto_retry_timer);
163             assert(ctx_cb != NULL);
164             assert(ctx_cb->udp_request == ctx->udp_request);
165             assert(ctx_cb->buffer == ctx->buffer);
166             free(ctx_cb);
167             event_free(udp_request->sendto_retry_timer);
168             udp_request->sendto_retry_timer = NULL;
169         }
170         if (cb) {
171             cb(udp_request);
172         }
173         return 0;
174     }
175 
176     err = evutil_socket_geterror(udp_request->client_proxy_handle);
177     logger(LOG_WARNING, "sendto: [%s]", evutil_socket_error_to_string(err));
178 
179     retriable = (err == ENOBUFS || err == ENOMEM ||
180                  err == EAGAIN || err == EINTR);
181 
182     if (retriable == 0) {
183         udp_request_kill(udp_request);
184         return -1;
185     }
186     assert(DNS_QUERY_TIMEOUT < UCHAR_MAX);
187     if (++(udp_request->retries) > DNS_QUERY_TIMEOUT) {
188         udp_request_kill(udp_request);
189         return -1;
190     }
191     if (udp_request->sendto_retry_timer != NULL) {
192         ctx_cb = event_get_callback_arg(udp_request->sendto_retry_timer);
193         assert(ctx_cb != NULL);
194         assert(ctx_cb->udp_request == ctx->udp_request);
195         assert(ctx_cb->buffer == ctx->buffer);
196     } else {
197         if ((ctx_cb = malloc(sizeof *ctx_cb)) == NULL) {
198             udp_request_kill(udp_request);
199             return -1;
200         }
201         assert(ctx_cb ==
202                event_get_callback_arg(udp_request->sendto_retry_timer));
203         *ctx_cb = *ctx;
204         if ((udp_request->sendto_retry_timer =
205              evtimer_new(udp_request->context->event_loop,
206                          sendto_with_retry_timer_cb, ctx_cb)) == NULL) {
207             free(ctx_cb);
208             udp_request_kill(udp_request);
209             return -1;
210         }
211     }
212     const struct timeval tv = {
213         .tv_sec = (time_t) UDP_DELAY_BETWEEN_RETRIES,.tv_usec = 0
214     };
215     evtimer_add(udp_request->sendto_retry_timer, &tv);
216     return -1;
217 
218 }
219 
220 static void
timeout_timer_cb(evutil_socket_t timeout_timer_handle,short ev_flags,void * const udp_request_)221 timeout_timer_cb(evutil_socket_t timeout_timer_handle, short ev_flags,
222                  void *const udp_request_)
223 {
224     UDPRequest *const udp_request = udp_request_;
225 
226     (void)ev_flags;
227     (void)timeout_timer_handle;
228     logger(LOG_DEBUG, "resolver timeout (UDP)");
229     udp_request_kill(udp_request);
230 }
231 
232 /**
233  * Return 0 if served.
234  */
235 static int
self_serve_cert_file(struct context * c,struct dns_header * header,size_t dns_query_len,size_t max_len,UDPRequest * udp_request)236 self_serve_cert_file(struct context *c, struct dns_header *header,
237                      size_t dns_query_len, size_t max_len, UDPRequest *udp_request)
238 {
239     int ret = dnscrypt_self_serve_cert_file(c, header, &dns_query_len, max_len);
240     if (ret == 0) {
241         SendtoWithRetryCtx retry_ctx = {
242             .udp_request = udp_request,
243             .handle = udp_request->client_proxy_handle,
244             .buffer = header,
245             .length = dns_query_len,
246             .flags = 0,
247             .dest_addr = (struct sockaddr *)&udp_request->client_sockaddr,
248             .dest_len = udp_request->client_sockaddr_len,
249             .cb = udp_request_kill
250         };
251         sendto_with_retry(&retry_ctx);
252         return 0;
253     }
254     logger(LOG_DEBUG, "failed to serve cert file, err: %d", ret);
255     return ret;
256 }
257 
258 static void
client_to_proxy_cb(evutil_socket_t client_proxy_handle,short ev_flags,void * const context)259 client_to_proxy_cb(evutil_socket_t client_proxy_handle, short ev_flags,
260                    void *const context)
261 {
262     logger(LOG_DEBUG, "client to proxy cb");
263     const size_t sizeof_dns_query = DNS_MAX_PACKET_SIZE_UDP;
264     static uint8_t *dns_query = NULL;
265     struct context *c = context;
266     UDPRequest *udp_request;
267     ssize_t nread;
268     size_t dns_query_len = 0;
269 
270     if (dns_query == NULL && (dns_query = sodium_malloc(sizeof_dns_query)) == NULL) {
271         return;
272     }
273     (void)ev_flags;
274     assert(client_proxy_handle == c->udp_listener_handle);
275 
276     udp_request = calloc(1, sizeof(*udp_request));
277     if (udp_request == NULL)
278         return;
279 
280     udp_request->context = c;
281     udp_request->sendto_retry_timer = NULL;
282     udp_request->timeout_timer = NULL;
283     udp_request->client_proxy_handle = client_proxy_handle;
284     udp_request->client_sockaddr_len = sizeof(udp_request->client_sockaddr);
285     memset(&udp_request->status, 0, sizeof(udp_request->status));
286     nread = recvfrom(client_proxy_handle,
287                      (void *)dns_query,
288                      sizeof_dns_query,
289                      0,
290                      (struct sockaddr *)&udp_request->client_sockaddr,
291                      &udp_request->client_sockaddr_len);
292     if (nread < 0) {
293         const int err = evutil_socket_geterror(client_proxy_handle);
294         if (!EVUTIL_ERR_RW_RETRIABLE(err)) {
295             logger(LOG_WARNING, "recvfrom(client): [%s]",
296                    evutil_socket_error_to_string(err));
297         }
298         udp_request_kill(udp_request);
299         return;
300     }
301 
302     if (nread < (ssize_t) DNS_HEADER_SIZE || nread > sizeof_dns_query) {
303         logger(LOG_WARNING, "Short query received");
304         udp_request_kill(udp_request);
305         return;
306     }
307 
308     dns_query_len = (size_t) nread;
309     assert(dns_query_len <= sizeof_dns_query);
310 
311     assert(SIZE_MAX - DNSCRYPT_MAX_PADDING - DNSCRYPT_QUERY_HEADER_SIZE >
312            dns_query_len);
313 
314     udp_request->len = (uint16_t) dns_query_len;
315     // decrypt if encrypted
316     struct dnscrypt_query_header *dnscrypt_header =
317         (struct dnscrypt_query_header *)dns_query;
318     debug_assert(sizeof c->keypairs[0].crypt_publickey >= DNSCRYPT_MAGIC_HEADER_LEN);
319     if ((udp_request->cert =
320          find_cert(c, dnscrypt_header->magic_query, dns_query_len)) == NULL) {
321         udp_request->is_dnscrypted = false;
322     } else {
323         if (dnscrypt_server_uncurve(c, udp_request->cert,
324                                     udp_request->client_nonce,
325                                     udp_request->nmkey, dns_query,
326                                     &dns_query_len) != 0 || dns_query_len < DNS_HEADER_SIZE) {
327             logger(LOG_DEBUG, "Received a suspicious query from the client");
328             udp_request_kill(udp_request);
329             return;
330         }
331         udp_request->is_dnscrypted = true;
332     }
333 
334     struct dns_header *header = (struct dns_header *)dns_query;
335 
336     // self serve signed certificate for provider name?
337     if (!udp_request->is_dnscrypted) {
338         if (self_serve_cert_file(c, header, dns_query_len, sizeof_dns_query, udp_request) == 0)
339             return;
340         if (!c->allow_not_dnscrypted) {
341             logger(LOG_DEBUG, "Unauthenticated query received over UDP");
342             udp_request_kill(udp_request);
343             return;
344         }
345     }
346 
347     udp_request->is_blocked = is_blocked(c, header, dns_query_len);
348 
349     udp_request->id = ntohs(header->id);
350     if (questions_hash(&udp_request->hash, header, dns_query_len, c->namebuff, c->hash_key) != 0) {
351         logger(LOG_DEBUG, "Received a suspicious query from the client");
352         udp_request_kill(udp_request);
353         return;
354     }
355 
356     static uint16_t gen;
357     udp_request->gen = gen++;
358     udp_request->status.is_in_queue = 1;
359     c->connections++;
360     RB_INSERT(UDPRequestQueue_, &c->udp_request_queue, udp_request);
361 
362     udp_request->timeout_timer =
363         evtimer_new(udp_request->context->event_loop, timeout_timer_cb,
364                     udp_request);
365     if (udp_request->timeout_timer) {
366         const struct timeval tv = {
367             .tv_sec = (time_t) DNS_QUERY_TIMEOUT,.tv_usec = 0
368         };
369         evtimer_add(udp_request->timeout_timer, &tv);
370     }
371 
372     SendtoWithRetryCtx retry_ctx = {
373         .udp_request = udp_request,.handle =
374             c->udp_resolver_handle,.buffer = dns_query,.length =
375             dns_query_len,.flags = 0,.dest_addr =
376             (struct sockaddr *)&c->resolver_sockaddr,.dest_len =
377             c->resolver_sockaddr_len,.cb = client_to_proxy_cb_sendto_cb
378     };
379     sendto_with_retry(&retry_ctx);
380 }
381 
382 /*
383  * Find corresponding request by DNS id and hash of questions.
384  */
385 static UDPRequest *
lookup_request(struct context * c,uint16_t id,uint64_t hash)386 lookup_request(struct context *c, uint16_t id, uint64_t hash)
387 {
388     UDPRequest *found_udp_request;
389     UDPRequest scanned_udp_request;
390 
391     scanned_udp_request.hash = hash;
392     scanned_udp_request.id = id;
393     scanned_udp_request.gen = (uint16_t) 0U;
394     found_udp_request = RB_NFIND(UDPRequestQueue_, &c->udp_request_queue,
395                                  &scanned_udp_request);
396     if (found_udp_request == NULL ||
397         found_udp_request->hash != hash || found_udp_request->id != id) {
398         return NULL;
399     }
400     return found_udp_request;
401 }
402 
403 static int
maybe_truncate(uint8_t * const dns_reply,size_t * const dns_reply_len_p,size_t query_len)404 maybe_truncate(uint8_t *const dns_reply, size_t *const dns_reply_len_p, size_t query_len)
405 {
406     struct dns_header *header = (struct dns_header *)dns_reply;
407     uint8_t *ansp;
408 
409     if (*dns_reply_len_p <= sizeof(struct dns_header)) {
410         *dns_reply_len_p = 0;
411         return -1;
412     }
413     if (query_len >= *dns_reply_len_p) {
414         return 0;
415     }
416     if (!(ansp = skip_questions(header, *dns_reply_len_p))) {
417         *dns_reply_len_p = sizeof(struct dns_header);
418         return -1;
419     }
420     *dns_reply_len_p = (size_t) (ansp - dns_reply);
421     header->hb3 |= HB3_TC;
422     header->ancount = htons(0);
423     header->nscount = htons(0);
424     header->arcount = htons(0);
425 
426     return 0;
427 }
428 
429 static void
resolver_to_proxy_cb(evutil_socket_t proxy_resolver_handle,short ev_flags,void * const context)430 resolver_to_proxy_cb(evutil_socket_t proxy_resolver_handle, short ev_flags,
431                      void *const context)
432 {
433     logger(LOG_DEBUG, "resolver to proxy cb");
434     const size_t sizeof_dns_reply = DNS_MAX_PACKET_SIZE_UDP;
435     static uint8_t *dns_reply = NULL;
436     struct context *c = context;
437     UDPRequest *udp_request = NULL;
438     struct sockaddr_storage resolver_sockaddr;
439     ev_socklen_t resolver_sockaddr_len = sizeof(struct sockaddr_storage);
440     ssize_t nread;
441     size_t dns_reply_len = (size_t) 0U;
442 
443     (void)ev_flags;
444     if (dns_reply == NULL && (dns_reply = sodium_malloc(sizeof_dns_reply)) == NULL) {
445         return;
446     }
447     nread = recvfrom(proxy_resolver_handle,
448                      (void *)dns_reply, sizeof_dns_reply, 0,
449                      (struct sockaddr *)&resolver_sockaddr,
450                      &resolver_sockaddr_len);
451     if (nread < 0) {
452         const int err = evutil_socket_geterror(proxy_resolver_handle);
453         if (!EVUTIL_ERR_RW_RETRIABLE(err)) {
454             logger(LOG_WARNING, "recvfrom(resolver): [%s]",
455                    evutil_socket_error_to_string(err));
456         }
457         return;
458     }
459     if (evutil_sockaddr_cmp((const struct sockaddr *)&resolver_sockaddr,
460                             (const struct sockaddr *)
461                             &c->resolver_sockaddr, 1) != 0) {
462         logger(LOG_WARNING,
463                "Received a resolver reply from a different resolver");
464         return;
465     }
466     dns_reply_len = nread;
467 
468     struct dns_header *header = (struct dns_header *)dns_reply;
469     uint16_t id = ntohs(header->id);
470     uint64_t hash;
471     if (questions_hash(&hash, header, dns_reply_len, c->namebuff, c->hash_key) != 0) {
472         logger(LOG_ERR, "Received an invalid response from the server");
473         return;
474     }
475     udp_request = lookup_request(c, id, hash);
476     if (udp_request == NULL) {
477         logger(LOG_DEBUG, "Received a reply that doesn't match any active query");
478         return;
479     }
480     size_t max_reply_size = DNS_MAX_PACKET_SIZE_UDP;
481     size_t max_len =
482         dns_reply_len + DNSCRYPT_MAX_PADDING + DNSCRYPT_REPLY_HEADER_SIZE;
483     if (max_len > max_reply_size)
484         max_len = max_reply_size;
485 
486     if (udp_request->is_blocked) {
487         struct dns_header *p = (struct dns_header *) dns_reply;
488         SET_RCODE(p, REFUSED);
489     }
490     maybe_truncate(dns_reply, &dns_reply_len, udp_request->len);
491 
492     if (udp_request->is_dnscrypted) {
493         if (dnscrypt_server_curve
494             (c, udp_request->cert, udp_request->client_nonce, udp_request->nmkey, dns_reply,
495              &dns_reply_len, max_len) != 0) {
496             logger(LOG_ERR, "Curving reply failed.");
497             return;
498         }
499     }
500 
501     SendtoWithRetryCtx retry_ctx = {
502         .udp_request = udp_request,.handle =
503             udp_request->client_proxy_handle,.buffer =
504             dns_reply,.length = dns_reply_len,.flags = 0,.dest_addr =
505             (struct sockaddr *)&udp_request->client_sockaddr,.dest_len =
506             udp_request->client_sockaddr_len,.cb = udp_request_kill
507     };
508     sendto_with_retry(&retry_ctx);
509 }
510 
511 int
udp_listener_bind(struct context * c)512 udp_listener_bind(struct context *c)
513 {
514     // listen socket & bind
515     assert(c->udp_listener_handle == -1);
516 
517     if ((c->udp_listener_handle =
518          socket(c->local_sockaddr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
519         logger(LOG_ERR, "Unable to create a socket (UDP)");
520         return -1;
521     }
522 
523     udp_tune(c->udp_listener_handle);
524 
525     evutil_make_socket_closeonexec(c->udp_listener_handle);
526     evutil_make_socket_nonblocking(c->udp_listener_handle);
527     if (bind
528         (c->udp_listener_handle, (struct sockaddr *)&c->local_sockaddr,
529          c->local_sockaddr_len) != 0) {
530         logger(LOG_ERR, "Unable to bind (UDP) [%s]",
531                evutil_socket_error_to_string(evutil_socket_geterror
532                                              (c->udp_listener_handle)));
533         evutil_closesocket(c->udp_listener_handle);
534         c->udp_listener_handle = -1;
535         return -1;
536     }
537 
538     // resolver socket
539     assert(c->udp_resolver_handle == -1);
540     if ((c->udp_resolver_handle =
541          socket(c->resolver_sockaddr.ss_family, SOCK_DGRAM,
542                 IPPROTO_UDP)) == -1) {
543         logger(LOG_ERR, "Unable to create a socket to the resolver");
544         evutil_closesocket(c->udp_resolver_handle);
545         c->udp_listener_handle = -1;
546     }
547     evutil_make_socket_closeonexec(c->udp_resolver_handle);
548     evutil_make_socket_nonblocking(c->udp_resolver_handle);
549     udp_tune(c->udp_resolver_handle);
550 
551     /* Bind source IP:port if --outgoing-address is provided */
552     if(c->outgoing_address &&
553        bind(c->udp_resolver_handle, (struct sockaddr *)&c->outgoing_sockaddr,
554             c->outgoing_sockaddr_len) != 0) {
555         logger(LOG_ERR, "Unable to bind (UDP) [%s]",
556             evutil_socket_error_to_string(evutil_socket_geterror
557                                           (c->udp_resolver_handle)));
558         evutil_closesocket(c->udp_resolver_handle);
559         c->udp_resolver_handle = -1;
560         return -1;
561     }
562 
563     RB_INIT(&c->udp_request_queue);
564 
565     return 0;
566 }
567 
568 void
udp_listener_stop(struct context * c)569 udp_listener_stop(struct context *c)
570 {
571     event_free(c->udp_resolver_event);
572     c->udp_resolver_event = NULL;
573 
574     while (udp_listener_kill_oldest_request(c) == 0);
575     logger(LOG_INFO, "UDP listener shut down");
576 }
577 
578 int
udp_listener_start(struct context * c)579 udp_listener_start(struct context *c)
580 {
581     assert(c->udp_listener_handle != -1);
582     if ((c->udp_listener_event =
583          event_new(c->event_loop, c->udp_listener_handle, EV_READ | EV_PERSIST,
584                    client_to_proxy_cb, c)) == NULL) {
585         return -1;
586     }
587     if (event_add(c->udp_listener_event, NULL) != 0) {
588         udp_listener_stop(c);
589         return -1;
590     }
591 
592     assert(c->udp_resolver_handle != -1);
593     if ((c->udp_resolver_event =
594          event_new(c->event_loop, c->udp_resolver_handle, EV_READ | EV_PERSIST,
595                    resolver_to_proxy_cb, c)) == NULL) {
596         udp_listener_stop(c);
597         return -1;
598     }
599     if (event_add(c->udp_resolver_event, NULL) != 0) {
600         udp_listener_stop(c);
601         return -1;
602     }
603     return 0;
604 }
605