Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2006-2007 Niels Provos |
2 | | * Copyright 2007-2012 Nick Mathewson and Niels Provos |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or without |
5 | | * modification, are permitted provided that the following conditions |
6 | | * are met: |
7 | | * 1. Redistributions of source code must retain the above copyright |
8 | | * notice, this list of conditions and the following disclaimer. |
9 | | * 2. Redistributions in binary form must reproduce the above copyright |
10 | | * notice, this list of conditions and the following disclaimer in the |
11 | | * documentation and/or other materials provided with the distribution. |
12 | | * 3. The name of the author may not be used to endorse or promote products |
13 | | * derived from this software without specific prior written permission. |
14 | | * |
15 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
16 | | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
17 | | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
18 | | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
19 | | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
20 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
21 | | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
22 | | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
23 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | | */ |
26 | | |
27 | | /* Based on software by Adam Langly. Adam's original message: |
28 | | * |
29 | | * Async DNS Library |
30 | | * Adam Langley <agl@imperialviolet.org> |
31 | | * Public Domain code |
32 | | * |
33 | | * This software is Public Domain. To view a copy of the public domain dedication, |
34 | | * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to |
35 | | * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. |
36 | | * |
37 | | * I ask and expect, but do not require, that all derivative works contain an |
38 | | * attribution similar to: |
39 | | * Parts developed by Adam Langley <agl@imperialviolet.org> |
40 | | * |
41 | | * You may wish to replace the word "Parts" with something else depending on |
42 | | * the amount of original code. |
43 | | * |
44 | | * (Derivative works does not include programs which link against, run or include |
45 | | * the source verbatim in their source distributions) |
46 | | * |
47 | | * Version: 0.1b |
48 | | */ |
49 | | |
50 | | #include "event2/event-config.h" |
51 | | #include "evconfig-private.h" |
52 | | |
53 | | #include <sys/types.h> |
54 | | |
55 | | #ifndef _FORTIFY_SOURCE |
56 | | #define _FORTIFY_SOURCE 3 |
57 | | #endif |
58 | | |
59 | | #include <string.h> |
60 | | #include <fcntl.h> |
61 | | #ifdef EVENT__HAVE_SYS_TIME_H |
62 | | #include <sys/time.h> |
63 | | #endif |
64 | | #ifdef EVENT__HAVE_STDINT_H |
65 | | #include <stdint.h> |
66 | | #endif |
67 | | #include <stdlib.h> |
68 | | #include <string.h> |
69 | | #include <errno.h> |
70 | | #ifdef EVENT__HAVE_UNISTD_H |
71 | | #include <unistd.h> |
72 | | #endif |
73 | | #include <limits.h> |
74 | | #include <sys/stat.h> |
75 | | #include <stdio.h> |
76 | | #include <stdarg.h> |
77 | | #include <sys/tree.h> |
78 | | #ifdef _WIN32 |
79 | | #include <winsock2.h> |
80 | | #include <winerror.h> |
81 | | #include <ws2tcpip.h> |
82 | | #ifndef _WIN32_IE |
83 | | #define _WIN32_IE 0x400 |
84 | | #endif |
85 | | #include <shlobj.h> |
86 | | #define strcasecmp strcmpi |
87 | | #endif |
88 | | |
89 | | #include "event2/buffer.h" |
90 | | #include "event2/bufferevent.h" |
91 | | #include "event2/dns.h" |
92 | | #include "event2/dns_struct.h" |
93 | | #include "event2/dns_compat.h" |
94 | | #include "event2/util.h" |
95 | | #include "event2/event.h" |
96 | | #include "event2/event_struct.h" |
97 | | #include "event2/listener.h" |
98 | | #include "event2/thread.h" |
99 | | |
100 | | #include "defer-internal.h" |
101 | | #include "log-internal.h" |
102 | | #include "mm-internal.h" |
103 | | #include "strlcpy-internal.h" |
104 | | #include "ipv6-internal.h" |
105 | | #include "util-internal.h" |
106 | | #include "evthread-internal.h" |
107 | | #include "evdns-internal.h" |
108 | | #ifdef _WIN32 |
109 | | #include <ctype.h> |
110 | | #include <winsock2.h> |
111 | | #include <windows.h> |
112 | | #include <iphlpapi.h> |
113 | | #include <io.h> |
114 | | #else |
115 | | #include <sys/socket.h> |
116 | | #include <netinet/in.h> |
117 | | #include <arpa/inet.h> |
118 | | #endif |
119 | | |
120 | | #ifdef EVENT__HAVE_NETINET_IN6_H |
121 | | #include <netinet/in6.h> |
122 | | #endif |
123 | | |
124 | 0 | #define EVDNS_LOG_DEBUG EVENT_LOG_DEBUG |
125 | 0 | #define EVDNS_LOG_WARN EVENT_LOG_WARN |
126 | 0 | #define EVDNS_LOG_MSG EVENT_LOG_MSG |
127 | | |
128 | | #ifndef EVDNS_NAME_MAX |
129 | | #define EVDNS_NAME_MAX 255 |
130 | | #endif |
131 | | |
132 | | #include <stdio.h> |
133 | | |
134 | | #undef MIN |
135 | | #undef MAX |
136 | 0 | #define MIN(a,b) ((a)<(b)?(a):(b)) |
137 | 0 | #define MAX(a,b) ((a)>(b)?(a):(b)) |
138 | | |
139 | | #define ASSERT_VALID_REQUEST(req) \ |
140 | 0 | EVUTIL_ASSERT((req)->handle && (req)->handle->current_req == (req)) |
141 | | |
142 | | #define u64 ev_uint64_t |
143 | 0 | #define u32 ev_uint32_t |
144 | 0 | #define u16 ev_uint16_t |
145 | 0 | #define u8 ev_uint8_t |
146 | | |
147 | | /* maximum number of addresses from a single packet */ |
148 | | /* that we bother recording */ |
149 | | #define MAX_V4_ADDRS 32 |
150 | | #define MAX_V6_ADDRS 32 |
151 | | |
152 | | /* Maximum allowable size of a DNS message over UDP without EDNS.*/ |
153 | 0 | #define DNS_MAX_UDP_SIZE 512 |
154 | | /* Maximum allowable size of a DNS message over UDP with EDNS.*/ |
155 | 0 | #define EDNS_MAX_UDP_SIZE 65535 |
156 | | |
157 | | #define EDNS_ENABLED(base) \ |
158 | 0 | (((base)->global_max_udp_size) > DNS_MAX_UDP_SIZE) |
159 | | |
160 | 0 | #define TYPE_A EVDNS_TYPE_A |
161 | 0 | #define TYPE_CNAME 5 |
162 | 0 | #define TYPE_PTR EVDNS_TYPE_PTR |
163 | 0 | #define TYPE_SOA EVDNS_TYPE_SOA |
164 | 0 | #define TYPE_AAAA EVDNS_TYPE_AAAA |
165 | 0 | #define TYPE_OPT 41 |
166 | | |
167 | 0 | #define CLASS_INET EVDNS_CLASS_INET |
168 | | |
169 | | /* Timeout in seconds for idle TCP connections that server keeps alive. */ |
170 | 0 | #define SERVER_IDLE_CONN_TIMEOUT 10 |
171 | | /* Timeout in seconds for idle TCP connections that client keeps alive. */ |
172 | 0 | #define CLIENT_IDLE_CONN_TIMEOUT 5 |
173 | | /* Default maximum number of simultaneous TCP client connections that DNS server can hold. */ |
174 | 0 | #define MAX_CLIENT_CONNECTIONS 10 |
175 | | |
176 | | struct reply { |
177 | | unsigned int type; |
178 | | unsigned int have_answer : 1; |
179 | | u32 rr_count; |
180 | | union { |
181 | | u32 *a; |
182 | | struct in6_addr *aaaa; |
183 | | char *ptr_name; |
184 | | void *raw; |
185 | | } data; |
186 | | char *cname; |
187 | | }; |
188 | | |
189 | | |
190 | | /* Persistent handle. We keep this separate from 'struct request' since we |
191 | | * need some object to last for as long as an evdns_request is outstanding so |
192 | | * that it can be canceled, whereas a search request can lead to multiple |
193 | | * 'struct request' instances being created over its lifetime. */ |
194 | | struct evdns_request { |
195 | | struct request *current_req; |
196 | | struct evdns_base *base; |
197 | | |
198 | | int pending_cb; /* Waiting for its callback to be invoked; not |
199 | | * owned by event base any more. */ |
200 | | |
201 | | /* data used when fulfilling the callback */ |
202 | | struct event_callback deferred; |
203 | | evdns_callback_type user_callback; |
204 | | void *user_pointer; |
205 | | u8 request_type; |
206 | | u8 have_reply; |
207 | | u32 ttl; |
208 | | u32 err; |
209 | | struct reply reply; |
210 | | |
211 | | /* elements used by the searching code */ |
212 | | int search_index; |
213 | | struct search_state *search_state; |
214 | | char *search_origname; /* needs to be free()ed */ |
215 | | int search_flags; |
216 | | u16 tcp_flags; |
217 | | }; |
218 | | |
219 | | struct request { |
220 | | u8 *request; /* the dns packet data */ |
221 | | u16 request_size; /* size of memory block stored in request field */ |
222 | | u8 request_type; /* TYPE_PTR or TYPE_A or TYPE_AAAA */ |
223 | | unsigned int request_len; |
224 | | int reissue_count; |
225 | | int tx_count; /* the number of times that this packet has been sent */ |
226 | | struct nameserver *ns; /* the server which we last sent it */ |
227 | | |
228 | | /* these objects are kept in a circular list */ |
229 | | /* XXX We could turn this into a CIRCLEQ. */ |
230 | | struct request *next, *prev; |
231 | | |
232 | | struct event timeout_event; |
233 | | |
234 | | u16 trans_id; /* the transaction id */ |
235 | | unsigned request_appended :1; /* true if the request pointer is data which follows this struct */ |
236 | | unsigned transmit_me :1; /* needs to be transmitted */ |
237 | | unsigned need_cname :1; /* make a separate callback for CNAME */ |
238 | | |
239 | | /* XXXX This is a horrible hack. */ |
240 | | char **put_cname_in_ptr; /* store the cname here if we get one. */ |
241 | | |
242 | | struct evdns_base *base; |
243 | | |
244 | | struct evdns_request *handle; |
245 | | }; |
246 | | |
247 | | enum tcp_state { |
248 | | TS_DISCONNECTED, |
249 | | TS_CONNECTING, |
250 | | TS_CONNECTED |
251 | | }; |
252 | | |
253 | | struct tcp_connection { |
254 | | struct bufferevent *bev; |
255 | | enum tcp_state state; |
256 | | u16 awaiting_packet_size; |
257 | | }; |
258 | | |
259 | | struct evdns_server_port; |
260 | | |
261 | | struct client_tcp_connection { |
262 | | LIST_ENTRY(client_tcp_connection) next; |
263 | | struct tcp_connection connection; |
264 | | struct evdns_server_port *port; |
265 | | }; |
266 | | |
267 | | struct nameserver { |
268 | | evutil_socket_t socket; /* a connected UDP socket */ |
269 | | struct tcp_connection *connection; /* intended for TCP support */ |
270 | | struct sockaddr_storage address; |
271 | | ev_socklen_t addrlen; |
272 | | int failed_times; /* number of times which we have given this server a chance */ |
273 | | int timedout; /* number of times in a row a request has timed out */ |
274 | | struct event event; |
275 | | /* these objects are kept in a circular list */ |
276 | | struct nameserver *next, *prev; |
277 | | struct event timeout_event; /* used to keep the timeout for */ |
278 | | /* when we next probe this server. */ |
279 | | /* Valid if state == 0 */ |
280 | | /* Outstanding probe request for this nameserver, if any */ |
281 | | struct evdns_request *probe_request; |
282 | | char state; /* zero if we think that this server is down */ |
283 | | char choked; /* true if we have an EAGAIN from this server's socket */ |
284 | | char write_waiting; /* true if we are waiting for EV_WRITE events */ |
285 | | struct evdns_base *base; |
286 | | |
287 | | /* Number of currently inflight requests: used |
288 | | * to track when we should add/del the event. */ |
289 | | int requests_inflight; |
290 | | }; |
291 | | |
292 | | |
293 | | /* Represents a local port where we're listening for DNS requests. */ |
294 | | struct evdns_server_port { |
295 | | evutil_socket_t socket; /* socket we use to read queries and write replies. */ |
296 | | int refcnt; /* reference count. */ |
297 | | char choked; /* Are we currently blocked from writing? */ |
298 | | char closing; /* Are we trying to close this port, pending writes? */ |
299 | | evdns_request_callback_fn_type user_callback; /* Fn to handle requests */ |
300 | | void *user_data; /* Opaque pointer passed to user_callback */ |
301 | | struct event event; /* Read/write event */ |
302 | | /* circular list of replies that we want to write. */ |
303 | | struct server_request *pending_replies; |
304 | | struct event_base *event_base; |
305 | | |
306 | | /* Structures for tcp support */ |
307 | | struct evconnlistener *listener; |
308 | | LIST_HEAD(client_list, client_tcp_connection) client_connections; |
309 | | unsigned client_connections_count; |
310 | | unsigned max_client_connections; |
311 | | struct timeval tcp_idle_timeout; |
312 | | |
313 | | #ifndef EVENT__DISABLE_THREAD_SUPPORT |
314 | | void *lock; |
315 | | #endif |
316 | | }; |
317 | | |
318 | | /* Represents part of a reply being built. (That is, a single RR.) */ |
319 | | struct server_reply_item { |
320 | | struct server_reply_item *next; /* next item in sequence. */ |
321 | | char *name; /* name part of the RR */ |
322 | | u16 type; /* The RR type */ |
323 | | u16 class; /* The RR class (usually CLASS_INET) */ |
324 | | u32 ttl; /* The RR TTL */ |
325 | | char is_name; /* True iff data is a label */ |
326 | | u16 datalen; /* Length of data; -1 if data is a label */ |
327 | | void *data; /* The contents of the RR */ |
328 | | }; |
329 | | |
330 | | /* Represents a request that we've received as a DNS server, and holds */ |
331 | | /* the components of the reply as we're constructing it. */ |
332 | | struct server_request { |
333 | | /* Pointers to the next and previous entries on the list of replies */ |
334 | | /* that we're waiting to write. Only set if we have tried to respond */ |
335 | | /* and gotten EAGAIN. */ |
336 | | struct server_request *next_pending; |
337 | | struct server_request *prev_pending; |
338 | | |
339 | | u16 trans_id; /* Transaction id. */ |
340 | | struct evdns_server_port *port; /* Which port received this request on? */ |
341 | | struct client_tcp_connection *client; /* Equal to NULL in case of UDP connection. */ |
342 | | struct sockaddr_storage addr; /* Where to send the response in case of UDP. Equal to NULL in case of TCP connection.*/ |
343 | | ev_socklen_t addrlen; /* length of addr */ |
344 | | u16 max_udp_reply_size; /* Maximum size of udp reply that client can handle. */ |
345 | | |
346 | | int n_answer; /* how many answer RRs have been set? */ |
347 | | int n_authority; /* how many authority RRs have been set? */ |
348 | | int n_additional; /* how many additional RRs have been set? */ |
349 | | |
350 | | struct server_reply_item *answer; /* linked list of answer RRs */ |
351 | | struct server_reply_item *authority; /* linked list of authority RRs */ |
352 | | struct server_reply_item *additional; /* linked list of additional RRs */ |
353 | | |
354 | | /* Constructed response. Only set once we're ready to send a reply. */ |
355 | | /* Once this is set, the RR fields are cleared, and no more should be set. */ |
356 | | char *response; |
357 | | size_t response_len; |
358 | | |
359 | | /* Caller-visible fields: flags, questions. */ |
360 | | struct evdns_server_request base; |
361 | | }; |
362 | | |
363 | | struct evdns_base { |
364 | | /* An array of n_req_heads circular lists for inflight requests. |
365 | | * Each inflight request req is in req_heads[req->trans_id % n_req_heads]. |
366 | | */ |
367 | | struct request **req_heads; |
368 | | /* A circular list of requests that we're waiting to send, but haven't |
369 | | * sent yet because there are too many requests inflight */ |
370 | | struct request *req_waiting_head; |
371 | | /* A circular list of nameservers. */ |
372 | | struct nameserver *server_head; |
373 | | int n_req_heads; |
374 | | |
375 | | struct event_base *event_base; |
376 | | |
377 | | /* The number of good nameservers that we have */ |
378 | | int global_good_nameservers; |
379 | | |
380 | | /* inflight requests are contained in the req_head list */ |
381 | | /* and are actually going out across the network */ |
382 | | int global_requests_inflight; |
383 | | /* requests which aren't inflight are in the waiting list */ |
384 | | /* and are counted here */ |
385 | | int global_requests_waiting; |
386 | | |
387 | | int global_max_requests_inflight; |
388 | | |
389 | | struct timeval global_timeout; /* 5 seconds by default */ |
390 | | int global_max_reissues; /* a reissue occurs when we get some errors from the server */ |
391 | | int global_max_retransmits; /* number of times we'll retransmit a request which timed out */ |
392 | | /* number of timeouts in a row before we consider this server to be down */ |
393 | | int global_max_nameserver_timeout; |
394 | | /* true iff we will use the 0x20 hack to prevent poisoning attacks. */ |
395 | | int global_randomize_case; |
396 | | /* Maximum size of a UDP DNS packet. */ |
397 | | u16 global_max_udp_size; |
398 | | |
399 | | /* The first time that a nameserver fails, how long do we wait before |
400 | | * probing to see if it has returned? */ |
401 | | struct timeval global_nameserver_probe_initial_timeout; |
402 | | |
403 | | /* Combination of DNS_QUERY_USEVC, DNS_QUERY_IGNTC flags |
404 | | * to control requests via TCP. */ |
405 | | u16 global_tcp_flags; |
406 | | /* Idle timeout for outgoing TCP connections. */ |
407 | | struct timeval global_tcp_idle_timeout; |
408 | | |
409 | | /** Port to bind to for outgoing DNS packets. */ |
410 | | struct sockaddr_storage global_outgoing_address; |
411 | | /** ev_socklen_t for global_outgoing_address. 0 if it isn't set. */ |
412 | | ev_socklen_t global_outgoing_addrlen; |
413 | | |
414 | | struct timeval global_getaddrinfo_allow_skew; |
415 | | |
416 | | int so_rcvbuf; |
417 | | int so_sndbuf; |
418 | | |
419 | | int getaddrinfo_ipv4_timeouts; |
420 | | int getaddrinfo_ipv6_timeouts; |
421 | | int getaddrinfo_ipv4_answered; |
422 | | int getaddrinfo_ipv6_answered; |
423 | | |
424 | | struct search_state *global_search_state; |
425 | | |
426 | | TAILQ_HEAD(hosts_list, hosts_entry) hostsdb; |
427 | | |
428 | | SPLAY_HEAD(evdns_tree, evdns_cache) cache_root; |
429 | | |
430 | | #ifndef EVENT__DISABLE_THREAD_SUPPORT |
431 | | void *lock; |
432 | | #endif |
433 | | |
434 | | int disable_when_inactive; |
435 | | int disable_cache; |
436 | | |
437 | | /* Maximum timeout between two probe packets |
438 | | * will change `global_nameserver_probe_initial_timeout` |
439 | | * when this value is smaller */ |
440 | | int ns_max_probe_timeout; |
441 | | /* Backoff factor of probe timeout */ |
442 | | int ns_timeout_backoff_factor; |
443 | | }; |
444 | | |
445 | | struct hosts_entry { |
446 | | TAILQ_ENTRY(hosts_entry) next; |
447 | | union { |
448 | | struct sockaddr sa; |
449 | | struct sockaddr_in sin; |
450 | | struct sockaddr_in6 sin6; |
451 | | } addr; |
452 | | int addrlen; |
453 | | char hostname[1]; |
454 | | }; |
455 | | |
456 | | struct evdns_cache { |
457 | | SPLAY_ENTRY(evdns_cache) node; |
458 | | char *name; |
459 | | struct evutil_addrinfo *ai; |
460 | | struct event ev_timeout; |
461 | | struct evdns_base *base; |
462 | | }; |
463 | | |
464 | | static struct evdns_base *current_base = NULL; |
465 | | |
466 | | struct evdns_base * |
467 | | evdns_get_global_base(void) |
468 | 0 | { |
469 | 0 | return current_base; |
470 | 0 | } |
471 | | |
472 | | /* Given a pointer to an evdns_server_request, get the corresponding */ |
473 | | /* server_request. */ |
474 | | #define TO_SERVER_REQUEST(base_ptr) \ |
475 | 0 | ((struct server_request*) \ |
476 | 0 | (((char*)(base_ptr) - evutil_offsetof(struct server_request, base)))) |
477 | | |
478 | 0 | #define REQ_HEAD(base, id) ((base)->req_heads[id % (base)->n_req_heads]) |
479 | | |
480 | | static struct nameserver *nameserver_pick(struct evdns_base *base); |
481 | | static void evdns_request_insert(struct request *req, struct request **head); |
482 | | static void evdns_request_remove(struct request *req, struct request **head); |
483 | | static void nameserver_ready_callback(evutil_socket_t fd, short events, void *arg); |
484 | | static int evdns_transmit(struct evdns_base *base); |
485 | | static int evdns_request_transmit(struct request *req); |
486 | | static void nameserver_send_probe(struct nameserver *const ns); |
487 | | static void search_request_finished(struct evdns_request *const); |
488 | | static int search_try_next(struct evdns_request *const req); |
489 | | static struct request *search_request_new(struct evdns_base *base, struct evdns_request *handle, int type, const char *const name, int flags); |
490 | | static void evdns_requests_pump_waiting_queue(struct evdns_base *base); |
491 | | static u16 transaction_id_pick(struct evdns_base *base); |
492 | | static struct request *request_new(struct evdns_base *base, struct evdns_request *handle, int type, const char *name, int flags); |
493 | | static struct request *request_clone(struct evdns_base *base, struct request* current); |
494 | | static void request_submit(struct request *const req); |
495 | | |
496 | | static int server_request_free(struct server_request *req); |
497 | | static void server_request_free_answers(struct server_request *req); |
498 | | static void server_port_free(struct evdns_server_port *port); |
499 | | static void server_port_ready_callback(evutil_socket_t fd, short events, void *arg); |
500 | | static int evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename); |
501 | | static int evdns_base_set_option_impl(struct evdns_base *base, |
502 | | const char *option, const char *val, int flags); |
503 | | static void evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests); |
504 | | static void evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg); |
505 | | static int evdns_server_request_format_response(struct server_request *req, int err); |
506 | | static void incoming_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, |
507 | | struct sockaddr *address, int socklen, void *arg); |
508 | | |
509 | | static int strtoint(const char *const str); |
510 | | |
511 | | #ifdef EVENT__DISABLE_THREAD_SUPPORT |
512 | | #define EVDNS_LOCK(base) EVUTIL_NIL_CONDITION_(base) |
513 | | #define EVDNS_UNLOCK(base) EVUTIL_NIL_STMT_ |
514 | | #define ASSERT_LOCKED(base) EVUTIL_NIL_STMT_ |
515 | | #else |
516 | | #define EVDNS_LOCK(base) \ |
517 | 0 | EVLOCK_LOCK((base)->lock, 0) |
518 | | #define EVDNS_UNLOCK(base) \ |
519 | 0 | EVLOCK_UNLOCK((base)->lock, 0) |
520 | | #define ASSERT_LOCKED(base) \ |
521 | 0 | EVLOCK_ASSERT_LOCKED((base)->lock) |
522 | | #endif |
523 | | |
524 | | static evdns_debug_log_fn_type evdns_log_fn = NULL; |
525 | | |
526 | | void |
527 | | evdns_set_log_fn(evdns_debug_log_fn_type fn) |
528 | 0 | { |
529 | 0 | evdns_log_fn = fn; |
530 | 0 | } |
531 | | |
532 | | #ifdef __GNUC__ |
533 | | #define EVDNS_LOG_CHECK __attribute__ ((format(printf, 2, 3))) |
534 | | #else |
535 | | #define EVDNS_LOG_CHECK |
536 | | #endif |
537 | | |
538 | | static void evdns_log_(int severity, const char *fmt, ...) EVDNS_LOG_CHECK; |
539 | | static void |
540 | | evdns_log_(int severity, const char *fmt, ...) |
541 | 0 | { |
542 | 0 | va_list args; |
543 | 0 | va_start(args,fmt); |
544 | 0 | if (evdns_log_fn) { |
545 | 0 | char buf[512]; |
546 | 0 | int is_warn = (severity == EVDNS_LOG_WARN); |
547 | 0 | evutil_vsnprintf(buf, sizeof(buf), fmt, args); |
548 | 0 | evdns_log_fn(is_warn, buf); |
549 | 0 | } else { |
550 | 0 | event_logv_(severity, NULL, fmt, args); |
551 | 0 | } |
552 | 0 | va_end(args); |
553 | 0 | } |
554 | | |
555 | 0 | #define log evdns_log_ |
556 | | |
557 | | /* Initialize tcp_connection structure. */ |
558 | | static void |
559 | | init_tcp_connection(struct tcp_connection *conn, struct bufferevent *bev) |
560 | 0 | { |
561 | 0 | memset(conn, 0, sizeof(*conn)); |
562 | 0 | conn->state = TS_DISCONNECTED; |
563 | 0 | conn->bev = bev; |
564 | 0 | conn->awaiting_packet_size = 0; |
565 | 0 | } |
566 | | |
567 | | /* Disconnect tcp connection. */ |
568 | | static void |
569 | | evdns_tcp_disconnect(struct tcp_connection *conn) |
570 | 0 | { |
571 | 0 | if (!conn) |
572 | 0 | return; |
573 | 0 | conn->state = TS_DISCONNECTED; |
574 | 0 | conn->awaiting_packet_size = 0; |
575 | 0 | if (conn->bev) { |
576 | 0 | bufferevent_free(conn->bev); |
577 | 0 | conn->bev = NULL; |
578 | 0 | } |
579 | 0 | } |
580 | | |
581 | | /* Add new tcp client to the list of TCP clients in the TCP DNS server. */ |
582 | | static struct client_tcp_connection* |
583 | | evdns_add_tcp_client(struct evdns_server_port *port, struct bufferevent *bev) |
584 | 0 | { |
585 | 0 | struct client_tcp_connection *client; |
586 | 0 | EVUTIL_ASSERT(port && bev); |
587 | 0 | if (port->max_client_connections == port->client_connections_count) |
588 | 0 | goto error; |
589 | | |
590 | 0 | client = mm_calloc(1, sizeof(*client)); |
591 | 0 | if (!client) |
592 | 0 | goto error; |
593 | 0 | init_tcp_connection(&client->connection, bev); |
594 | 0 | client->port = port; |
595 | 0 | LIST_INSERT_HEAD(&port->client_connections, client, next); |
596 | |
|
597 | 0 | ++port->client_connections_count; |
598 | | /* we need to hold evdns_server_port as long as one connection at least stays alive */ |
599 | 0 | ++port->refcnt; |
600 | 0 | return client; |
601 | 0 | error: |
602 | 0 | return NULL; |
603 | 0 | } |
604 | | |
605 | | /* Remove tcp client and free all associated data from the TCP DNS server. */ |
606 | | static int |
607 | | evdns_remove_tcp_client(struct evdns_server_port *port, struct client_tcp_connection *client) |
608 | 0 | { |
609 | 0 | if (!port || !client) |
610 | 0 | goto error; |
611 | | |
612 | 0 | evdns_tcp_disconnect(&client->connection); |
613 | 0 | LIST_REMOVE(client, next); |
614 | 0 | mm_free(client); |
615 | 0 | --port->client_connections_count; |
616 | 0 | --port->refcnt; |
617 | 0 | return 0; |
618 | 0 | error: |
619 | 0 | return -1; |
620 | 0 | } |
621 | | |
622 | | /* Remove all tcp clients and free all associated data from the TCP DNS server. */ |
623 | | static void |
624 | | evdns_remove_all_tcp_clients(struct evdns_server_port *port) |
625 | 0 | { |
626 | 0 | struct client_tcp_connection *client; |
627 | 0 | while ((client = LIST_FIRST(&port->client_connections))) { |
628 | 0 | evdns_remove_tcp_client(port, client); |
629 | 0 | } |
630 | 0 | } |
631 | | |
632 | | /* Create new tcp connection structure for DNS client. */ |
633 | | static struct tcp_connection * |
634 | | new_tcp_connection(struct bufferevent *bev) |
635 | 0 | { |
636 | 0 | struct tcp_connection *conn; |
637 | 0 | if (!bev) |
638 | 0 | return NULL; |
639 | | |
640 | 0 | conn = mm_calloc(1, sizeof(*conn)); |
641 | 0 | if (!conn) |
642 | 0 | return NULL; |
643 | 0 | init_tcp_connection(conn, bev); |
644 | 0 | return conn; |
645 | 0 | } |
646 | | |
647 | | /* Disconnect and free all associated data for the tcp connection in DNS client. */ |
648 | | static void |
649 | | disconnect_and_free_connection(struct tcp_connection *conn) |
650 | 0 | { |
651 | 0 | if (!conn) |
652 | 0 | return; |
653 | 0 | evdns_tcp_disconnect(conn); |
654 | 0 | mm_free(conn); |
655 | 0 | } |
656 | | |
657 | | /* This walks the list of inflight requests to find the */ |
658 | | /* one with a matching transaction id. Returns NULL on */ |
659 | | /* failure */ |
660 | | static struct request * |
661 | 0 | request_find_from_trans_id(struct evdns_base *base, u16 trans_id) { |
662 | 0 | struct request *req = REQ_HEAD(base, trans_id); |
663 | 0 | struct request *const started_at = req; |
664 | |
|
665 | 0 | ASSERT_LOCKED(base); |
666 | |
|
667 | 0 | if (req) { |
668 | 0 | do { |
669 | 0 | if (req->trans_id == trans_id) return req; |
670 | 0 | req = req->next; |
671 | 0 | } while (req != started_at); |
672 | 0 | } |
673 | | |
674 | 0 | return NULL; |
675 | 0 | } |
676 | | |
677 | | /* a libevent callback function which is called when a nameserver */ |
678 | | /* has gone down and we want to test if it has came back to life yet */ |
679 | | static void |
680 | 0 | nameserver_prod_callback(evutil_socket_t fd, short events, void *arg) { |
681 | 0 | struct nameserver *const ns = (struct nameserver *) arg; |
682 | 0 | (void)fd; |
683 | 0 | (void)events; |
684 | |
|
685 | 0 | EVDNS_LOCK(ns->base); |
686 | 0 | nameserver_send_probe(ns); |
687 | 0 | EVDNS_UNLOCK(ns->base); |
688 | 0 | } |
689 | | |
690 | | /* a libevent callback which is called when a nameserver probe (to see if */ |
691 | | /* it has come back to life) times out. We increment the count of failed_times */ |
692 | | /* and wait longer to send the next probe packet. */ |
693 | | static void |
694 | 0 | nameserver_probe_failed(struct nameserver *const ns) { |
695 | 0 | struct timeval timeout; |
696 | 0 | int i; |
697 | |
|
698 | 0 | ASSERT_LOCKED(ns->base); |
699 | 0 | (void) evtimer_del(&ns->timeout_event); |
700 | 0 | if (ns->state == 1) { |
701 | | /* This can happen if the nameserver acts in a way which makes us mark */ |
702 | | /* it as bad and then starts sending good replies. */ |
703 | 0 | return; |
704 | 0 | } |
705 | | |
706 | 0 | memcpy(&timeout, &ns->base->global_nameserver_probe_initial_timeout, |
707 | 0 | sizeof(struct timeval)); |
708 | 0 | for (i = ns->failed_times; i > 0 && timeout.tv_sec < ns->base->ns_max_probe_timeout; --i) { |
709 | 0 | timeout.tv_sec *= ns->base->ns_timeout_backoff_factor; |
710 | 0 | timeout.tv_usec *= ns->base->ns_timeout_backoff_factor; |
711 | 0 | if (timeout.tv_usec > 1000000) { |
712 | 0 | timeout.tv_sec += timeout.tv_usec / 1000000; |
713 | 0 | timeout.tv_usec %= 1000000; |
714 | 0 | } |
715 | 0 | } |
716 | 0 | if (timeout.tv_sec > ns->base->ns_max_probe_timeout) { |
717 | 0 | timeout.tv_sec = ns->base->ns_max_probe_timeout; |
718 | 0 | timeout.tv_usec = 0; |
719 | 0 | } |
720 | |
|
721 | 0 | ns->failed_times++; |
722 | |
|
723 | 0 | if (evtimer_add(&ns->timeout_event, &timeout) < 0) { |
724 | 0 | char addrbuf[128]; |
725 | 0 | log(EVDNS_LOG_WARN, |
726 | 0 | "Error from libevent when adding timer event for %s", |
727 | 0 | evutil_format_sockaddr_port_( |
728 | 0 | (struct sockaddr *)&ns->address, |
729 | 0 | addrbuf, sizeof(addrbuf))); |
730 | 0 | } |
731 | 0 | } |
732 | | |
733 | | static void |
734 | 0 | request_swap_ns(struct request *req, struct nameserver *ns) { |
735 | 0 | if (ns && req->ns != ns) { |
736 | 0 | EVUTIL_ASSERT(req->ns->requests_inflight > 0); |
737 | 0 | req->ns->requests_inflight--; |
738 | 0 | ns->requests_inflight++; |
739 | |
|
740 | 0 | req->ns = ns; |
741 | 0 | } |
742 | 0 | } |
743 | | |
744 | | /* called when a nameserver has been deemed to have failed. For example, too */ |
745 | | /* many packets have timed out etc */ |
746 | | static void |
747 | 0 | nameserver_failed(struct nameserver *const ns, const char *msg, int err) { |
748 | 0 | struct request *req, *started_at; |
749 | 0 | struct evdns_base *base = ns->base; |
750 | 0 | int i; |
751 | 0 | char addrbuf[128]; |
752 | |
|
753 | 0 | ASSERT_LOCKED(base); |
754 | | /* if this nameserver has already been marked as failed */ |
755 | | /* then don't do anything */ |
756 | 0 | if (!ns->state) return; |
757 | | |
758 | 0 | log(EVDNS_LOG_MSG, "Nameserver %s has failed: %s", |
759 | 0 | evutil_format_sockaddr_port_( |
760 | 0 | (struct sockaddr *)&ns->address, |
761 | 0 | addrbuf, sizeof(addrbuf)), |
762 | 0 | msg); |
763 | |
|
764 | 0 | base->global_good_nameservers--; |
765 | 0 | EVUTIL_ASSERT(base->global_good_nameservers >= 0); |
766 | 0 | if (base->global_good_nameservers == 0) { |
767 | 0 | log(EVDNS_LOG_MSG, "All nameservers have failed"); |
768 | 0 | } |
769 | |
|
770 | 0 | ns->state = 0; |
771 | 0 | ns->failed_times = 1; |
772 | |
|
773 | 0 | if (ns->connection) { |
774 | 0 | disconnect_and_free_connection(ns->connection); |
775 | 0 | ns->connection = NULL; |
776 | 0 | } else if (err == ENOTCONN) { |
777 | | /* XXX: If recvfrom results in ENOTCONN, the socket remains readable |
778 | | * which triggers another recvfrom. The observed behavior is 100% CPU use. |
779 | | * This occurs on iOS (kqueue) after the process has been backgrounded |
780 | | * for a long time (~300 seconds) and then resumed. |
781 | | * All sockets, TCP and UDP, seem to get ENOTCONN and must be closed. |
782 | | * https://github.com/libevent/libevent/issues/265 */ |
783 | 0 | const struct sockaddr *address = (const struct sockaddr *)&ns->address; |
784 | 0 | evutil_closesocket(ns->socket); |
785 | 0 | ns->socket = evutil_socket_(address->sa_family, |
786 | 0 | SOCK_DGRAM | EVUTIL_SOCK_NONBLOCK | EVUTIL_SOCK_CLOEXEC, 0); |
787 | |
|
788 | 0 | if (base->global_outgoing_addrlen && |
789 | 0 | !evutil_sockaddr_is_loopback_(address)) { |
790 | 0 | if (bind(ns->socket, |
791 | 0 | (struct sockaddr *)&base->global_outgoing_address, |
792 | 0 | base->global_outgoing_addrlen) < 0) { |
793 | 0 | log(EVDNS_LOG_WARN, "Couldn't bind to outgoing address"); |
794 | 0 | } |
795 | 0 | } |
796 | |
|
797 | 0 | event_del(&ns->event); |
798 | 0 | event_assign(&ns->event, ns->base->event_base, ns->socket, |
799 | 0 | EV_READ | (ns->write_waiting ? EV_WRITE : 0) | EV_PERSIST, |
800 | 0 | nameserver_ready_callback, ns); |
801 | 0 | if (!base->disable_when_inactive && event_add(&ns->event, NULL) < 0) { |
802 | 0 | log(EVDNS_LOG_WARN, "Couldn't add %s event", |
803 | 0 | ns->write_waiting ? "rw": "read"); |
804 | 0 | } |
805 | 0 | } |
806 | 0 | if (evtimer_add(&ns->timeout_event, |
807 | 0 | &base->global_nameserver_probe_initial_timeout) < 0) { |
808 | 0 | log(EVDNS_LOG_WARN, |
809 | 0 | "Error from libevent when adding timer event for %s", |
810 | 0 | evutil_format_sockaddr_port_( |
811 | 0 | (struct sockaddr *)&ns->address, |
812 | 0 | addrbuf, sizeof(addrbuf))); |
813 | | /* ???? Do more? */ |
814 | 0 | } |
815 | | |
816 | | /* walk the list of inflight requests to see if any can be reassigned to */ |
817 | | /* a different server. Requests in the waiting queue don't have a */ |
818 | | /* nameserver assigned yet */ |
819 | | |
820 | | /* if we don't have *any* good nameservers then there's no point */ |
821 | | /* trying to reassign requests to one */ |
822 | 0 | if (!base->global_good_nameservers) return; |
823 | | |
824 | 0 | for (i = 0; i < base->n_req_heads; ++i) { |
825 | 0 | req = started_at = base->req_heads[i]; |
826 | 0 | if (req) { |
827 | 0 | do { |
828 | 0 | if (req->tx_count == 0 && req->ns == ns) { |
829 | | /* still waiting to go out, can be moved */ |
830 | | /* to another server */ |
831 | 0 | request_swap_ns(req, nameserver_pick(base)); |
832 | 0 | } |
833 | 0 | req = req->next; |
834 | 0 | } while (req != started_at); |
835 | 0 | } |
836 | 0 | } |
837 | 0 | } |
838 | | |
839 | | static void |
840 | | nameserver_up(struct nameserver *const ns) |
841 | 0 | { |
842 | 0 | char addrbuf[128]; |
843 | 0 | ASSERT_LOCKED(ns->base); |
844 | 0 | if (ns->state) return; |
845 | 0 | log(EVDNS_LOG_MSG, "Nameserver %s is back up", |
846 | 0 | evutil_format_sockaddr_port_( |
847 | 0 | (struct sockaddr *)&ns->address, |
848 | 0 | addrbuf, sizeof(addrbuf))); |
849 | 0 | evtimer_del(&ns->timeout_event); |
850 | 0 | if (ns->probe_request) { |
851 | 0 | evdns_cancel_request(ns->base, ns->probe_request); |
852 | 0 | ns->probe_request = NULL; |
853 | 0 | } |
854 | 0 | ns->state = 1; |
855 | 0 | ns->failed_times = 0; |
856 | 0 | ns->timedout = 0; |
857 | 0 | ns->base->global_good_nameservers++; |
858 | 0 | } |
859 | | |
860 | | static void |
861 | 0 | request_trans_id_set(struct request *const req, const u16 trans_id) { |
862 | 0 | req->trans_id = trans_id; |
863 | 0 | *((u16 *) req->request) = htons(trans_id); |
864 | 0 | } |
865 | | |
866 | | /* Called to remove a request from a list and dealloc it. */ |
867 | | /* head is a pointer to the head of the list it should be */ |
868 | | /* removed from or NULL if the request isn't in a list. */ |
869 | | /* when free_handle is one, free the handle as well. */ |
870 | | static void |
871 | 0 | request_finished(struct request *const req, struct request **head, int free_handle) { |
872 | 0 | struct evdns_base *base = req->base; |
873 | 0 | int was_inflight = (head != &base->req_waiting_head); |
874 | 0 | EVDNS_LOCK(base); |
875 | 0 | ASSERT_VALID_REQUEST(req); |
876 | |
|
877 | 0 | if (head) |
878 | 0 | evdns_request_remove(req, head); |
879 | |
|
880 | 0 | log(EVDNS_LOG_DEBUG, "Removing timeout for request %p", (void *)req); |
881 | 0 | if (was_inflight) { |
882 | 0 | evtimer_del(&req->timeout_event); |
883 | 0 | base->global_requests_inflight--; |
884 | 0 | req->ns->requests_inflight--; |
885 | 0 | } else { |
886 | 0 | base->global_requests_waiting--; |
887 | 0 | } |
888 | | /* it was initialized during request_new / evtimer_assign */ |
889 | 0 | event_debug_unassign(&req->timeout_event); |
890 | |
|
891 | 0 | if (req->ns && |
892 | 0 | req->ns->requests_inflight == 0 && |
893 | 0 | req->base->disable_when_inactive) { |
894 | 0 | event_del(&req->ns->event); |
895 | 0 | evtimer_del(&req->ns->timeout_event); |
896 | 0 | } |
897 | |
|
898 | 0 | if (!req->request_appended) { |
899 | | /* need to free the request data on it's own */ |
900 | 0 | mm_free(req->request); |
901 | 0 | } else { |
902 | | /* the request data is appended onto the header */ |
903 | | /* so everything gets free()ed when we: */ |
904 | 0 | } |
905 | |
|
906 | 0 | if (req->handle) { |
907 | 0 | EVUTIL_ASSERT(req->handle->current_req == req); |
908 | |
|
909 | 0 | if (free_handle) { |
910 | 0 | search_request_finished(req->handle); |
911 | 0 | req->handle->current_req = NULL; |
912 | 0 | if (! req->handle->pending_cb) { |
913 | | /* If we're planning to run the callback, |
914 | | * don't free the handle until later. */ |
915 | 0 | mm_free(req->handle); |
916 | 0 | } |
917 | 0 | req->handle = NULL; /* If we have a bug, let's crash |
918 | | * early */ |
919 | 0 | } else { |
920 | 0 | req->handle->current_req = NULL; |
921 | 0 | } |
922 | 0 | } |
923 | |
|
924 | 0 | mm_free(req); |
925 | |
|
926 | 0 | evdns_requests_pump_waiting_queue(base); |
927 | 0 | EVDNS_UNLOCK(base); |
928 | 0 | } |
929 | | |
930 | | /* This is called when a server returns a funny error code. */ |
931 | | /* We try the request again with another server. */ |
932 | | /* */ |
933 | | /* return: */ |
934 | | /* 0 ok */ |
935 | | /* 1 failed/reissue is pointless */ |
936 | | static int |
937 | 0 | request_reissue(struct request *req) { |
938 | 0 | const struct nameserver *const last_ns = req->ns; |
939 | 0 | ASSERT_LOCKED(req->base); |
940 | 0 | ASSERT_VALID_REQUEST(req); |
941 | | /* the last nameserver should have been marked as failing */ |
942 | | /* by the caller of this function, therefore pick will try */ |
943 | | /* not to return it */ |
944 | 0 | request_swap_ns(req, nameserver_pick(req->base)); |
945 | 0 | if (req->ns == last_ns) { |
946 | | /* ... but pick did return it */ |
947 | | /* not a lot of point in trying again with the */ |
948 | | /* same server */ |
949 | 0 | return 1; |
950 | 0 | } |
951 | | |
952 | 0 | req->reissue_count++; |
953 | 0 | req->tx_count = 0; |
954 | 0 | req->transmit_me = 1; |
955 | |
|
956 | 0 | return 0; |
957 | 0 | } |
958 | | |
959 | | /* this function looks for space on the inflight queue and promotes */ |
960 | | /* requests from the waiting queue if it can. */ |
961 | | /* */ |
962 | | /* TODO: */ |
963 | | /* add return code, see at nameserver_pick() and other functions. */ |
964 | | static void |
965 | 0 | evdns_requests_pump_waiting_queue(struct evdns_base *base) { |
966 | 0 | ASSERT_LOCKED(base); |
967 | 0 | while (base->global_requests_inflight < base->global_max_requests_inflight && |
968 | 0 | base->global_requests_waiting) { |
969 | 0 | struct request *req; |
970 | |
|
971 | 0 | EVUTIL_ASSERT(base->req_waiting_head); |
972 | 0 | req = base->req_waiting_head; |
973 | |
|
974 | 0 | req->ns = nameserver_pick(base); |
975 | 0 | if (!req->ns) |
976 | 0 | return; |
977 | | |
978 | | /* move a request from the waiting queue to the inflight queue */ |
979 | 0 | req->ns->requests_inflight++; |
980 | |
|
981 | 0 | evdns_request_remove(req, &base->req_waiting_head); |
982 | |
|
983 | 0 | base->global_requests_waiting--; |
984 | 0 | base->global_requests_inflight++; |
985 | |
|
986 | 0 | request_trans_id_set(req, transaction_id_pick(base)); |
987 | |
|
988 | 0 | evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); |
989 | 0 | evdns_request_transmit(req); |
990 | 0 | evdns_transmit(base); |
991 | 0 | } |
992 | 0 | } |
993 | | |
994 | | static void |
995 | | reply_run_callback(struct event_callback *d, void *user_pointer) |
996 | 0 | { |
997 | 0 | struct evdns_request *handle = |
998 | 0 | EVUTIL_UPCAST(d, struct evdns_request, deferred); |
999 | |
|
1000 | 0 | switch (handle->request_type) { |
1001 | 0 | case TYPE_A: |
1002 | 0 | if (handle->have_reply) { |
1003 | 0 | handle->user_callback(DNS_ERR_NONE, DNS_IPv4_A, |
1004 | 0 | handle->reply.rr_count, handle->ttl, |
1005 | 0 | handle->reply.data.a, |
1006 | 0 | user_pointer); |
1007 | 0 | if (handle->reply.cname) |
1008 | 0 | handle->user_callback(DNS_ERR_NONE, DNS_CNAME, 1, |
1009 | 0 | handle->ttl, handle->reply.cname, user_pointer); |
1010 | 0 | } else |
1011 | 0 | handle->user_callback(handle->err, DNS_IPv4_A, 0, handle->ttl, NULL, user_pointer); |
1012 | 0 | break; |
1013 | 0 | case TYPE_PTR: |
1014 | 0 | if (handle->have_reply) { |
1015 | 0 | char *name = handle->reply.data.ptr_name; |
1016 | 0 | handle->user_callback(DNS_ERR_NONE, DNS_PTR, 1, handle->ttl, |
1017 | 0 | &name, user_pointer); |
1018 | 0 | } else { |
1019 | 0 | handle->user_callback(handle->err, DNS_PTR, 0, handle->ttl, NULL, user_pointer); |
1020 | 0 | } |
1021 | 0 | break; |
1022 | 0 | case TYPE_AAAA: |
1023 | 0 | if (handle->have_reply) { |
1024 | 0 | handle->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA, |
1025 | 0 | handle->reply.rr_count, handle->ttl, |
1026 | 0 | handle->reply.data.aaaa, |
1027 | 0 | user_pointer); |
1028 | 0 | if (handle->reply.cname) |
1029 | 0 | handle->user_callback(DNS_ERR_NONE, DNS_CNAME, 1, |
1030 | 0 | handle->ttl, handle->reply.cname, user_pointer); |
1031 | 0 | } else |
1032 | 0 | handle->user_callback(handle->err, DNS_IPv6_AAAA, 0, handle->ttl, NULL, user_pointer); |
1033 | 0 | break; |
1034 | 0 | default: |
1035 | 0 | EVUTIL_ASSERT(0); |
1036 | 0 | } |
1037 | | |
1038 | 0 | if (handle->reply.data.raw) { |
1039 | 0 | mm_free(handle->reply.data.raw); |
1040 | 0 | } |
1041 | |
|
1042 | 0 | if (handle->reply.cname) { |
1043 | 0 | mm_free(handle->reply.cname); |
1044 | 0 | } |
1045 | |
|
1046 | 0 | mm_free(handle); |
1047 | 0 | } |
1048 | | |
1049 | | static void |
1050 | | reply_schedule_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply) |
1051 | 0 | { |
1052 | 0 | struct evdns_request* handle = req->handle; |
1053 | |
|
1054 | 0 | ASSERT_LOCKED(req->base); |
1055 | |
|
1056 | 0 | handle->request_type = req->request_type; |
1057 | 0 | handle->ttl = ttl; |
1058 | 0 | handle->err = err; |
1059 | 0 | if (reply) { |
1060 | 0 | handle->have_reply = 1; |
1061 | 0 | memcpy(&handle->reply, reply, sizeof(struct reply)); |
1062 | | /* We've taken ownership of the data. */ |
1063 | 0 | reply->data.raw = NULL; |
1064 | 0 | } |
1065 | |
|
1066 | 0 | handle->pending_cb = 1; |
1067 | |
|
1068 | 0 | event_deferred_cb_init_( |
1069 | 0 | &handle->deferred, |
1070 | 0 | event_get_priority(&req->timeout_event), |
1071 | 0 | reply_run_callback, |
1072 | 0 | handle->user_pointer); |
1073 | 0 | event_deferred_cb_schedule_( |
1074 | 0 | req->base->event_base, |
1075 | 0 | &handle->deferred); |
1076 | 0 | } |
1077 | | |
1078 | | static int |
1079 | | client_retransmit_through_tcp(struct evdns_request *handle) |
1080 | 0 | { |
1081 | 0 | struct request *req = handle->current_req; |
1082 | 0 | struct evdns_base *base = req->base; |
1083 | 0 | struct request *newreq = request_clone(base, req); |
1084 | 0 | ASSERT_LOCKED(base); |
1085 | 0 | if (!newreq) |
1086 | 0 | return 1; |
1087 | 0 | request_finished(req, &REQ_HEAD(req->base, req->trans_id), 0); |
1088 | 0 | handle->current_req = newreq; |
1089 | 0 | newreq->handle = handle; |
1090 | 0 | request_submit(newreq); |
1091 | 0 | return 0; |
1092 | 0 | } |
1093 | | |
1094 | 0 | #define _QR_MASK 0x8000U |
1095 | 0 | #define _OP_MASK 0x7800U |
1096 | | #define _AA_MASK 0x0400U |
1097 | 0 | #define _TC_MASK 0x0200U |
1098 | 0 | #define _RD_MASK 0x0100U |
1099 | | #define _RA_MASK 0x0080U |
1100 | | #define _Z_MASK 0x0040U |
1101 | | #define _AD_MASK 0x0020U |
1102 | 0 | #define _CD_MASK 0x0010U |
1103 | 0 | #define _RCODE_MASK 0x000fU |
1104 | | #define _Z_MASK_DEPRECATED 0x0070U |
1105 | | |
1106 | | /* this processes a parsed reply packet */ |
1107 | | static void |
1108 | 0 | reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) { |
1109 | 0 | int error; |
1110 | 0 | char addrbuf[128]; |
1111 | 0 | int retransmit_via_tcp = 0; |
1112 | 0 | static const int error_codes[] = { |
1113 | 0 | DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, |
1114 | 0 | DNS_ERR_NOTIMPL, DNS_ERR_REFUSED |
1115 | 0 | }; |
1116 | |
|
1117 | 0 | ASSERT_LOCKED(req->base); |
1118 | 0 | ASSERT_VALID_REQUEST(req); |
1119 | |
|
1120 | 0 | if (flags & (_RCODE_MASK | _TC_MASK) || !reply || !reply->have_answer) { |
1121 | | /* there was an error */ |
1122 | 0 | if (flags & _TC_MASK) { |
1123 | 0 | error = DNS_ERR_TRUNCATED; |
1124 | 0 | retransmit_via_tcp = (req->handle->tcp_flags & (DNS_QUERY_IGNTC | DNS_QUERY_USEVC)) == 0; |
1125 | 0 | } else if (flags & _RCODE_MASK) { |
1126 | 0 | u16 error_code = (flags & _RCODE_MASK) - 1; |
1127 | 0 | if (error_code > 4) { |
1128 | 0 | error = DNS_ERR_UNKNOWN; |
1129 | 0 | } else { |
1130 | 0 | error = error_codes[error_code]; |
1131 | 0 | } |
1132 | 0 | } else if (reply && !reply->have_answer) { |
1133 | 0 | error = DNS_ERR_NODATA; |
1134 | 0 | } else { |
1135 | 0 | error = DNS_ERR_UNKNOWN; |
1136 | 0 | } |
1137 | |
|
1138 | 0 | switch (error) { |
1139 | 0 | case DNS_ERR_NOTIMPL: |
1140 | 0 | case DNS_ERR_REFUSED: |
1141 | | /* we regard these errors as marking a bad nameserver */ |
1142 | 0 | if (req->reissue_count < req->base->global_max_reissues) { |
1143 | 0 | char msg[64]; |
1144 | 0 | evutil_snprintf(msg, sizeof(msg), "Bad response %d (%s)", |
1145 | 0 | error, evdns_err_to_string(error)); |
1146 | 0 | nameserver_failed(req->ns, msg, 0); |
1147 | 0 | if (!request_reissue(req)) return; |
1148 | 0 | } |
1149 | 0 | break; |
1150 | 0 | case DNS_ERR_SERVERFAILED: |
1151 | | /* rcode 2 (servfailed) sometimes means "we |
1152 | | * are broken" and sometimes (with some binds) |
1153 | | * means "that request was very confusing." |
1154 | | * Treat this as a timeout, not a failure. |
1155 | | */ |
1156 | 0 | log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver" |
1157 | 0 | "at %s; will allow the request to time out.", |
1158 | 0 | evutil_format_sockaddr_port_( |
1159 | 0 | (struct sockaddr *)&req->ns->address, |
1160 | 0 | addrbuf, sizeof(addrbuf))); |
1161 | | /* Call the timeout function */ |
1162 | 0 | evdns_request_timeout_callback(0, 0, req); |
1163 | 0 | return; |
1164 | 0 | default: |
1165 | | /* we got a good reply from the nameserver: it is up. */ |
1166 | 0 | if (req->handle == req->ns->probe_request) { |
1167 | | /* Avoid double-free */ |
1168 | 0 | req->ns->probe_request = NULL; |
1169 | 0 | } |
1170 | |
|
1171 | 0 | nameserver_up(req->ns); |
1172 | 0 | } |
1173 | | |
1174 | 0 | if (retransmit_via_tcp) { |
1175 | 0 | log(EVDNS_LOG_DEBUG, "Received truncated reply(flags 0x%x, transac ID: %d). Retransmitting via TCP.", |
1176 | 0 | req->handle->tcp_flags, req->trans_id); |
1177 | 0 | req->handle->tcp_flags |= DNS_QUERY_USEVC; |
1178 | 0 | client_retransmit_through_tcp(req->handle); |
1179 | 0 | return; |
1180 | 0 | } |
1181 | | |
1182 | 0 | if (req->handle->search_state && |
1183 | 0 | req->request_type != TYPE_PTR) { |
1184 | | /* if we have a list of domains to search in, |
1185 | | * try the next one */ |
1186 | 0 | if (!search_try_next(req->handle)) { |
1187 | | /* a new request was issued so this |
1188 | | * request is finished and */ |
1189 | | /* the user callback will be made when |
1190 | | * that request (or a */ |
1191 | | /* child of it) finishes. */ |
1192 | 0 | return; |
1193 | 0 | } |
1194 | 0 | } |
1195 | | |
1196 | | /* all else failed. Pass the failure up */ |
1197 | 0 | reply_schedule_callback(req, ttl, error, NULL); |
1198 | 0 | request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); |
1199 | 0 | } else { |
1200 | | /* all ok, tell the user */ |
1201 | 0 | reply_schedule_callback(req, ttl, 0, reply); |
1202 | 0 | if (req->handle == req->ns->probe_request) |
1203 | 0 | req->ns->probe_request = NULL; /* Avoid double-free */ |
1204 | 0 | nameserver_up(req->ns); |
1205 | 0 | request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); |
1206 | 0 | } |
1207 | 0 | } |
1208 | | |
1209 | | static int |
1210 | 0 | name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) { |
1211 | 0 | int name_end = -1; |
1212 | 0 | int j = *idx; |
1213 | 0 | int ptr_count = 0; |
1214 | 0 | #define GET32(x) do { if (j + 4 > length) goto err; memcpy(&t32_, packet + j, 4); j += 4; x = ntohl(t32_); } while (0) |
1215 | 0 | #define GET16(x) do { if (j + 2 > length) goto err; memcpy(&t_, packet + j, 2); j += 2; x = ntohs(t_); } while (0) |
1216 | 0 | #define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while (0) |
1217 | |
|
1218 | 0 | char *cp = name_out; |
1219 | 0 | const char *const end = name_out + name_out_len; |
1220 | | |
1221 | | /* Normally, names are a series of length prefixed strings terminated */ |
1222 | | /* with a length of 0 (the lengths are u8's < 63). */ |
1223 | | /* However, the length can start with a pair of 1 bits and that */ |
1224 | | /* means that the next 14 bits are a pointer within the current */ |
1225 | | /* packet. */ |
1226 | |
|
1227 | 0 | for (;;) { |
1228 | 0 | u8 label_len; |
1229 | 0 | GET8(label_len); |
1230 | 0 | if (!label_len) break; |
1231 | 0 | if (label_len & 0xc0) { |
1232 | 0 | u8 ptr_low; |
1233 | 0 | GET8(ptr_low); |
1234 | 0 | if (name_end < 0) name_end = j; |
1235 | 0 | j = (((int)label_len & 0x3f) << 8) + ptr_low; |
1236 | | /* Make sure that the target offset is in-bounds. */ |
1237 | 0 | if (j < 0 || j >= length) return -1; |
1238 | | /* If we've jumped more times than there are characters in the |
1239 | | * message, we must have a loop. */ |
1240 | 0 | if (++ptr_count > length) return -1; |
1241 | 0 | continue; |
1242 | 0 | } |
1243 | 0 | if (label_len > 63) return -1; |
1244 | 0 | if (cp != name_out) { |
1245 | 0 | if (cp + 1 >= end) return -1; |
1246 | 0 | *cp++ = '.'; |
1247 | 0 | } |
1248 | 0 | if (cp + label_len >= end) return -1; |
1249 | 0 | if (j + label_len > length) return -1; |
1250 | 0 | memcpy(cp, packet + j, label_len); |
1251 | 0 | cp += label_len; |
1252 | 0 | j += label_len; |
1253 | 0 | } |
1254 | 0 | if (cp >= end) return -1; |
1255 | 0 | *cp = '\0'; |
1256 | 0 | if (name_end < 0) |
1257 | 0 | *idx = j; |
1258 | 0 | else |
1259 | 0 | *idx = name_end; |
1260 | 0 | return 0; |
1261 | 0 | err: |
1262 | 0 | return -1; |
1263 | 0 | } |
1264 | | |
1265 | | /* parses a raw request from a nameserver */ |
1266 | | static int |
1267 | | reply_parse(struct evdns_base *base, u8 *packet, int length) |
1268 | 0 | { |
1269 | 0 | int j = 0, k = 0; /* index into packet */ |
1270 | 0 | u16 t_; /* used by the macros */ |
1271 | 0 | u32 t32_; /* used by the macros */ |
1272 | 0 | char tmp_name[256], cmp_name[256]; /* used by the macros */ |
1273 | 0 | int name_matches = 0; |
1274 | |
|
1275 | 0 | u16 trans_id, questions, answers, authority, additional, datalength; |
1276 | 0 | u16 flags = 0; |
1277 | 0 | u32 ttl, ttl_r = 0xffffffff; |
1278 | 0 | struct reply reply; |
1279 | 0 | struct request *req = NULL; |
1280 | 0 | unsigned int i, buf_size; |
1281 | |
|
1282 | 0 | memset(&reply, 0, sizeof(reply)); |
1283 | |
|
1284 | 0 | ASSERT_LOCKED(base); |
1285 | |
|
1286 | 0 | GET16(trans_id); |
1287 | 0 | GET16(flags); |
1288 | 0 | GET16(questions); |
1289 | 0 | GET16(answers); |
1290 | 0 | GET16(authority); |
1291 | 0 | GET16(additional); |
1292 | 0 | (void) authority; /* suppress "unused variable" warnings. */ |
1293 | 0 | (void) additional; /* suppress "unused variable" warnings. */ |
1294 | |
|
1295 | 0 | req = request_find_from_trans_id(base, trans_id); |
1296 | 0 | if (!req) return -1; |
1297 | 0 | EVUTIL_ASSERT(req->base == base); |
1298 | | |
1299 | | /* If it's not an answer, it doesn't correspond to any request. */ |
1300 | 0 | if (!(flags & _QR_MASK)) return -1; /* must be an answer */ |
1301 | 0 | if ((flags & (_RCODE_MASK|_TC_MASK)) && (flags & (_RCODE_MASK|_TC_MASK)) != DNS_ERR_NOTEXIST) { |
1302 | | /* there was an error and it's not NXDOMAIN */ |
1303 | 0 | goto err; |
1304 | 0 | } |
1305 | | /* if (!answers) return; */ /* must have an answer of some form */ |
1306 | | |
1307 | | /* This macro skips a name in the DNS reply. */ |
1308 | 0 | #define SKIP_NAME \ |
1309 | 0 | do { tmp_name[0] = '\0'; \ |
1310 | 0 | if (name_parse(packet, length, &j, tmp_name, \ |
1311 | 0 | sizeof(tmp_name))<0) \ |
1312 | 0 | goto err; \ |
1313 | 0 | } while (0) |
1314 | | |
1315 | 0 | reply.type = req->request_type; |
1316 | | |
1317 | | /* skip over each question in the reply */ |
1318 | 0 | for (i = 0; i < questions; ++i) { |
1319 | | /* the question looks like |
1320 | | * <label:name><u16:type><u16:class> |
1321 | | */ |
1322 | 0 | tmp_name[0] = '\0'; |
1323 | 0 | cmp_name[0] = '\0'; |
1324 | 0 | k = j; |
1325 | 0 | if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name)) < 0) |
1326 | 0 | goto err; |
1327 | 0 | if (name_parse(req->request, req->request_len, &k, |
1328 | 0 | cmp_name, sizeof(cmp_name))<0) |
1329 | 0 | goto err; |
1330 | 0 | if (!base->global_randomize_case) { |
1331 | 0 | if (strcmp(tmp_name, cmp_name) == 0) |
1332 | 0 | name_matches = 1; |
1333 | 0 | } else { |
1334 | 0 | if (evutil_ascii_strcasecmp(tmp_name, cmp_name) == 0) |
1335 | 0 | name_matches = 1; |
1336 | 0 | } |
1337 | |
|
1338 | 0 | j += 4; |
1339 | 0 | if (j > length) |
1340 | 0 | goto err; |
1341 | 0 | } |
1342 | | |
1343 | 0 | if (!name_matches) |
1344 | 0 | goto err; |
1345 | | |
1346 | | /* We can allocate less for the reply data, but to do it we'll have |
1347 | | * to parse the response. To simplify things let's just allocate |
1348 | | * a little bit more to avoid complex evaluations. |
1349 | | */ |
1350 | 0 | buf_size = MAX(length - j, EVDNS_NAME_MAX); |
1351 | 0 | reply.data.raw = mm_malloc(buf_size); |
1352 | | |
1353 | | /* now we have the answer section which looks like |
1354 | | * <label:name><u16:type><u16:class><u32:ttl><u16:len><data...> |
1355 | | */ |
1356 | |
|
1357 | 0 | for (i = 0; i < answers; ++i) { |
1358 | 0 | u16 type, class; |
1359 | |
|
1360 | 0 | SKIP_NAME; |
1361 | 0 | GET16(type); |
1362 | 0 | GET16(class); |
1363 | 0 | GET32(ttl); |
1364 | 0 | GET16(datalength); |
1365 | | |
1366 | 0 | if (type == TYPE_A && class == CLASS_INET) { |
1367 | 0 | int addrcount; |
1368 | 0 | if (req->request_type != TYPE_A) { |
1369 | 0 | j += datalength; continue; |
1370 | 0 | } |
1371 | 0 | if ((datalength & 3) != 0) /* not an even number of As. */ |
1372 | 0 | goto err; |
1373 | 0 | addrcount = datalength >> 2; |
1374 | |
|
1375 | 0 | ttl_r = MIN(ttl_r, ttl); |
1376 | | /* we only bother with the first four addresses. */ |
1377 | 0 | if (j + 4*addrcount > length) goto err; |
1378 | 0 | memcpy(&reply.data.a[reply.rr_count], |
1379 | 0 | packet + j, 4*addrcount); |
1380 | 0 | j += 4*addrcount; |
1381 | 0 | reply.rr_count += addrcount; |
1382 | 0 | reply.have_answer = 1; |
1383 | 0 | } else if (type == TYPE_PTR && class == CLASS_INET) { |
1384 | 0 | if (req->request_type != TYPE_PTR) { |
1385 | 0 | j += datalength; continue; |
1386 | 0 | } |
1387 | 0 | if (name_parse(packet, length, &j, reply.data.ptr_name, |
1388 | 0 | buf_size)<0) |
1389 | 0 | goto err; |
1390 | 0 | ttl_r = MIN(ttl_r, ttl); |
1391 | 0 | reply.have_answer = 1; |
1392 | 0 | break; |
1393 | 0 | } else if (type == TYPE_CNAME) { |
1394 | 0 | char cname[EVDNS_NAME_MAX]; |
1395 | 0 | if (name_parse(packet, length, &j, cname, |
1396 | 0 | sizeof(cname))<0) |
1397 | 0 | goto err; |
1398 | 0 | if (req->need_cname) |
1399 | 0 | reply.cname = mm_strdup(cname); |
1400 | 0 | if (req->put_cname_in_ptr && !*req->put_cname_in_ptr) |
1401 | 0 | *req->put_cname_in_ptr = mm_strdup(cname); |
1402 | 0 | } else if (type == TYPE_AAAA && class == CLASS_INET) { |
1403 | 0 | int addrcount; |
1404 | 0 | if (req->request_type != TYPE_AAAA) { |
1405 | 0 | j += datalength; continue; |
1406 | 0 | } |
1407 | 0 | if ((datalength & 15) != 0) /* not an even number of AAAAs. */ |
1408 | 0 | goto err; |
1409 | 0 | addrcount = datalength >> 4; /* each address is 16 bytes long */ |
1410 | 0 | ttl_r = MIN(ttl_r, ttl); |
1411 | | |
1412 | | /* we only bother with the first four addresses. */ |
1413 | 0 | if (j + 16*addrcount > length) goto err; |
1414 | 0 | memcpy(&reply.data.aaaa[reply.rr_count], |
1415 | 0 | packet + j, 16*addrcount); |
1416 | 0 | reply.rr_count += addrcount; |
1417 | 0 | j += 16*addrcount; |
1418 | 0 | reply.have_answer = 1; |
1419 | 0 | } else { |
1420 | | /* skip over any other type of resource */ |
1421 | 0 | j += datalength; |
1422 | 0 | } |
1423 | 0 | } |
1424 | | |
1425 | 0 | if (!reply.have_answer) { |
1426 | 0 | for (i = 0; i < authority; ++i) { |
1427 | 0 | u16 type, class; |
1428 | 0 | SKIP_NAME; |
1429 | 0 | GET16(type); |
1430 | 0 | GET16(class); |
1431 | 0 | GET32(ttl); |
1432 | 0 | GET16(datalength); |
1433 | 0 | if (type == TYPE_SOA && class == CLASS_INET) { |
1434 | 0 | u32 serial, refresh, retry, expire, minimum; |
1435 | 0 | SKIP_NAME; |
1436 | 0 | SKIP_NAME; |
1437 | 0 | GET32(serial); |
1438 | 0 | GET32(refresh); |
1439 | 0 | GET32(retry); |
1440 | 0 | GET32(expire); |
1441 | 0 | GET32(minimum); |
1442 | 0 | (void)expire; |
1443 | 0 | (void)retry; |
1444 | 0 | (void)refresh; |
1445 | 0 | (void)serial; |
1446 | 0 | ttl_r = MIN(ttl_r, ttl); |
1447 | 0 | ttl_r = MIN(ttl_r, minimum); |
1448 | 0 | } else { |
1449 | | /* skip over any other type of resource */ |
1450 | 0 | j += datalength; |
1451 | 0 | } |
1452 | 0 | } |
1453 | 0 | } |
1454 | | |
1455 | 0 | if (ttl_r == 0xffffffff) |
1456 | 0 | ttl_r = 0; |
1457 | |
|
1458 | 0 | reply_handle(req, flags, ttl_r, &reply); |
1459 | 0 | if (reply.data.raw) |
1460 | 0 | mm_free(reply.data.raw); |
1461 | 0 | return 0; |
1462 | 0 | err: |
1463 | 0 | if (req) |
1464 | 0 | reply_handle(req, flags, 0, NULL); |
1465 | 0 | if (reply.data.raw) |
1466 | 0 | mm_free(reply.data.raw); |
1467 | 0 | return -1; |
1468 | 0 | } |
1469 | | |
1470 | | /* Parse a raw request (packet,length) sent to a nameserver port (port) from */ |
1471 | | /* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */ |
1472 | | /* callback. */ |
1473 | | static int |
1474 | | request_parse(u8 *packet, int length, struct evdns_server_port *port, |
1475 | | struct sockaddr *addr, ev_socklen_t addrlen, struct client_tcp_connection *client) |
1476 | 0 | { |
1477 | 0 | int j = 0; /* index into packet */ |
1478 | 0 | u16 t_; /* used by the macros */ |
1479 | 0 | u32 t32_; /* used by the macros */ |
1480 | 0 | char tmp_name[256]; /* used by the macros */ |
1481 | |
|
1482 | 0 | int i; |
1483 | 0 | u16 trans_id, flags, questions, answers, authority, additional; |
1484 | 0 | struct server_request *server_req = NULL; |
1485 | 0 | u32 ttl; |
1486 | 0 | u16 type, class, rdlen; |
1487 | |
|
1488 | 0 | ASSERT_LOCKED(port); |
1489 | | |
1490 | | /* Get the header fields */ |
1491 | 0 | GET16(trans_id); |
1492 | 0 | GET16(flags); |
1493 | 0 | GET16(questions); |
1494 | 0 | GET16(answers); |
1495 | 0 | GET16(authority); |
1496 | 0 | GET16(additional); |
1497 | | |
1498 | 0 | if (flags & _QR_MASK) return -1; /* Must not be an answer. */ |
1499 | 0 | flags &= (_RD_MASK|_CD_MASK); /* Only RD and CD get preserved. */ |
1500 | |
|
1501 | 0 | server_req = mm_malloc(sizeof(struct server_request)); |
1502 | 0 | if (server_req == NULL) return -1; |
1503 | 0 | memset(server_req, 0, sizeof(struct server_request)); |
1504 | |
|
1505 | 0 | server_req->trans_id = trans_id; |
1506 | 0 | if (addr) { |
1507 | 0 | memcpy(&server_req->addr, addr, addrlen); |
1508 | 0 | server_req->addrlen = addrlen; |
1509 | 0 | } |
1510 | |
|
1511 | 0 | server_req->port = port; |
1512 | 0 | server_req->client = client; |
1513 | 0 | server_req->base.flags = flags; |
1514 | 0 | server_req->base.nquestions = 0; |
1515 | 0 | server_req->base.questions = mm_calloc(sizeof(struct evdns_server_question *), questions); |
1516 | 0 | if (server_req->base.questions == NULL) |
1517 | 0 | goto err; |
1518 | | |
1519 | 0 | for (i = 0; i < questions; ++i) { |
1520 | 0 | u16 type, class; |
1521 | 0 | struct evdns_server_question *q; |
1522 | 0 | int namelen; |
1523 | 0 | if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) |
1524 | 0 | goto err; |
1525 | 0 | GET16(type); |
1526 | 0 | GET16(class); |
1527 | 0 | namelen = (int)strlen(tmp_name); |
1528 | 0 | q = mm_malloc(sizeof(struct evdns_server_question) + namelen); |
1529 | 0 | if (!q) |
1530 | 0 | goto err; |
1531 | 0 | q->type = type; |
1532 | 0 | q->dns_question_class = class; |
1533 | 0 | memcpy(q->name, tmp_name, namelen+1); |
1534 | 0 | server_req->base.questions[server_req->base.nquestions++] = q; |
1535 | 0 | } |
1536 | | |
1537 | 0 | #define SKIP_RR \ |
1538 | 0 | do { \ |
1539 | 0 | SKIP_NAME; \ |
1540 | 0 | j += 2 /* type */ + 2 /* class */ + 4 /* ttl */; \ |
1541 | 0 | GET16(rdlen); \ |
1542 | 0 | j += rdlen; \ |
1543 | 0 | } while (0) |
1544 | | |
1545 | 0 | for (i = 0; i < answers; ++i) { |
1546 | 0 | SKIP_RR; |
1547 | 0 | } |
1548 | | |
1549 | 0 | for (i = 0; i < authority; ++i) { |
1550 | 0 | SKIP_RR; |
1551 | 0 | } |
1552 | | |
1553 | 0 | server_req->max_udp_reply_size = DNS_MAX_UDP_SIZE; |
1554 | 0 | for (i = 0; i < additional; ++i) { |
1555 | 0 | SKIP_NAME; |
1556 | 0 | GET16(type); |
1557 | 0 | GET16(class); |
1558 | 0 | GET32(ttl); |
1559 | 0 | GET16(rdlen); |
1560 | 0 | (void)ttl; |
1561 | 0 | j += rdlen; |
1562 | 0 | if (type == TYPE_OPT) { |
1563 | | /* In case of OPT pseudo-RR `class` field is treated |
1564 | | * as a requestor's UDP payload size. */ |
1565 | 0 | server_req->max_udp_reply_size = MAX(class, DNS_MAX_UDP_SIZE); |
1566 | 0 | evdns_server_request_add_reply(&(server_req->base), |
1567 | 0 | EVDNS_ADDITIONAL_SECTION, |
1568 | 0 | "", /* name */ |
1569 | 0 | TYPE_OPT, /* type */ |
1570 | 0 | DNS_MAX_UDP_SIZE, /* class */ |
1571 | 0 | 0, /* ttl */ |
1572 | 0 | 0, /* datalen */ |
1573 | 0 | 0, /* is_name */ |
1574 | | NULL /* data */ |
1575 | 0 | ); |
1576 | 0 | break; |
1577 | 0 | } |
1578 | 0 | } |
1579 | | |
1580 | 0 | port->refcnt++; |
1581 | | |
1582 | | /* Only standard queries are supported. */ |
1583 | 0 | if (flags & _OP_MASK) { |
1584 | 0 | evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL); |
1585 | 0 | return -1; |
1586 | 0 | } |
1587 | | |
1588 | 0 | port->user_callback(&(server_req->base), port->user_data); |
1589 | |
|
1590 | 0 | return 0; |
1591 | 0 | err: |
1592 | 0 | if (server_req) { |
1593 | 0 | if (server_req->base.questions) { |
1594 | 0 | for (i = 0; i < server_req->base.nquestions; ++i) |
1595 | 0 | mm_free(server_req->base.questions[i]); |
1596 | 0 | mm_free(server_req->base.questions); |
1597 | 0 | } |
1598 | 0 | mm_free(server_req); |
1599 | 0 | } |
1600 | 0 | return -1; |
1601 | |
|
1602 | 0 | #undef SKIP_RR |
1603 | 0 | #undef SKIP_NAME |
1604 | 0 | #undef GET32 |
1605 | 0 | #undef GET16 |
1606 | 0 | #undef GET8 |
1607 | 0 | } |
1608 | | |
1609 | | /* Try to choose a strong transaction id which isn't already in flight */ |
1610 | | static u16 |
1611 | 0 | transaction_id_pick(struct evdns_base *base) { |
1612 | 0 | ASSERT_LOCKED(base); |
1613 | 0 | for (;;) { |
1614 | 0 | u16 trans_id; |
1615 | 0 | evutil_secure_rng_get_bytes(&trans_id, sizeof(trans_id)); |
1616 | |
|
1617 | 0 | if (trans_id == 0xffff) continue; |
1618 | | /* now check to see if that id is already inflight */ |
1619 | 0 | if (request_find_from_trans_id(base, trans_id) == NULL) |
1620 | 0 | return trans_id; |
1621 | 0 | } |
1622 | 0 | } |
1623 | | |
1624 | | /* choose a namesever to use. This function will try to ignore */ |
1625 | | /* nameservers which we think are down and load balance across the rest */ |
1626 | | /* by updating the server_head global each time. */ |
1627 | | static struct nameserver * |
1628 | 0 | nameserver_pick(struct evdns_base *base) { |
1629 | 0 | struct nameserver *started_at = base->server_head, *picked; |
1630 | 0 | ASSERT_LOCKED(base); |
1631 | 0 | if (!base->server_head) return NULL; |
1632 | | |
1633 | | /* if we don't have any good nameservers then there's no */ |
1634 | | /* point in trying to find one. */ |
1635 | 0 | if (!base->global_good_nameservers) { |
1636 | 0 | base->server_head = base->server_head->next; |
1637 | 0 | return base->server_head; |
1638 | 0 | } |
1639 | | |
1640 | | /* remember that nameservers are in a circular list */ |
1641 | 0 | for (;;) { |
1642 | 0 | if (base->server_head->state) { |
1643 | | /* we think this server is currently good */ |
1644 | 0 | picked = base->server_head; |
1645 | 0 | base->server_head = base->server_head->next; |
1646 | 0 | return picked; |
1647 | 0 | } |
1648 | | |
1649 | 0 | base->server_head = base->server_head->next; |
1650 | 0 | if (base->server_head == started_at) { |
1651 | | /* all the nameservers seem to be down */ |
1652 | | /* so we just return this one and hope for the */ |
1653 | | /* best */ |
1654 | 0 | EVUTIL_ASSERT(base->global_good_nameservers == 0); |
1655 | 0 | picked = base->server_head; |
1656 | 0 | base->server_head = base->server_head->next; |
1657 | 0 | return picked; |
1658 | 0 | } |
1659 | 0 | } |
1660 | 0 | } |
1661 | | |
1662 | | /* this is called when a namesever socket is ready for reading */ |
1663 | | static void |
1664 | 0 | nameserver_read(struct nameserver *ns) { |
1665 | 0 | struct sockaddr_storage ss; |
1666 | 0 | ev_socklen_t addrlen = sizeof(ss); |
1667 | 0 | char addrbuf[128]; |
1668 | 0 | const size_t max_packet_size = ns->base->global_max_udp_size; |
1669 | 0 | u8 *packet = mm_malloc(max_packet_size); |
1670 | 0 | ASSERT_LOCKED(ns->base); |
1671 | |
|
1672 | 0 | if (!packet) { |
1673 | 0 | nameserver_failed(ns, "not enough memory", 0); |
1674 | 0 | return; |
1675 | 0 | } |
1676 | | |
1677 | 0 | for (;;) { |
1678 | 0 | const int r = recvfrom(ns->socket, (void*)packet, |
1679 | 0 | max_packet_size, 0, |
1680 | 0 | (struct sockaddr*)&ss, &addrlen); |
1681 | 0 | if (r < 0) { |
1682 | 0 | int err = evutil_socket_geterror(ns->socket); |
1683 | 0 | if (EVUTIL_ERR_RW_RETRIABLE(err)) |
1684 | 0 | goto done; |
1685 | 0 | nameserver_failed(ns, |
1686 | 0 | evutil_socket_error_to_string(err), err); |
1687 | 0 | goto done; |
1688 | 0 | } |
1689 | 0 | if (evutil_sockaddr_cmp((struct sockaddr*)&ss, |
1690 | 0 | (struct sockaddr*)&ns->address, 0)) { |
1691 | 0 | log(EVDNS_LOG_WARN, "Address mismatch on received " |
1692 | 0 | "DNS packet. Apparent source was %s", |
1693 | 0 | evutil_format_sockaddr_port_( |
1694 | 0 | (struct sockaddr *)&ss, |
1695 | 0 | addrbuf, sizeof(addrbuf))); |
1696 | 0 | goto done; |
1697 | 0 | } |
1698 | | |
1699 | 0 | ns->timedout = 0; |
1700 | 0 | reply_parse(ns->base, packet, r); |
1701 | 0 | } |
1702 | 0 | done: |
1703 | 0 | mm_free(packet); |
1704 | 0 | } |
1705 | | |
1706 | | /* Read a packet from a DNS client on a server port s, parse it, and */ |
1707 | | /* act accordingly. */ |
1708 | | static void |
1709 | 0 | server_udp_port_read(struct evdns_server_port *s) { |
1710 | 0 | u8 packet[1500]; |
1711 | 0 | struct sockaddr_storage addr; |
1712 | 0 | ev_socklen_t addrlen; |
1713 | 0 | int r; |
1714 | 0 | ASSERT_LOCKED(s); |
1715 | |
|
1716 | 0 | for (;;) { |
1717 | 0 | addrlen = sizeof(struct sockaddr_storage); |
1718 | 0 | r = recvfrom(s->socket, (void*)packet, sizeof(packet), 0, |
1719 | 0 | (struct sockaddr*) &addr, &addrlen); |
1720 | 0 | if (r < 0) { |
1721 | 0 | int err = evutil_socket_geterror(s->socket); |
1722 | 0 | if (EVUTIL_ERR_RW_RETRIABLE(err)) |
1723 | 0 | return; |
1724 | 0 | log(EVDNS_LOG_WARN, |
1725 | 0 | "Error %s (%d) while reading request.", |
1726 | 0 | evutil_socket_error_to_string(err), err); |
1727 | 0 | return; |
1728 | 0 | } |
1729 | 0 | request_parse(packet, r, s, (struct sockaddr*) &addr, addrlen, NULL); |
1730 | 0 | } |
1731 | 0 | } |
1732 | | |
1733 | | static int |
1734 | | server_send_response(struct evdns_server_port *port, struct server_request *req) |
1735 | 0 | { |
1736 | 0 | u16 packet_size = 0; |
1737 | 0 | struct bufferevent *bev = NULL; |
1738 | 0 | if (req->client) { |
1739 | 0 | bev = req->client->connection.bev; |
1740 | 0 | EVUTIL_ASSERT(bev); |
1741 | 0 | EVUTIL_ASSERT(req->response_len <= 65535); |
1742 | 0 | packet_size = htons((u16)req->response_len); |
1743 | 0 | if (bufferevent_write(bev, &packet_size, sizeof(packet_size))) |
1744 | 0 | goto beferevent_error; |
1745 | 0 | if (bufferevent_write(bev, (void*)req->response, req->response_len)) |
1746 | 0 | goto beferevent_error; |
1747 | 0 | return (int)req->response_len; |
1748 | 0 | } else { |
1749 | 0 | int r = sendto(port->socket, req->response, (int)req->response_len, 0, |
1750 | 0 | (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); |
1751 | 0 | return r; |
1752 | 0 | } |
1753 | | |
1754 | 0 | beferevent_error: |
1755 | 0 | log(EVDNS_LOG_WARN, "Failed to send reply to request %p for client %p", (void *)req, (void *)req->client); |
1756 | | /* disconnect if we got bufferevent error */ |
1757 | 0 | evdns_remove_tcp_client(port, req->client); |
1758 | 0 | return -1; |
1759 | 0 | } |
1760 | | |
1761 | | /* Try to write all pending replies on a given DNS server port. */ |
1762 | | static void |
1763 | | server_port_flush(struct evdns_server_port *port) |
1764 | 0 | { |
1765 | 0 | struct server_request *req = port->pending_replies; |
1766 | 0 | ASSERT_LOCKED(port); |
1767 | 0 | while (req) { |
1768 | 0 | int r = server_send_response(port, req); |
1769 | 0 | if (r < 0) { |
1770 | 0 | int err = evutil_socket_geterror(port->socket); |
1771 | 0 | if (EVUTIL_ERR_RW_RETRIABLE(err)) |
1772 | 0 | return; |
1773 | 0 | log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", evutil_socket_error_to_string(err), err); |
1774 | 0 | } |
1775 | 0 | if (server_request_free(req)) { |
1776 | | /* we released the last reference to req->port. */ |
1777 | 0 | return; |
1778 | 0 | } else { |
1779 | 0 | EVUTIL_ASSERT(req != port->pending_replies); |
1780 | 0 | req = port->pending_replies; |
1781 | 0 | } |
1782 | 0 | } |
1783 | | |
1784 | | /* We have no more pending requests; stop listening for 'writeable' events. */ |
1785 | 0 | (void) event_del(&port->event); |
1786 | 0 | event_assign(&port->event, port->event_base, |
1787 | 0 | port->socket, EV_READ | EV_PERSIST, |
1788 | 0 | server_port_ready_callback, port); |
1789 | |
|
1790 | 0 | if (event_add(&port->event, NULL) < 0) { |
1791 | 0 | log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server."); |
1792 | | /* ???? Do more? */ |
1793 | 0 | } |
1794 | 0 | } |
1795 | | |
1796 | | /* set if we are waiting for the ability to write to this server. */ |
1797 | | /* if waiting is true then we ask libevent for EV_WRITE events, otherwise */ |
1798 | | /* we stop these events. */ |
1799 | | static void |
1800 | 0 | nameserver_write_waiting(struct nameserver *ns, char waiting) { |
1801 | 0 | ASSERT_LOCKED(ns->base); |
1802 | 0 | if (ns->write_waiting == waiting) return; |
1803 | | |
1804 | 0 | ns->write_waiting = waiting; |
1805 | 0 | (void) event_del(&ns->event); |
1806 | 0 | event_assign(&ns->event, ns->base->event_base, |
1807 | 0 | ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST, |
1808 | 0 | nameserver_ready_callback, ns); |
1809 | 0 | if (event_add(&ns->event, NULL) < 0) { |
1810 | 0 | char addrbuf[128]; |
1811 | 0 | log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s", |
1812 | 0 | evutil_format_sockaddr_port_( |
1813 | 0 | (struct sockaddr *)&ns->address, |
1814 | 0 | addrbuf, sizeof(addrbuf))); |
1815 | | /* ???? Do more? */ |
1816 | 0 | } |
1817 | 0 | } |
1818 | | |
1819 | | /* a callback function. Called by libevent when the kernel says that */ |
1820 | | /* a nameserver socket is ready for writing or reading */ |
1821 | | static void |
1822 | 0 | nameserver_ready_callback(evutil_socket_t fd, short events, void *arg) { |
1823 | 0 | struct nameserver *ns = (struct nameserver *) arg; |
1824 | 0 | (void)fd; |
1825 | |
|
1826 | 0 | EVDNS_LOCK(ns->base); |
1827 | 0 | if (events & EV_WRITE) { |
1828 | 0 | ns->choked = 0; |
1829 | 0 | if (!evdns_transmit(ns->base)) { |
1830 | 0 | nameserver_write_waiting(ns, 0); |
1831 | 0 | } |
1832 | 0 | } |
1833 | 0 | if (events & EV_READ) { |
1834 | 0 | nameserver_read(ns); |
1835 | 0 | } |
1836 | 0 | EVDNS_UNLOCK(ns->base); |
1837 | 0 | } |
1838 | | |
1839 | | /* a callback function. Called by libevent when the kernel says that */ |
1840 | | /* a server socket is ready for writing or reading. */ |
1841 | | static void |
1842 | 0 | server_port_ready_callback(evutil_socket_t fd, short events, void *arg) { |
1843 | 0 | struct evdns_server_port *port = (struct evdns_server_port *) arg; |
1844 | 0 | (void) fd; |
1845 | |
|
1846 | 0 | EVDNS_LOCK(port); |
1847 | 0 | if (events & EV_WRITE) { |
1848 | 0 | port->choked = 0; |
1849 | 0 | server_port_flush(port); |
1850 | 0 | } |
1851 | 0 | if (events & EV_READ) { |
1852 | 0 | server_udp_port_read(port); |
1853 | 0 | } |
1854 | 0 | EVDNS_UNLOCK(port); |
1855 | 0 | } |
1856 | | |
1857 | | /* This is an inefficient representation; only use it via the dnslabel_table_* |
1858 | | * functions, so that is can be safely replaced with something smarter later. */ |
1859 | 0 | #define MAX_LABELS 128 |
1860 | | /* Structures used to implement name compression */ |
1861 | | struct dnslabel_entry { char *v; off_t pos; }; |
1862 | | struct dnslabel_table { |
1863 | | int n_labels; /* number of current entries */ |
1864 | | /* map from name to position in message */ |
1865 | | struct dnslabel_entry labels[MAX_LABELS]; |
1866 | | }; |
1867 | | |
1868 | | /* Initialize dnslabel_table. */ |
1869 | | static void |
1870 | | dnslabel_table_init(struct dnslabel_table *table) |
1871 | 0 | { |
1872 | 0 | table->n_labels = 0; |
1873 | 0 | } |
1874 | | |
1875 | | /* Free all storage held by table, but not the table itself. */ |
1876 | | static void |
1877 | | dnslabel_clear(struct dnslabel_table *table) |
1878 | 0 | { |
1879 | 0 | int i; |
1880 | 0 | for (i = 0; i < table->n_labels; ++i) |
1881 | 0 | mm_free(table->labels[i].v); |
1882 | 0 | table->n_labels = 0; |
1883 | 0 | } |
1884 | | |
1885 | | /* return the position of the label in the current message, or -1 if the label */ |
1886 | | /* hasn't been used yet. */ |
1887 | | static int |
1888 | | dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label) |
1889 | 0 | { |
1890 | 0 | int i; |
1891 | 0 | for (i = 0; i < table->n_labels; ++i) { |
1892 | 0 | if (!strcmp(label, table->labels[i].v)) |
1893 | 0 | return table->labels[i].pos; |
1894 | 0 | } |
1895 | 0 | return -1; |
1896 | 0 | } |
1897 | | |
1898 | | /* remember that we've used the label at position pos */ |
1899 | | static int |
1900 | | dnslabel_table_add(struct dnslabel_table *table, const char *label, off_t pos) |
1901 | 0 | { |
1902 | 0 | char *v; |
1903 | 0 | int p; |
1904 | 0 | if (table->n_labels == MAX_LABELS) |
1905 | 0 | return (-1); |
1906 | 0 | v = mm_strdup(label); |
1907 | 0 | if (v == NULL) |
1908 | 0 | return (-1); |
1909 | 0 | p = table->n_labels++; |
1910 | 0 | table->labels[p].v = v; |
1911 | 0 | table->labels[p].pos = pos; |
1912 | |
|
1913 | 0 | return (0); |
1914 | 0 | } |
1915 | | |
1916 | | /* Converts a string to a length-prefixed set of DNS labels, starting */ |
1917 | | /* at buf[j]. name and buf must not overlap. name_len should be the length */ |
1918 | | /* of name. table is optional, and is used for compression. */ |
1919 | | /* */ |
1920 | | /* Input: abc.def */ |
1921 | | /* Output: <3>abc<3>def<0> */ |
1922 | | /* */ |
1923 | | /* Returns the first index after the encoded name, or negative on error. */ |
1924 | | /* -1 label was > 63 bytes */ |
1925 | | /* -2 name too long to fit in buffer. */ |
1926 | | /* */ |
1927 | | static off_t |
1928 | | dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j, |
1929 | | const char *name, const size_t name_len, |
1930 | 0 | struct dnslabel_table *table) { |
1931 | 0 | const char *end = name + name_len; |
1932 | 0 | int ref = 0; |
1933 | 0 | u16 t_; |
1934 | |
|
1935 | 0 | #define APPEND16(x) do { \ |
1936 | 0 | if (j + 2 > (off_t)buf_len) \ |
1937 | 0 | goto overflow; \ |
1938 | 0 | t_ = htons(x); \ |
1939 | 0 | memcpy(buf + j, &t_, 2); \ |
1940 | 0 | j += 2; \ |
1941 | 0 | } while (0) |
1942 | 0 | #define APPEND32(x) do { \ |
1943 | 0 | if (j + 4 > (off_t)buf_len) \ |
1944 | 0 | goto overflow; \ |
1945 | 0 | t32_ = htonl(x); \ |
1946 | 0 | memcpy(buf + j, &t32_, 4); \ |
1947 | 0 | j += 4; \ |
1948 | 0 | } while (0) |
1949 | |
|
1950 | 0 | if (name_len > 255) return -2; |
1951 | | |
1952 | 0 | for (;;) { |
1953 | 0 | const char *const start = name; |
1954 | 0 | if (table && (ref = dnslabel_table_get_pos(table, name)) >= 0) { |
1955 | 0 | APPEND16(ref | 0xc000); |
1956 | 0 | return j; |
1957 | 0 | } |
1958 | 0 | name = strchr(name, '.'); |
1959 | 0 | if (!name) { |
1960 | 0 | const size_t label_len = end - start; |
1961 | 0 | if (label_len > 63) return -1; |
1962 | 0 | if ((size_t)(j+label_len+1) > buf_len) return -2; |
1963 | 0 | if (table) dnslabel_table_add(table, start, j); |
1964 | 0 | buf[j++] = (ev_uint8_t)label_len; |
1965 | |
|
1966 | 0 | memcpy(buf + j, start, label_len); |
1967 | 0 | j += (int) label_len; |
1968 | 0 | break; |
1969 | 0 | } else { |
1970 | | /* append length of the label. */ |
1971 | 0 | const size_t label_len = name - start; |
1972 | 0 | if (label_len > 63) return -1; |
1973 | 0 | if ((size_t)(j+label_len+1) > buf_len) return -2; |
1974 | 0 | if (table) dnslabel_table_add(table, start, j); |
1975 | 0 | buf[j++] = (ev_uint8_t)label_len; |
1976 | |
|
1977 | 0 | memcpy(buf + j, start, label_len); |
1978 | 0 | j += (int) label_len; |
1979 | | /* hop over the '.' */ |
1980 | 0 | name++; |
1981 | 0 | } |
1982 | 0 | } |
1983 | | |
1984 | | /* the labels must be terminated by a 0. */ |
1985 | | /* It's possible that the name ended in a . */ |
1986 | | /* in which case the zero is already there */ |
1987 | 0 | if (!j || buf[j-1]) buf[j++] = 0; |
1988 | 0 | return j; |
1989 | 0 | overflow: |
1990 | 0 | return (-2); |
1991 | 0 | } |
1992 | | |
1993 | | /* Finds the length of a dns request for a DNS name of the given */ |
1994 | | /* length. The actual request may be smaller than the value returned */ |
1995 | | /* here */ |
1996 | | static size_t |
1997 | | evdns_request_len(const struct evdns_base *base, const size_t name_len) |
1998 | 0 | { |
1999 | 0 | int additional_section_len = 0; |
2000 | 0 | if (EDNS_ENABLED(base)) { |
2001 | 0 | additional_section_len = 1 + /* length of domain name string, always 0 */ |
2002 | 0 | 2 + /* space for resource type */ |
2003 | 0 | 2 + /* space for UDP payload size */ |
2004 | 0 | 4 + /* space for extended RCODE flags */ |
2005 | 0 | 2; /* space for length of RDATA, always 0 */ |
2006 | 0 | } |
2007 | 0 | return 96 + /* length of the DNS standard header */ |
2008 | 0 | name_len + 2 + |
2009 | 0 | 4 /* space for the resource type */ + |
2010 | 0 | additional_section_len; |
2011 | 0 | } |
2012 | | |
2013 | | /* build a dns request packet into buf. buf should be at least as long */ |
2014 | | /* as evdns_request_len told you it should be. */ |
2015 | | /* */ |
2016 | | /* Returns the amount of space used. Negative on error. */ |
2017 | | static int |
2018 | | evdns_request_data_build(const struct evdns_base *base, |
2019 | | const char *const name, const size_t name_len, |
2020 | | const u16 trans_id, const u16 type, const u16 class, u8 *const buf, |
2021 | | size_t buf_len) |
2022 | 0 | { |
2023 | 0 | off_t j = 0; /* current offset into buf */ |
2024 | 0 | u16 t_; /* used by the macros */ |
2025 | 0 | u32 t32_; /* used by the macros */ |
2026 | |
|
2027 | 0 | APPEND16(trans_id); |
2028 | 0 | APPEND16(0x0100); /* standard query, recusion needed */ |
2029 | 0 | APPEND16(1); /* one question */ |
2030 | 0 | APPEND16(0); /* no answers */ |
2031 | 0 | APPEND16(0); /* no authority */ |
2032 | 0 | APPEND16(EDNS_ENABLED(base) ? 1 : 0); /* additional */ |
2033 | | |
2034 | 0 | j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL); |
2035 | 0 | if (j < 0) { |
2036 | 0 | return (int)j; |
2037 | 0 | } |
2038 | | |
2039 | 0 | APPEND16(type); |
2040 | 0 | APPEND16(class); |
2041 | | |
2042 | 0 | if (EDNS_ENABLED(base)) { |
2043 | | /* The OPT pseudo-RR format |
2044 | | * (https://tools.ietf.org/html/rfc6891#section-6.1.2) |
2045 | | * +------------+--------------+------------------------------+ |
2046 | | * | Field Name | Field Type | Description | |
2047 | | * +------------+--------------+------------------------------+ |
2048 | | * | NAME | domain name | MUST be 0 (root domain) | |
2049 | | * | TYPE | u_int16_t | OPT (41) | |
2050 | | * | CLASS | u_int16_t | requestor's UDP payload size | |
2051 | | * | TTL | u_int32_t | extended RCODE and flags | |
2052 | | * | RDLEN | u_int16_t | length of all RDATA | |
2053 | | * | RDATA | octet stream | {attribute,value} pairs | |
2054 | | * +------------+--------------+------------------------------+ */ |
2055 | 0 | buf[j++] = 0; /* NAME, always 0 */ |
2056 | 0 | APPEND16(TYPE_OPT); /* OPT type */ |
2057 | 0 | APPEND16(base->global_max_udp_size); /* max UDP payload size */ |
2058 | 0 | APPEND32(0); /* No extended RCODE flags set */ |
2059 | 0 | APPEND16(0); /* length of RDATA is 0 */ |
2060 | 0 | } |
2061 | | |
2062 | 0 | return (int)j; |
2063 | 0 | overflow: |
2064 | 0 | return (-1); |
2065 | 0 | } |
2066 | | |
2067 | | /* exported function */ |
2068 | | struct evdns_server_port * |
2069 | | evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type cb, void *user_data) |
2070 | 0 | { |
2071 | 0 | struct evdns_server_port *port; |
2072 | 0 | if (flags) |
2073 | 0 | return NULL; /* flags not yet implemented */ |
2074 | 0 | if (!(port = mm_malloc(sizeof(struct evdns_server_port)))) |
2075 | 0 | return NULL; |
2076 | 0 | memset(port, 0, sizeof(struct evdns_server_port)); |
2077 | | |
2078 | |
|
2079 | 0 | port->socket = socket; |
2080 | 0 | port->refcnt = 1; |
2081 | 0 | port->choked = 0; |
2082 | 0 | port->closing = 0; |
2083 | 0 | port->user_callback = cb; |
2084 | 0 | port->user_data = user_data; |
2085 | 0 | port->pending_replies = NULL; |
2086 | 0 | port->event_base = base; |
2087 | 0 | port->max_client_connections = MAX_CLIENT_CONNECTIONS; |
2088 | 0 | port->tcp_idle_timeout.tv_sec = SERVER_IDLE_CONN_TIMEOUT; |
2089 | 0 | port->tcp_idle_timeout.tv_usec = 0; |
2090 | 0 | port->client_connections_count = 0; |
2091 | 0 | LIST_INIT(&port->client_connections); |
2092 | 0 | event_assign(&port->event, port->event_base, |
2093 | 0 | port->socket, EV_READ | EV_PERSIST, |
2094 | 0 | server_port_ready_callback, port); |
2095 | 0 | if (event_add(&port->event, NULL) < 0) { |
2096 | 0 | mm_free(port); |
2097 | 0 | return NULL; |
2098 | 0 | } |
2099 | 0 | EVTHREAD_ALLOC_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); |
2100 | 0 | return port; |
2101 | 0 | } |
2102 | | |
2103 | | /* exported function */ |
2104 | | struct evdns_server_port * |
2105 | | evdns_add_server_port_with_listener(struct event_base *base, struct evconnlistener *listener, int flags, evdns_request_callback_fn_type cb, void *user_data) |
2106 | 0 | { |
2107 | 0 | struct evdns_server_port *port; |
2108 | 0 | if (!listener) |
2109 | 0 | return NULL; |
2110 | 0 | if (flags) |
2111 | 0 | return NULL; /* flags not yet implemented */ |
2112 | | |
2113 | 0 | if (!(port = mm_calloc(1, sizeof(struct evdns_server_port)))) |
2114 | 0 | return NULL; |
2115 | 0 | port->socket = -1; |
2116 | 0 | port->refcnt = 1; |
2117 | 0 | port->choked = 0; |
2118 | 0 | port->closing = 0; |
2119 | 0 | port->user_callback = cb; |
2120 | 0 | port->user_data = user_data; |
2121 | 0 | port->pending_replies = NULL; |
2122 | 0 | port->event_base = base; |
2123 | 0 | port->max_client_connections = MAX_CLIENT_CONNECTIONS; |
2124 | 0 | port->client_connections_count = 0; |
2125 | 0 | LIST_INIT(&port->client_connections); |
2126 | 0 | port->listener = listener; |
2127 | 0 | evconnlistener_set_cb(port->listener, incoming_conn_cb, port); |
2128 | |
|
2129 | 0 | EVTHREAD_ALLOC_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); |
2130 | 0 | return port; |
2131 | 0 | } |
2132 | | |
2133 | | static void |
2134 | | server_tcp_event_cb(struct bufferevent *bev, short events, void *ctx); |
2135 | | |
2136 | | static int |
2137 | | tcp_read_message(struct tcp_connection *conn, u8 **msg, int *msg_len) |
2138 | 0 | { |
2139 | 0 | struct bufferevent *bev = conn->bev; |
2140 | 0 | struct evbuffer *input = bufferevent_get_input(bev); |
2141 | 0 | u8 *packet = NULL; |
2142 | 0 | int r = 0; |
2143 | |
|
2144 | 0 | EVUTIL_ASSERT(conn); |
2145 | 0 | EVUTIL_ASSERT(conn->state == TS_CONNECTED); |
2146 | | |
2147 | | /* reading new packet size */ |
2148 | 0 | if (!conn->awaiting_packet_size) { |
2149 | 0 | if (evbuffer_get_length(input) < sizeof(ev_uint16_t)) |
2150 | 0 | goto awaiting_next; |
2151 | | |
2152 | 0 | bufferevent_read(bev, (void*)&conn->awaiting_packet_size, |
2153 | 0 | sizeof(conn->awaiting_packet_size)); |
2154 | 0 | conn->awaiting_packet_size = ntohs(conn->awaiting_packet_size); |
2155 | 0 | if (conn->awaiting_packet_size <= 0) |
2156 | 0 | goto fail; |
2157 | 0 | } |
2158 | | |
2159 | | /* reading new packet content */ |
2160 | 0 | if (evbuffer_get_length(input) < conn->awaiting_packet_size) |
2161 | 0 | goto awaiting_next; |
2162 | | |
2163 | 0 | packet = mm_malloc(conn->awaiting_packet_size); |
2164 | 0 | if (!packet) |
2165 | 0 | goto fail; |
2166 | | |
2167 | 0 | r = (int)bufferevent_read(bev, (void*)packet, conn->awaiting_packet_size); |
2168 | 0 | if (r != conn->awaiting_packet_size) { |
2169 | 0 | mm_free(packet); |
2170 | 0 | packet = NULL; |
2171 | 0 | goto fail; |
2172 | 0 | } |
2173 | | |
2174 | 0 | *msg = packet; |
2175 | 0 | *msg_len = r; |
2176 | 0 | awaiting_next: |
2177 | 0 | return 0; |
2178 | 0 | fail: |
2179 | 0 | return 1; |
2180 | 0 | } |
2181 | | |
2182 | | static void |
2183 | | server_tcp_read_packet_cb(struct bufferevent *bev, void *ctx) |
2184 | 0 | { |
2185 | 0 | u8 *msg = NULL; |
2186 | 0 | int msg_len = 0; |
2187 | 0 | int rc; |
2188 | 0 | struct client_tcp_connection *client = (struct client_tcp_connection *)ctx; |
2189 | 0 | struct evdns_server_port *port = client->port; |
2190 | 0 | struct tcp_connection *conn = &client->connection; |
2191 | 0 | EVUTIL_ASSERT(port && bev); |
2192 | 0 | EVDNS_LOCK(port); |
2193 | |
|
2194 | 0 | while (1) { |
2195 | 0 | if (tcp_read_message(conn, &msg, &msg_len)) { |
2196 | 0 | log(EVDNS_LOG_MSG, "Closing client connection %p due to error", (void *)bev); |
2197 | 0 | evdns_remove_tcp_client(port, client); |
2198 | 0 | rc = port->refcnt; |
2199 | 0 | EVDNS_UNLOCK(port); |
2200 | 0 | if (!rc) |
2201 | 0 | server_port_free(port); |
2202 | 0 | return; |
2203 | 0 | } |
2204 | | |
2205 | | /* Only part of the message was received. */ |
2206 | 0 | if (!msg) |
2207 | 0 | break; |
2208 | | |
2209 | 0 | request_parse(msg, msg_len, port, NULL, 0, client); |
2210 | 0 | mm_free(msg); |
2211 | 0 | msg = NULL; |
2212 | 0 | conn->awaiting_packet_size = 0; |
2213 | 0 | } |
2214 | | |
2215 | 0 | bufferevent_setwatermark(bev, EV_READ, |
2216 | 0 | conn->awaiting_packet_size ? conn->awaiting_packet_size : sizeof(ev_uint16_t), 0); |
2217 | 0 | bufferevent_setcb(bev, server_tcp_read_packet_cb, NULL, server_tcp_event_cb, ctx); |
2218 | 0 | EVDNS_UNLOCK(port); |
2219 | 0 | } |
2220 | | |
2221 | | static void |
2222 | | server_tcp_event_cb(struct bufferevent *bev, short events, void *ctx) |
2223 | 0 | { |
2224 | 0 | struct client_tcp_connection *client = (struct client_tcp_connection *)ctx; |
2225 | 0 | struct evdns_server_port *port = client->port; |
2226 | 0 | int rc; |
2227 | 0 | EVUTIL_ASSERT(port && bev); |
2228 | 0 | EVDNS_LOCK(port); |
2229 | 0 | if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { |
2230 | 0 | log(EVDNS_LOG_DEBUG, "Closing connection %p", (void *)bev); |
2231 | 0 | evdns_remove_tcp_client(port, client); |
2232 | 0 | } |
2233 | 0 | rc = port->refcnt; |
2234 | 0 | EVDNS_UNLOCK(port); |
2235 | 0 | if (!rc) |
2236 | 0 | server_port_free(port); |
2237 | 0 | } |
2238 | | |
2239 | | static void |
2240 | | incoming_conn_cb(struct evconnlistener *listener, evutil_socket_t fd, |
2241 | | struct sockaddr *address, int socklen, void *arg) |
2242 | 0 | { |
2243 | 0 | struct evdns_server_port *port = (struct evdns_server_port*)arg; |
2244 | 0 | struct bufferevent *bev = bufferevent_socket_new(port->event_base, fd, BEV_OPT_CLOSE_ON_FREE); |
2245 | 0 | struct client_tcp_connection *client = NULL; |
2246 | 0 | struct tcp_connection *cd = NULL; |
2247 | |
|
2248 | 0 | if (!bev) |
2249 | 0 | goto error; |
2250 | 0 | log(EVDNS_LOG_DEBUG, "New incoming client connection %p", (void *)bev); |
2251 | |
|
2252 | 0 | bufferevent_set_timeouts(bev, &port->tcp_idle_timeout, &port->tcp_idle_timeout); |
2253 | |
|
2254 | 0 | client = evdns_add_tcp_client(port, bev); |
2255 | 0 | if (!client) |
2256 | 0 | goto error; |
2257 | 0 | cd = &client->connection; |
2258 | |
|
2259 | 0 | cd->state = TS_CONNECTED; |
2260 | 0 | bufferevent_setwatermark(bev, EV_READ, sizeof(ev_uint16_t), 0); |
2261 | 0 | bufferevent_setcb(bev, server_tcp_read_packet_cb, NULL, server_tcp_event_cb, (void *)client); |
2262 | 0 | bufferevent_enable(bev, EV_READ); |
2263 | |
|
2264 | 0 | return; |
2265 | 0 | error: |
2266 | 0 | if (bev) |
2267 | 0 | bufferevent_free(bev); |
2268 | 0 | return; |
2269 | 0 | } |
2270 | | |
2271 | | struct evdns_server_port * |
2272 | | evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type cb, void *user_data) |
2273 | 0 | { |
2274 | 0 | return evdns_add_server_port_with_base(NULL, socket, flags, cb, user_data); |
2275 | 0 | } |
2276 | | |
2277 | | /* exported function */ |
2278 | | void |
2279 | | evdns_close_server_port(struct evdns_server_port *port) |
2280 | 0 | { |
2281 | 0 | EVDNS_LOCK(port); |
2282 | 0 | evdns_remove_all_tcp_clients(port); |
2283 | 0 | if (--port->refcnt == 0) { |
2284 | 0 | EVDNS_UNLOCK(port); |
2285 | 0 | server_port_free(port); |
2286 | 0 | } else { |
2287 | 0 | port->closing = 1; |
2288 | 0 | EVDNS_UNLOCK(port); |
2289 | 0 | } |
2290 | 0 | } |
2291 | | |
2292 | | /* exported function */ |
2293 | | int |
2294 | | evdns_server_request_add_reply(struct evdns_server_request *req_, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data) |
2295 | 0 | { |
2296 | 0 | struct server_request *req = TO_SERVER_REQUEST(req_); |
2297 | 0 | struct server_reply_item **itemp, *item; |
2298 | 0 | int *countp; |
2299 | 0 | int result = -1; |
2300 | |
|
2301 | 0 | EVDNS_LOCK(req->port); |
2302 | 0 | if (req->response) /* have we already answered? */ |
2303 | 0 | goto done; |
2304 | | |
2305 | 0 | switch (section) { |
2306 | 0 | case EVDNS_ANSWER_SECTION: |
2307 | 0 | itemp = &req->answer; |
2308 | 0 | countp = &req->n_answer; |
2309 | 0 | break; |
2310 | 0 | case EVDNS_AUTHORITY_SECTION: |
2311 | 0 | itemp = &req->authority; |
2312 | 0 | countp = &req->n_authority; |
2313 | 0 | break; |
2314 | 0 | case EVDNS_ADDITIONAL_SECTION: |
2315 | 0 | itemp = &req->additional; |
2316 | 0 | countp = &req->n_additional; |
2317 | 0 | break; |
2318 | 0 | default: |
2319 | 0 | goto done; |
2320 | 0 | } |
2321 | 0 | while (*itemp) { |
2322 | 0 | itemp = &((*itemp)->next); |
2323 | 0 | } |
2324 | 0 | item = mm_malloc(sizeof(struct server_reply_item)); |
2325 | 0 | if (!item) |
2326 | 0 | goto done; |
2327 | 0 | item->next = NULL; |
2328 | 0 | if (!(item->name = mm_strdup(name))) { |
2329 | 0 | mm_free(item); |
2330 | 0 | goto done; |
2331 | 0 | } |
2332 | 0 | item->type = type; |
2333 | 0 | item->dns_question_class = class; |
2334 | 0 | item->ttl = ttl; |
2335 | 0 | item->is_name = is_name != 0; |
2336 | 0 | item->datalen = 0; |
2337 | 0 | item->data = NULL; |
2338 | 0 | if (data) { |
2339 | 0 | if (item->is_name) { |
2340 | 0 | if (!(item->data = mm_strdup(data))) { |
2341 | 0 | mm_free(item->name); |
2342 | 0 | mm_free(item); |
2343 | 0 | goto done; |
2344 | 0 | } |
2345 | 0 | item->datalen = (u16)-1; |
2346 | 0 | } else { |
2347 | 0 | if (!(item->data = mm_malloc(datalen))) { |
2348 | 0 | mm_free(item->name); |
2349 | 0 | mm_free(item); |
2350 | 0 | goto done; |
2351 | 0 | } |
2352 | 0 | item->datalen = datalen; |
2353 | 0 | memcpy(item->data, data, datalen); |
2354 | 0 | } |
2355 | 0 | } |
2356 | | |
2357 | 0 | *itemp = item; |
2358 | 0 | ++(*countp); |
2359 | 0 | result = 0; |
2360 | 0 | done: |
2361 | 0 | EVDNS_UNLOCK(req->port); |
2362 | 0 | return result; |
2363 | 0 | } |
2364 | | |
2365 | | /* exported function */ |
2366 | | int |
2367 | | evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl) |
2368 | 0 | { |
2369 | 0 | return evdns_server_request_add_reply( |
2370 | 0 | req, EVDNS_ANSWER_SECTION, name, TYPE_A, CLASS_INET, |
2371 | 0 | ttl, n*4, 0, addrs); |
2372 | 0 | } |
2373 | | |
2374 | | /* exported function */ |
2375 | | int |
2376 | | evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl) |
2377 | 0 | { |
2378 | 0 | return evdns_server_request_add_reply( |
2379 | 0 | req, EVDNS_ANSWER_SECTION, name, TYPE_AAAA, CLASS_INET, |
2380 | 0 | ttl, n*16, 0, addrs); |
2381 | 0 | } |
2382 | | |
2383 | | /* exported function */ |
2384 | | int |
2385 | | evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl) |
2386 | 0 | { |
2387 | 0 | u32 a; |
2388 | 0 | char buf[32]; |
2389 | 0 | if (in && inaddr_name) |
2390 | 0 | return -1; |
2391 | 0 | else if (!in && !inaddr_name) |
2392 | 0 | return -1; |
2393 | 0 | if (in) { |
2394 | 0 | a = ntohl(in->s_addr); |
2395 | 0 | evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", |
2396 | 0 | (int)(u8)((a )&0xff), |
2397 | 0 | (int)(u8)((a>>8 )&0xff), |
2398 | 0 | (int)(u8)((a>>16)&0xff), |
2399 | 0 | (int)(u8)((a>>24)&0xff)); |
2400 | 0 | inaddr_name = buf; |
2401 | 0 | } |
2402 | 0 | return evdns_server_request_add_reply( |
2403 | 0 | req, EVDNS_ANSWER_SECTION, inaddr_name, TYPE_PTR, CLASS_INET, |
2404 | 0 | ttl, -1, 1, hostname); |
2405 | 0 | } |
2406 | | |
2407 | | /* exported function */ |
2408 | | int |
2409 | | evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl) |
2410 | 0 | { |
2411 | 0 | return evdns_server_request_add_reply( |
2412 | 0 | req, EVDNS_ANSWER_SECTION, name, TYPE_CNAME, CLASS_INET, |
2413 | 0 | ttl, -1, 1, cname); |
2414 | 0 | } |
2415 | | |
2416 | | /* exported function */ |
2417 | | void |
2418 | | evdns_server_request_set_flags(struct evdns_server_request *exreq, int flags) |
2419 | 0 | { |
2420 | 0 | struct server_request *req = TO_SERVER_REQUEST(exreq); |
2421 | 0 | req->base.flags &= ~(EVDNS_FLAGS_AA|EVDNS_FLAGS_RD); |
2422 | 0 | req->base.flags |= flags; |
2423 | 0 | } |
2424 | | |
2425 | | static int |
2426 | | evdns_server_request_format_response(struct server_request *req, int err) |
2427 | 0 | { |
2428 | 0 | unsigned char buf[1024 * 64]; |
2429 | 0 | size_t buf_len = sizeof(buf); |
2430 | 0 | off_t j = 0, r; |
2431 | 0 | u16 t_; |
2432 | 0 | u32 t32_; |
2433 | 0 | int i; |
2434 | 0 | u16 flags; |
2435 | 0 | struct dnslabel_table table; |
2436 | |
|
2437 | 0 | if (err < 0 || err > 15) return -1; |
2438 | | |
2439 | | /* Set response bit and error code; copy OPCODE and RD fields from |
2440 | | * question; copy RA and AA if set by caller. */ |
2441 | 0 | flags = req->base.flags; |
2442 | 0 | flags |= (_QR_MASK | err); |
2443 | |
|
2444 | 0 | dnslabel_table_init(&table); |
2445 | 0 | APPEND16(req->trans_id); |
2446 | 0 | APPEND16(flags); |
2447 | 0 | APPEND16(req->base.nquestions); |
2448 | 0 | APPEND16(req->n_answer); |
2449 | 0 | APPEND16(req->n_authority); |
2450 | 0 | APPEND16(req->n_additional); |
2451 | | |
2452 | | /* Add questions. */ |
2453 | 0 | for (i=0; i < req->base.nquestions; ++i) { |
2454 | 0 | const char *s = req->base.questions[i]->name; |
2455 | 0 | j = dnsname_to_labels(buf, buf_len, j, s, strlen(s), &table); |
2456 | 0 | if (j < 0) { |
2457 | 0 | dnslabel_clear(&table); |
2458 | 0 | return (int) j; |
2459 | 0 | } |
2460 | 0 | APPEND16(req->base.questions[i]->type); |
2461 | 0 | APPEND16(req->base.questions[i]->dns_question_class); |
2462 | 0 | } |
2463 | | |
2464 | | /* Add answer, authority, and additional sections. */ |
2465 | 0 | for (i=0; i<3; ++i) { |
2466 | 0 | struct server_reply_item *item; |
2467 | 0 | if (i==0) |
2468 | 0 | item = req->answer; |
2469 | 0 | else if (i==1) |
2470 | 0 | item = req->authority; |
2471 | 0 | else |
2472 | 0 | item = req->additional; |
2473 | 0 | while (item) { |
2474 | 0 | r = dnsname_to_labels(buf, buf_len, j, item->name, strlen(item->name), &table); |
2475 | 0 | if (r < 0) |
2476 | 0 | goto overflow; |
2477 | 0 | j = r; |
2478 | |
|
2479 | 0 | APPEND16(item->type); |
2480 | 0 | APPEND16(item->dns_question_class); |
2481 | 0 | APPEND32(item->ttl); |
2482 | 0 | if (item->is_name) { |
2483 | 0 | off_t len_idx = j, name_start; |
2484 | 0 | j += 2; |
2485 | 0 | name_start = j; |
2486 | 0 | r = dnsname_to_labels(buf, buf_len, j, item->data, strlen(item->data), &table); |
2487 | 0 | if (r < 0) |
2488 | 0 | goto overflow; |
2489 | 0 | j = r; |
2490 | 0 | t_ = htons( (short) (j-name_start) ); |
2491 | 0 | memcpy(buf+len_idx, &t_, 2); |
2492 | 0 | } else { |
2493 | 0 | APPEND16(item->datalen); |
2494 | 0 | if (j+item->datalen > (off_t)buf_len) |
2495 | 0 | goto overflow; |
2496 | 0 | if (item->data) { |
2497 | 0 | memcpy(buf+j, item->data, item->datalen); |
2498 | 0 | j += item->datalen; |
2499 | 0 | } else { |
2500 | 0 | EVUTIL_ASSERT(item->datalen == 0); |
2501 | 0 | } |
2502 | 0 | } |
2503 | 0 | item = item->next; |
2504 | 0 | } |
2505 | 0 | } |
2506 | | |
2507 | 0 | if (j > req->max_udp_reply_size && !req->client) { |
2508 | 0 | overflow: |
2509 | 0 | j = req->max_udp_reply_size; |
2510 | 0 | buf[2] |= 0x02; /* set the truncated bit. */ |
2511 | 0 | } |
2512 | |
|
2513 | 0 | req->response_len = j; |
2514 | |
|
2515 | 0 | if (!(req->response = mm_malloc(req->response_len))) { |
2516 | 0 | server_request_free_answers(req); |
2517 | 0 | dnslabel_clear(&table); |
2518 | 0 | return (-1); |
2519 | 0 | } |
2520 | 0 | memcpy(req->response, buf, req->response_len); |
2521 | 0 | server_request_free_answers(req); |
2522 | 0 | dnslabel_clear(&table); |
2523 | 0 | return (0); |
2524 | 0 | } |
2525 | | |
2526 | | /* exported function */ |
2527 | | int |
2528 | | evdns_server_request_respond(struct evdns_server_request *req_, int err) |
2529 | 0 | { |
2530 | 0 | struct server_request *req = TO_SERVER_REQUEST(req_); |
2531 | 0 | struct evdns_server_port *port = req->port; |
2532 | 0 | int r = -1; |
2533 | |
|
2534 | 0 | EVDNS_LOCK(port); |
2535 | 0 | if (!req->response) { |
2536 | 0 | if ((r = evdns_server_request_format_response(req, err))<0) |
2537 | 0 | goto done; |
2538 | 0 | } |
2539 | | |
2540 | 0 | r = server_send_response(port, req); |
2541 | 0 | if (r < 0 && req->client) { |
2542 | 0 | int sock_err = evutil_socket_geterror(port->socket); |
2543 | 0 | if (EVUTIL_ERR_RW_RETRIABLE(sock_err)) |
2544 | 0 | goto done; |
2545 | | |
2546 | 0 | if (port->pending_replies) { |
2547 | 0 | req->prev_pending = port->pending_replies->prev_pending; |
2548 | 0 | req->next_pending = port->pending_replies; |
2549 | 0 | req->prev_pending->next_pending = |
2550 | 0 | req->next_pending->prev_pending = req; |
2551 | 0 | } else { |
2552 | 0 | req->prev_pending = req->next_pending = req; |
2553 | 0 | port->pending_replies = req; |
2554 | 0 | port->choked = 1; |
2555 | |
|
2556 | 0 | (void) event_del(&port->event); |
2557 | 0 | event_assign(&port->event, port->event_base, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV_PERSIST, server_port_ready_callback, port); |
2558 | |
|
2559 | 0 | if (event_add(&port->event, NULL) < 0) { |
2560 | 0 | log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server"); |
2561 | 0 | } |
2562 | |
|
2563 | 0 | } |
2564 | |
|
2565 | 0 | r = 1; |
2566 | 0 | goto done; |
2567 | 0 | } |
2568 | 0 | if (server_request_free(req)) { |
2569 | 0 | r = 0; |
2570 | 0 | goto done; |
2571 | 0 | } |
2572 | | |
2573 | 0 | if (port->pending_replies) |
2574 | 0 | server_port_flush(port); |
2575 | |
|
2576 | 0 | r = 0; |
2577 | 0 | done: |
2578 | 0 | EVDNS_UNLOCK(port); |
2579 | 0 | return r; |
2580 | 0 | } |
2581 | | |
2582 | | /* Free all storage held by RRs in req. */ |
2583 | | static void |
2584 | | server_request_free_answers(struct server_request *req) |
2585 | 0 | { |
2586 | 0 | struct server_reply_item *victim, *next, **list; |
2587 | 0 | int i; |
2588 | 0 | for (i = 0; i < 3; ++i) { |
2589 | 0 | if (i==0) |
2590 | 0 | list = &req->answer; |
2591 | 0 | else if (i==1) |
2592 | 0 | list = &req->authority; |
2593 | 0 | else |
2594 | 0 | list = &req->additional; |
2595 | |
|
2596 | 0 | victim = *list; |
2597 | 0 | while (victim) { |
2598 | 0 | next = victim->next; |
2599 | 0 | mm_free(victim->name); |
2600 | 0 | victim->name = NULL; |
2601 | 0 | if (victim->data) { |
2602 | 0 | mm_free(victim->data); |
2603 | 0 | victim->data = NULL; |
2604 | 0 | } |
2605 | 0 | mm_free(victim); |
2606 | 0 | victim = next; |
2607 | 0 | } |
2608 | 0 | *list = NULL; |
2609 | 0 | } |
2610 | 0 | } |
2611 | | |
2612 | | /* Free all storage held by req, and remove links to it. */ |
2613 | | /* return true iff we just wound up freeing the server_port. */ |
2614 | | static int |
2615 | | server_request_free(struct server_request *req) |
2616 | 0 | { |
2617 | 0 | int i, rc=1, lock=0; |
2618 | 0 | if (req->base.questions) { |
2619 | 0 | for (i = 0; i < req->base.nquestions; ++i) { |
2620 | 0 | mm_free(req->base.questions[i]); |
2621 | 0 | req->base.questions[i] = NULL; |
2622 | 0 | } |
2623 | 0 | mm_free(req->base.questions); |
2624 | 0 | req->base.questions = NULL; |
2625 | 0 | } |
2626 | |
|
2627 | 0 | if (req->port) { |
2628 | 0 | EVDNS_LOCK(req->port); |
2629 | 0 | lock=1; |
2630 | 0 | if (req->port->pending_replies == req) { |
2631 | 0 | if (req->next_pending && req->next_pending != req) |
2632 | 0 | req->port->pending_replies = req->next_pending; |
2633 | 0 | else |
2634 | 0 | req->port->pending_replies = NULL; |
2635 | 0 | } |
2636 | 0 | rc = --req->port->refcnt; |
2637 | 0 | } |
2638 | |
|
2639 | 0 | if (req->response) { |
2640 | 0 | mm_free(req->response); |
2641 | 0 | req->response = NULL; |
2642 | 0 | } |
2643 | |
|
2644 | 0 | server_request_free_answers(req); |
2645 | |
|
2646 | 0 | if (req->next_pending && req->next_pending != req) { |
2647 | 0 | req->next_pending->prev_pending = req->prev_pending; |
2648 | 0 | req->prev_pending->next_pending = req->next_pending; |
2649 | 0 | } |
2650 | |
|
2651 | 0 | if (rc == 0) { |
2652 | 0 | EVDNS_UNLOCK(req->port); /* ????? nickm */ |
2653 | 0 | server_port_free(req->port); |
2654 | 0 | mm_free(req); |
2655 | 0 | return (1); |
2656 | 0 | } |
2657 | 0 | if (lock) |
2658 | 0 | EVDNS_UNLOCK(req->port); |
2659 | 0 | mm_free(req); |
2660 | 0 | return (0); |
2661 | 0 | } |
2662 | | |
2663 | | /* Free all storage held by an evdns_server_port. Only called when */ |
2664 | | static void |
2665 | | server_port_free(struct evdns_server_port *port) |
2666 | 0 | { |
2667 | 0 | EVUTIL_ASSERT(port); |
2668 | 0 | EVUTIL_ASSERT(!port->refcnt); |
2669 | 0 | EVUTIL_ASSERT(!port->pending_replies); |
2670 | 0 | if (port->socket > 0) { |
2671 | 0 | evutil_closesocket(port->socket); |
2672 | 0 | port->socket = -1; |
2673 | 0 | } |
2674 | | |
2675 | | /* if tcp server */ |
2676 | 0 | if (port->listener) { |
2677 | 0 | evconnlistener_free(port->listener); |
2678 | 0 | } else { |
2679 | 0 | (void) event_del(&port->event); |
2680 | 0 | event_debug_unassign(&port->event); |
2681 | 0 | } |
2682 | |
|
2683 | 0 | EVTHREAD_FREE_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); |
2684 | 0 | mm_free(port); |
2685 | 0 | } |
2686 | | |
2687 | | /* exported function */ |
2688 | | int |
2689 | | evdns_server_request_drop(struct evdns_server_request *req_) |
2690 | 0 | { |
2691 | 0 | struct server_request *req = TO_SERVER_REQUEST(req_); |
2692 | 0 | server_request_free(req); |
2693 | 0 | return 0; |
2694 | 0 | } |
2695 | | |
2696 | | /* exported function */ |
2697 | | int |
2698 | | evdns_server_request_get_requesting_addr(struct evdns_server_request *req_, struct sockaddr *sa, int addr_len) |
2699 | 0 | { |
2700 | 0 | struct server_request *req = TO_SERVER_REQUEST(req_); |
2701 | 0 | if (addr_len < (int)req->addrlen) |
2702 | 0 | return -1; |
2703 | 0 | memcpy(sa, &(req->addr), req->addrlen); |
2704 | 0 | return req->addrlen; |
2705 | 0 | } |
2706 | | |
2707 | | static void |
2708 | | retransmit_all_tcp_requests_for(struct nameserver *server) |
2709 | 0 | { |
2710 | 0 | int i = 0; |
2711 | 0 | for (i = 0; i < server->base->n_req_heads; ++i) { |
2712 | 0 | struct request *started_at = server->base->req_heads[i]; |
2713 | 0 | struct request *req = started_at; |
2714 | 0 | if (!req) |
2715 | 0 | continue; |
2716 | | |
2717 | 0 | do { |
2718 | 0 | if (req->ns == server && (req->handle->tcp_flags & DNS_QUERY_USEVC)) { |
2719 | 0 | if (req->tx_count >= req->base->global_max_retransmits) { |
2720 | 0 | log(EVDNS_LOG_DEBUG, "Giving up on request %p; tx_count==%d", |
2721 | 0 | (void *)req, req->tx_count); |
2722 | 0 | reply_schedule_callback(req, 0, DNS_ERR_TIMEOUT, NULL); |
2723 | 0 | request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); |
2724 | 0 | } else { |
2725 | 0 | (void) evtimer_del(&req->timeout_event); |
2726 | 0 | evdns_request_transmit(req); |
2727 | 0 | } |
2728 | 0 | } |
2729 | 0 | req = req->next; |
2730 | 0 | } while (req != started_at); |
2731 | 0 | } |
2732 | 0 | } |
2733 | | |
2734 | | /* this is a libevent callback function which is called when a request */ |
2735 | | /* has timed out. */ |
2736 | | static void |
2737 | 0 | evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) { |
2738 | 0 | struct request *const req = (struct request *) arg; |
2739 | 0 | struct evdns_base *base = req->base; |
2740 | |
|
2741 | 0 | (void) fd; |
2742 | 0 | (void) events; |
2743 | |
|
2744 | 0 | log(EVDNS_LOG_DEBUG, "Request %p timed out", arg); |
2745 | 0 | EVDNS_LOCK(base); |
2746 | |
|
2747 | 0 | if (req->tx_count >= req->base->global_max_retransmits) { |
2748 | 0 | struct nameserver *ns = req->ns; |
2749 | | /* this request has failed */ |
2750 | 0 | log(EVDNS_LOG_DEBUG, "Giving up on request %p; tx_count==%d", |
2751 | 0 | arg, req->tx_count); |
2752 | 0 | reply_schedule_callback(req, 0, DNS_ERR_TIMEOUT, NULL); |
2753 | |
|
2754 | 0 | request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); |
2755 | 0 | nameserver_failed(ns, "request timed out.", 0); |
2756 | 0 | } else { |
2757 | | /* if request is using tcp connection, so tear connection */ |
2758 | 0 | if (req->handle->tcp_flags & DNS_QUERY_USEVC) { |
2759 | 0 | disconnect_and_free_connection(req->ns->connection); |
2760 | 0 | req->ns->connection = NULL; |
2761 | | |
2762 | | /* client can have the only connection to DNS server */ |
2763 | 0 | retransmit_all_tcp_requests_for(req->ns); |
2764 | 0 | } else { |
2765 | | /* retransmit it */ |
2766 | 0 | log(EVDNS_LOG_DEBUG, "Retransmitting request %p; tx_count==%d by udp", arg, req->tx_count); |
2767 | 0 | (void) evtimer_del(&req->timeout_event); |
2768 | 0 | request_swap_ns(req, nameserver_pick(base)); |
2769 | 0 | evdns_request_transmit(req); |
2770 | |
|
2771 | 0 | req->ns->timedout++; |
2772 | 0 | if (req->ns->timedout > req->base->global_max_nameserver_timeout) { |
2773 | 0 | req->ns->timedout = 0; |
2774 | 0 | nameserver_failed(req->ns, "request timed out.", 0); |
2775 | 0 | } |
2776 | 0 | } |
2777 | 0 | } |
2778 | |
|
2779 | 0 | EVDNS_UNLOCK(base); |
2780 | 0 | } |
2781 | | |
2782 | | /* try to send a request to a given server. */ |
2783 | | /* */ |
2784 | | /* return: */ |
2785 | | /* 0 ok */ |
2786 | | /* 1 temporary failure */ |
2787 | | /* 2 other failure */ |
2788 | | static int |
2789 | 0 | evdns_request_transmit_to(struct request *req, struct nameserver *server) { |
2790 | 0 | int r; |
2791 | 0 | ASSERT_LOCKED(req->base); |
2792 | 0 | ASSERT_VALID_REQUEST(req); |
2793 | |
|
2794 | 0 | if (server->requests_inflight == 1 && |
2795 | 0 | req->base->disable_when_inactive && |
2796 | 0 | event_add(&server->event, NULL) < 0) { |
2797 | 0 | return 1; |
2798 | 0 | } |
2799 | | |
2800 | 0 | r = sendto(server->socket, (void*)req->request, req->request_len, 0, |
2801 | 0 | (struct sockaddr *)&server->address, server->addrlen); |
2802 | 0 | if (r < 0) { |
2803 | 0 | int err = evutil_socket_geterror(server->socket); |
2804 | 0 | if (EVUTIL_ERR_RW_RETRIABLE(err)) |
2805 | 0 | return 1; |
2806 | 0 | nameserver_failed(req->ns, evutil_socket_error_to_string(err), err); |
2807 | 0 | return 2; |
2808 | 0 | } else if (r != (int)req->request_len) { |
2809 | 0 | return 1; /* short write */ |
2810 | 0 | } else { |
2811 | 0 | return 0; |
2812 | 0 | } |
2813 | 0 | } |
2814 | | |
2815 | | /* try to connect to a given server. */ |
2816 | | /* */ |
2817 | | /* return: */ |
2818 | | /* 0 ok */ |
2819 | | /* 1 temporary failure */ |
2820 | | /* 2 other failure */ |
2821 | | static int |
2822 | | evdns_tcp_connect_if_disconnected(struct nameserver *server) |
2823 | 0 | { |
2824 | 0 | struct tcp_connection *conn = server->connection; |
2825 | 0 | struct timeval *timeout = &server->base->global_tcp_idle_timeout; |
2826 | 0 | if (conn && conn->state != TS_DISCONNECTED && conn->bev != NULL) |
2827 | 0 | return 0; |
2828 | | |
2829 | 0 | disconnect_and_free_connection(conn); |
2830 | 0 | conn = new_tcp_connection(bufferevent_socket_new(server->base->event_base, -1, BEV_OPT_CLOSE_ON_FREE)); |
2831 | 0 | if (!conn) |
2832 | 0 | return 2; |
2833 | 0 | server->connection = conn; |
2834 | |
|
2835 | 0 | if (bufferevent_set_timeouts(conn->bev, timeout, timeout)) |
2836 | 0 | return 1; |
2837 | | |
2838 | 0 | EVUTIL_ASSERT(conn->state == TS_DISCONNECTED); |
2839 | 0 | if (bufferevent_socket_connect(conn->bev, (struct sockaddr *)&server->address, server->addrlen)) |
2840 | 0 | return 1; |
2841 | | |
2842 | 0 | conn->state = TS_CONNECTING; |
2843 | 0 | log(EVDNS_LOG_DEBUG, "New tcp connection %p created", (void *)conn); |
2844 | 0 | return 0; |
2845 | 0 | } |
2846 | | |
2847 | | static void |
2848 | | client_tcp_event_cb(struct bufferevent *bev, short events, void *ctx); |
2849 | | |
2850 | | |
2851 | | static void |
2852 | | client_tcp_read_packet_cb(struct bufferevent *bev, void *ctx) |
2853 | 0 | { |
2854 | 0 | u8 *msg = NULL; |
2855 | 0 | int msg_len = 0; |
2856 | 0 | struct nameserver *server = (struct nameserver*)ctx; |
2857 | 0 | struct tcp_connection *conn = server->connection; |
2858 | 0 | EVUTIL_ASSERT(server && bev); |
2859 | 0 | EVDNS_LOCK(server->base); |
2860 | |
|
2861 | 0 | while (1) { |
2862 | 0 | if (tcp_read_message(conn, &msg, &msg_len)) { |
2863 | 0 | disconnect_and_free_connection(server->connection); |
2864 | 0 | server->connection = NULL; |
2865 | 0 | EVDNS_UNLOCK(server->base); |
2866 | 0 | return; |
2867 | 0 | } |
2868 | | |
2869 | | /* Only part of the message was received. */ |
2870 | 0 | if (!msg) |
2871 | 0 | break; |
2872 | | |
2873 | 0 | reply_parse(server->base, msg, msg_len); |
2874 | 0 | mm_free(msg); |
2875 | 0 | msg = NULL; |
2876 | 0 | conn->awaiting_packet_size = 0; |
2877 | 0 | } |
2878 | | |
2879 | 0 | bufferevent_setwatermark(bev, EV_READ, |
2880 | 0 | conn->awaiting_packet_size ? conn->awaiting_packet_size : sizeof(ev_uint16_t), 0); |
2881 | 0 | bufferevent_setcb(bev, client_tcp_read_packet_cb, NULL, client_tcp_event_cb, ctx); |
2882 | 0 | EVDNS_UNLOCK(server->base); |
2883 | 0 | } |
2884 | | |
2885 | | static void |
2886 | 0 | client_tcp_event_cb(struct bufferevent *bev, short events, void *ctx) { |
2887 | 0 | struct nameserver *server = (struct nameserver*)ctx; |
2888 | 0 | struct tcp_connection *conn = server->connection; |
2889 | 0 | EVUTIL_ASSERT(server); |
2890 | 0 | EVDNS_LOCK(server->base); |
2891 | 0 | EVUTIL_ASSERT(conn && conn->bev == bev && bev); |
2892 | |
|
2893 | 0 | log(EVDNS_LOG_DEBUG, "Event %d on connection %p", events, (void *)conn); |
2894 | |
|
2895 | 0 | if (events & (BEV_EVENT_TIMEOUT)) { |
2896 | 0 | disconnect_and_free_connection(server->connection); |
2897 | 0 | server->connection = NULL; |
2898 | 0 | } else if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { |
2899 | 0 | disconnect_and_free_connection(server->connection); |
2900 | 0 | server->connection = NULL; |
2901 | 0 | } else if (events & BEV_EVENT_CONNECTED) { |
2902 | 0 | EVUTIL_ASSERT (conn->state == TS_CONNECTING); |
2903 | 0 | conn->state = TS_CONNECTED; |
2904 | 0 | evutil_make_socket_nonblocking(bufferevent_getfd(bev)); |
2905 | 0 | bufferevent_setcb(bev, client_tcp_read_packet_cb, NULL, client_tcp_event_cb, server); |
2906 | 0 | bufferevent_setwatermark(bev, EV_READ, sizeof(ev_uint16_t), 0); |
2907 | 0 | } |
2908 | 0 | EVDNS_UNLOCK(server->base); |
2909 | 0 | } |
2910 | | |
2911 | | /* try to send a request to a given server. */ |
2912 | | /* */ |
2913 | | /* return: */ |
2914 | | /* 0 ok */ |
2915 | | /* 1 temporary failure */ |
2916 | | /* 2 other failure */ |
2917 | | static int |
2918 | 0 | evdns_request_transmit_through_tcp(struct request *req, struct nameserver *server) { |
2919 | 0 | uint16_t packet_size; |
2920 | 0 | struct tcp_connection *conn = NULL; |
2921 | 0 | int r; |
2922 | 0 | ASSERT_LOCKED(req->base); |
2923 | 0 | ASSERT_VALID_REQUEST(req); |
2924 | |
|
2925 | 0 | if ((r = evdns_tcp_connect_if_disconnected(server))) |
2926 | 0 | return r; |
2927 | | |
2928 | 0 | conn = server->connection; |
2929 | 0 | bufferevent_setcb(conn->bev, client_tcp_read_packet_cb, NULL, client_tcp_event_cb, server); |
2930 | |
|
2931 | 0 | log(EVDNS_LOG_DEBUG, "Sending request %p via tcp connection %p", (void *)req, (void *)conn); |
2932 | 0 | packet_size = htons(req->request_len); |
2933 | 0 | if (bufferevent_write(conn->bev, &packet_size, sizeof(packet_size)) ) |
2934 | 0 | goto fail; |
2935 | 0 | if (bufferevent_write(conn->bev, (void*)req->request, req->request_len) ) |
2936 | 0 | goto fail; |
2937 | 0 | if (bufferevent_enable(conn->bev, EV_READ)) |
2938 | 0 | goto fail; |
2939 | 0 | if (evtimer_add(&req->timeout_event, &req->base->global_timeout) < 0) |
2940 | 0 | goto fail; |
2941 | | |
2942 | 0 | return 0; |
2943 | 0 | fail: |
2944 | 0 | log(EVDNS_LOG_WARN, "Failed to send request %p via tcp connection %p", (void *)req, (void *)conn); |
2945 | 0 | disconnect_and_free_connection(server->connection); |
2946 | 0 | server->connection = NULL; |
2947 | 0 | return 2; |
2948 | 0 | } |
2949 | | |
2950 | | /* try to send a request, updating the fields of the request */ |
2951 | | /* as needed */ |
2952 | | /* */ |
2953 | | /* return: */ |
2954 | | /* 0 ok */ |
2955 | | /* 1 failed */ |
2956 | | static int |
2957 | 0 | evdns_request_transmit(struct request *req) { |
2958 | 0 | int retcode = 0, r; |
2959 | |
|
2960 | 0 | ASSERT_LOCKED(req->base); |
2961 | 0 | ASSERT_VALID_REQUEST(req); |
2962 | | /* if we fail to send this packet then this flag marks it */ |
2963 | | /* for evdns_transmit */ |
2964 | 0 | req->transmit_me = 1; |
2965 | 0 | EVUTIL_ASSERT(req->trans_id != 0xffff); |
2966 | |
|
2967 | 0 | if (!req->ns) |
2968 | 0 | { |
2969 | | /* unable to transmit request if no nameservers */ |
2970 | 0 | return 1; |
2971 | 0 | } |
2972 | | |
2973 | 0 | if (req->ns->choked) { |
2974 | | /* don't bother trying to write to a socket */ |
2975 | | /* which we have had EAGAIN from */ |
2976 | 0 | return 1; |
2977 | 0 | } |
2978 | | |
2979 | 0 | if (req->handle->tcp_flags & DNS_QUERY_USEVC) { |
2980 | 0 | r = evdns_request_transmit_through_tcp(req, req->ns); |
2981 | | /* |
2982 | | If connection didn't initiated now, so report about temporary problems. |
2983 | | We don't mark name server as chocked so udp packets possibly have no |
2984 | | problems during transmit. Simply we will retry attempt later */ |
2985 | 0 | if (r == 1) { |
2986 | 0 | return r; |
2987 | 0 | } |
2988 | 0 | } else { |
2989 | 0 | r = evdns_request_transmit_to(req, req->ns); |
2990 | 0 | } |
2991 | 0 | switch (r) { |
2992 | 0 | case 1: |
2993 | | /* temp failure */ |
2994 | 0 | req->ns->choked = 1; |
2995 | 0 | nameserver_write_waiting(req->ns, 1); |
2996 | 0 | return 1; |
2997 | 0 | case 2: |
2998 | | /* failed to transmit the request entirely. we can fallthrough since |
2999 | | * we'll set a timeout, which will time out, and make us retransmit the |
3000 | | * request anyway. */ |
3001 | 0 | retcode = 1; |
3002 | 0 | EVUTIL_FALLTHROUGH; |
3003 | 0 | default: |
3004 | | /* all ok */ |
3005 | 0 | log(EVDNS_LOG_DEBUG, |
3006 | 0 | "Setting timeout for request %p, sent to nameserver %p", (void *)req, (void *)req->ns); |
3007 | 0 | if (evtimer_add(&req->timeout_event, &req->base->global_timeout) < 0) { |
3008 | 0 | log(EVDNS_LOG_WARN, |
3009 | 0 | "Error from libevent when adding timer for request %p", |
3010 | 0 | (void *)req); |
3011 | | /* ???? Do more? */ |
3012 | 0 | } |
3013 | 0 | req->tx_count++; |
3014 | 0 | req->transmit_me = 0; |
3015 | 0 | return retcode; |
3016 | 0 | } |
3017 | 0 | } |
3018 | | |
3019 | | static void |
3020 | 0 | nameserver_probe_callback(int result, char type, int count, int ttl, void *addresses, void *arg) { |
3021 | 0 | struct nameserver *const ns = (struct nameserver *) arg; |
3022 | 0 | (void) type; |
3023 | 0 | (void) count; |
3024 | 0 | (void) ttl; |
3025 | 0 | (void) addresses; |
3026 | |
|
3027 | 0 | if (result == DNS_ERR_CANCEL) { |
3028 | | /* We canceled this request because the nameserver came up |
3029 | | * for some other reason. Do not change our opinion about |
3030 | | * the nameserver. */ |
3031 | 0 | return; |
3032 | 0 | } |
3033 | | |
3034 | 0 | EVDNS_LOCK(ns->base); |
3035 | 0 | ns->probe_request = NULL; |
3036 | 0 | if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) { |
3037 | | /* this is a good reply */ |
3038 | 0 | nameserver_up(ns); |
3039 | 0 | } else { |
3040 | 0 | nameserver_probe_failed(ns); |
3041 | 0 | } |
3042 | 0 | EVDNS_UNLOCK(ns->base); |
3043 | 0 | } |
3044 | | |
3045 | | static void |
3046 | 0 | nameserver_send_probe(struct nameserver *const ns) { |
3047 | 0 | struct evdns_request *handle; |
3048 | 0 | struct request *req; |
3049 | 0 | char addrbuf[128]; |
3050 | | /* here we need to send a probe to a given nameserver */ |
3051 | | /* in the hope that it is up now. */ |
3052 | |
|
3053 | 0 | ASSERT_LOCKED(ns->base); |
3054 | 0 | log(EVDNS_LOG_DEBUG, "Sending probe to %s", |
3055 | 0 | evutil_format_sockaddr_port_( |
3056 | 0 | (struct sockaddr *)&ns->address, |
3057 | 0 | addrbuf, sizeof(addrbuf))); |
3058 | 0 | handle = mm_calloc(1, sizeof(*handle)); |
3059 | 0 | if (!handle) return; |
3060 | 0 | handle->user_callback = nameserver_probe_callback; |
3061 | 0 | handle->user_pointer = ns; |
3062 | 0 | req = request_new(ns->base, handle, TYPE_A, "google.com", DNS_QUERY_NO_SEARCH); |
3063 | 0 | if (!req) { |
3064 | 0 | mm_free(handle); |
3065 | 0 | return; |
3066 | 0 | } |
3067 | 0 | ns->probe_request = handle; |
3068 | | /* we force this into the inflight queue no matter what */ |
3069 | 0 | request_trans_id_set(req, transaction_id_pick(ns->base)); |
3070 | 0 | req->ns = ns; |
3071 | 0 | request_submit(req); |
3072 | 0 | } |
3073 | | |
3074 | | /* returns: */ |
3075 | | /* 0 didn't try to transmit anything */ |
3076 | | /* 1 tried to transmit something */ |
3077 | | static int |
3078 | 0 | evdns_transmit(struct evdns_base *base) { |
3079 | 0 | char did_try_to_transmit = 0; |
3080 | 0 | int i; |
3081 | |
|
3082 | 0 | ASSERT_LOCKED(base); |
3083 | 0 | for (i = 0; i < base->n_req_heads; ++i) { |
3084 | 0 | if (base->req_heads[i]) { |
3085 | 0 | struct request *const started_at = base->req_heads[i], *req = started_at; |
3086 | | /* first transmit all the requests which are currently waiting */ |
3087 | 0 | do { |
3088 | 0 | if (req->transmit_me) { |
3089 | 0 | did_try_to_transmit = 1; |
3090 | 0 | evdns_request_transmit(req); |
3091 | 0 | } |
3092 | |
|
3093 | 0 | req = req->next; |
3094 | 0 | } while (req != started_at); |
3095 | 0 | } |
3096 | 0 | } |
3097 | |
|
3098 | 0 | return did_try_to_transmit; |
3099 | 0 | } |
3100 | | |
3101 | | /* exported function */ |
3102 | | int |
3103 | | evdns_base_count_nameservers(struct evdns_base *base) |
3104 | 0 | { |
3105 | 0 | const struct nameserver *server; |
3106 | 0 | int n = 0; |
3107 | |
|
3108 | 0 | EVDNS_LOCK(base); |
3109 | 0 | server = base->server_head; |
3110 | 0 | if (!server) |
3111 | 0 | goto done; |
3112 | 0 | do { |
3113 | 0 | ++n; |
3114 | 0 | server = server->next; |
3115 | 0 | } while (server != base->server_head); |
3116 | 0 | done: |
3117 | 0 | EVDNS_UNLOCK(base); |
3118 | 0 | return n; |
3119 | 0 | } |
3120 | | |
3121 | | int |
3122 | | evdns_count_nameservers(void) |
3123 | 0 | { |
3124 | 0 | return evdns_base_count_nameservers(current_base); |
3125 | 0 | } |
3126 | | |
3127 | | /* exported function */ |
3128 | | int |
3129 | | evdns_base_clear_nameservers_and_suspend(struct evdns_base *base) |
3130 | 0 | { |
3131 | 0 | struct nameserver *server, *started_at; |
3132 | 0 | int i; |
3133 | |
|
3134 | 0 | EVDNS_LOCK(base); |
3135 | 0 | server = base->server_head; |
3136 | 0 | started_at = base->server_head; |
3137 | 0 | if (!server) { |
3138 | 0 | EVDNS_UNLOCK(base); |
3139 | 0 | return 0; |
3140 | 0 | } |
3141 | 0 | while (1) { |
3142 | 0 | struct nameserver *next = server->next; |
3143 | 0 | disconnect_and_free_connection(server->connection); |
3144 | 0 | server->connection = NULL; |
3145 | 0 | (void) event_del(&server->event); |
3146 | 0 | if (evtimer_initialized(&server->timeout_event)) |
3147 | 0 | (void) evtimer_del(&server->timeout_event); |
3148 | 0 | if (server->probe_request) { |
3149 | 0 | evdns_cancel_request(server->base, server->probe_request); |
3150 | 0 | server->probe_request = NULL; |
3151 | 0 | } |
3152 | 0 | if (server->socket >= 0) |
3153 | 0 | evutil_closesocket(server->socket); |
3154 | 0 | mm_free(server); |
3155 | 0 | if (next == started_at) |
3156 | 0 | break; |
3157 | 0 | server = next; |
3158 | 0 | } |
3159 | 0 | base->server_head = NULL; |
3160 | 0 | base->global_good_nameservers = 0; |
3161 | |
|
3162 | 0 | for (i = 0; i < base->n_req_heads; ++i) { |
3163 | 0 | struct request *req, *req_started_at; |
3164 | 0 | req = req_started_at = base->req_heads[i]; |
3165 | 0 | while (req) { |
3166 | 0 | struct request *next = req->next; |
3167 | 0 | req->tx_count = req->reissue_count = 0; |
3168 | 0 | req->ns = NULL; |
3169 | | /* ???? What to do about searches? */ |
3170 | 0 | (void) evtimer_del(&req->timeout_event); |
3171 | 0 | req->trans_id = 0; |
3172 | 0 | req->transmit_me = 0; |
3173 | |
|
3174 | 0 | base->global_requests_waiting++; |
3175 | 0 | evdns_request_insert(req, &base->req_waiting_head); |
3176 | | /* We want to insert these suspended elements at the front of |
3177 | | * the waiting queue, since they were pending before any of |
3178 | | * the waiting entries were added. This is a circular list, |
3179 | | * so we can just shift the start back by one.*/ |
3180 | 0 | base->req_waiting_head = base->req_waiting_head->prev; |
3181 | |
|
3182 | 0 | if (next == req_started_at) |
3183 | 0 | break; |
3184 | 0 | req = next; |
3185 | 0 | } |
3186 | 0 | base->req_heads[i] = NULL; |
3187 | 0 | } |
3188 | |
|
3189 | 0 | base->global_requests_inflight = 0; |
3190 | |
|
3191 | 0 | EVDNS_UNLOCK(base); |
3192 | 0 | return 0; |
3193 | 0 | } |
3194 | | |
3195 | | int |
3196 | | evdns_clear_nameservers_and_suspend(void) |
3197 | 0 | { |
3198 | 0 | return evdns_base_clear_nameservers_and_suspend(current_base); |
3199 | 0 | } |
3200 | | |
3201 | | |
3202 | | /* exported function */ |
3203 | | int |
3204 | | evdns_base_resume(struct evdns_base *base) |
3205 | 0 | { |
3206 | 0 | EVDNS_LOCK(base); |
3207 | 0 | evdns_requests_pump_waiting_queue(base); |
3208 | 0 | EVDNS_UNLOCK(base); |
3209 | |
|
3210 | 0 | return 0; |
3211 | 0 | } |
3212 | | |
3213 | | int |
3214 | | evdns_resume(void) |
3215 | 0 | { |
3216 | 0 | return evdns_base_resume(current_base); |
3217 | 0 | } |
3218 | | |
3219 | | static int |
3220 | 0 | evdns_nameserver_add_impl_(struct evdns_base *base, const struct sockaddr *address, int addrlen) { |
3221 | | /* first check to see if we already have this nameserver */ |
3222 | |
|
3223 | 0 | const struct nameserver *server = base->server_head, *const started_at = base->server_head; |
3224 | 0 | struct nameserver *ns; |
3225 | 0 | int err = 0; |
3226 | 0 | char addrbuf[128]; |
3227 | |
|
3228 | 0 | ASSERT_LOCKED(base); |
3229 | 0 | if (server) { |
3230 | 0 | do { |
3231 | 0 | if (!evutil_sockaddr_cmp((struct sockaddr*)&server->address, address, 1)) return 3; |
3232 | 0 | server = server->next; |
3233 | 0 | } while (server != started_at); |
3234 | 0 | } |
3235 | 0 | if (addrlen > (int)sizeof(ns->address)) { |
3236 | 0 | log(EVDNS_LOG_DEBUG, "Addrlen %d too long.", (int)addrlen); |
3237 | 0 | return 2; |
3238 | 0 | } |
3239 | | |
3240 | 0 | ns = (struct nameserver *) mm_malloc(sizeof(struct nameserver)); |
3241 | 0 | if (!ns) return -1; |
3242 | | |
3243 | 0 | memset(ns, 0, sizeof(struct nameserver)); |
3244 | 0 | ns->base = base; |
3245 | |
|
3246 | 0 | evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns); |
3247 | |
|
3248 | 0 | ns->socket = evutil_socket_(address->sa_family, |
3249 | 0 | SOCK_DGRAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0); |
3250 | 0 | if (ns->socket < 0) { err = 1; goto out1; } |
3251 | | |
3252 | 0 | if (base->global_outgoing_addrlen && |
3253 | 0 | !evutil_sockaddr_is_loopback_(address)) { |
3254 | 0 | if (bind(ns->socket, |
3255 | 0 | (struct sockaddr*)&base->global_outgoing_address, |
3256 | 0 | base->global_outgoing_addrlen) < 0) { |
3257 | 0 | log(EVDNS_LOG_WARN,"Couldn't bind to outgoing address"); |
3258 | 0 | err = 2; |
3259 | 0 | goto out2; |
3260 | 0 | } |
3261 | 0 | } |
3262 | | |
3263 | 0 | if (base->so_rcvbuf) { |
3264 | 0 | if (setsockopt(ns->socket, SOL_SOCKET, SO_RCVBUF, |
3265 | 0 | (void *)&base->so_rcvbuf, sizeof(base->so_rcvbuf))) { |
3266 | 0 | log(EVDNS_LOG_WARN, "Couldn't set SO_RCVBUF to %i", base->so_rcvbuf); |
3267 | 0 | err = -SO_RCVBUF; |
3268 | 0 | goto out2; |
3269 | 0 | } |
3270 | 0 | } |
3271 | 0 | if (base->so_sndbuf) { |
3272 | 0 | if (setsockopt(ns->socket, SOL_SOCKET, SO_SNDBUF, |
3273 | 0 | (void *)&base->so_sndbuf, sizeof(base->so_sndbuf))) { |
3274 | 0 | log(EVDNS_LOG_WARN, "Couldn't set SO_SNDBUF to %i", base->so_sndbuf); |
3275 | 0 | err = -SO_SNDBUF; |
3276 | 0 | goto out2; |
3277 | 0 | } |
3278 | 0 | } |
3279 | | |
3280 | 0 | memcpy(&ns->address, address, addrlen); |
3281 | 0 | ns->addrlen = addrlen; |
3282 | 0 | ns->state = 1; |
3283 | 0 | ns->connection = NULL; |
3284 | 0 | event_assign(&ns->event, ns->base->event_base, ns->socket, |
3285 | 0 | EV_READ | EV_PERSIST, nameserver_ready_callback, ns); |
3286 | 0 | if (!base->disable_when_inactive && event_add(&ns->event, NULL) < 0) { |
3287 | 0 | err = 2; |
3288 | 0 | goto out2; |
3289 | 0 | } |
3290 | | |
3291 | 0 | log(EVDNS_LOG_DEBUG, "Added nameserver %s as %p", |
3292 | 0 | evutil_format_sockaddr_port_(address, addrbuf, sizeof(addrbuf)), (void *)ns); |
3293 | | |
3294 | | /* insert this nameserver into the list of them */ |
3295 | 0 | if (!base->server_head) { |
3296 | 0 | ns->next = ns->prev = ns; |
3297 | 0 | base->server_head = ns; |
3298 | 0 | } else { |
3299 | 0 | ns->next = base->server_head->next; |
3300 | 0 | ns->prev = base->server_head; |
3301 | 0 | base->server_head->next = ns; |
3302 | 0 | ns->next->prev = ns; |
3303 | 0 | } |
3304 | |
|
3305 | 0 | base->global_good_nameservers++; |
3306 | |
|
3307 | 0 | return 0; |
3308 | | |
3309 | 0 | out2: |
3310 | 0 | evutil_closesocket(ns->socket); |
3311 | 0 | out1: |
3312 | 0 | event_debug_unassign(&ns->event); |
3313 | 0 | mm_free(ns); |
3314 | 0 | log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", |
3315 | 0 | evutil_format_sockaddr_port_(address, addrbuf, sizeof(addrbuf)), err); |
3316 | 0 | return err; |
3317 | 0 | } |
3318 | | |
3319 | | /* exported function */ |
3320 | | int |
3321 | | evdns_base_nameserver_add(struct evdns_base *base, unsigned long int address) |
3322 | 0 | { |
3323 | 0 | struct sockaddr_in sin; |
3324 | 0 | int res; |
3325 | 0 | memset(&sin, 0, sizeof(sin)); |
3326 | 0 | sin.sin_addr.s_addr = address; |
3327 | 0 | sin.sin_port = htons(53); |
3328 | 0 | sin.sin_family = AF_INET; |
3329 | | #ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
3330 | | sin.sin_len = sizeof(sin); |
3331 | | #endif |
3332 | 0 | EVDNS_LOCK(base); |
3333 | 0 | res = evdns_nameserver_add_impl_(base, (struct sockaddr*)&sin, sizeof(sin)); |
3334 | 0 | EVDNS_UNLOCK(base); |
3335 | 0 | return res; |
3336 | 0 | } |
3337 | | |
3338 | | int |
3339 | 0 | evdns_nameserver_add(unsigned long int address) { |
3340 | 0 | if (!current_base) |
3341 | 0 | current_base = evdns_base_new(NULL, 0); |
3342 | 0 | return evdns_base_nameserver_add(current_base, address); |
3343 | 0 | } |
3344 | | |
3345 | | static void |
3346 | | sockaddr_setport(struct sockaddr *sa, ev_uint16_t port) |
3347 | 0 | { |
3348 | 0 | if (sa->sa_family == AF_INET) { |
3349 | 0 | ((struct sockaddr_in *)sa)->sin_port = htons(port); |
3350 | 0 | } else if (sa->sa_family == AF_INET6) { |
3351 | 0 | ((struct sockaddr_in6 *)sa)->sin6_port = htons(port); |
3352 | 0 | } |
3353 | 0 | } |
3354 | | |
3355 | | static ev_uint16_t |
3356 | | sockaddr_getport(struct sockaddr *sa) |
3357 | 0 | { |
3358 | 0 | if (sa->sa_family == AF_INET) { |
3359 | 0 | return ntohs(((struct sockaddr_in *)sa)->sin_port); |
3360 | 0 | } else if (sa->sa_family == AF_INET6) { |
3361 | 0 | return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); |
3362 | 0 | } else { |
3363 | 0 | return 0; |
3364 | 0 | } |
3365 | 0 | } |
3366 | | |
3367 | | /* exported function */ |
3368 | | int |
3369 | 0 | evdns_base_nameserver_ip_add(struct evdns_base *base, const char *ip_as_string) { |
3370 | 0 | struct sockaddr_storage ss; |
3371 | 0 | struct sockaddr *sa; |
3372 | 0 | int len = sizeof(ss); |
3373 | 0 | int res; |
3374 | 0 | if (evutil_parse_sockaddr_port(ip_as_string, (struct sockaddr *)&ss, |
3375 | 0 | &len)) { |
3376 | 0 | log(EVDNS_LOG_WARN, "Unable to parse nameserver address %s", |
3377 | 0 | ip_as_string); |
3378 | 0 | return 4; |
3379 | 0 | } |
3380 | 0 | sa = (struct sockaddr *) &ss; |
3381 | 0 | if (sockaddr_getport(sa) == 0) |
3382 | 0 | sockaddr_setport(sa, 53); |
3383 | |
|
3384 | 0 | EVDNS_LOCK(base); |
3385 | 0 | res = evdns_nameserver_add_impl_(base, sa, len); |
3386 | 0 | EVDNS_UNLOCK(base); |
3387 | 0 | return res; |
3388 | 0 | } |
3389 | | |
3390 | | int |
3391 | 0 | evdns_nameserver_ip_add(const char *ip_as_string) { |
3392 | 0 | if (!current_base) |
3393 | 0 | current_base = evdns_base_new(NULL, 0); |
3394 | 0 | return evdns_base_nameserver_ip_add(current_base, ip_as_string); |
3395 | 0 | } |
3396 | | |
3397 | | int |
3398 | | evdns_base_nameserver_sockaddr_add(struct evdns_base *base, |
3399 | | const struct sockaddr *sa, ev_socklen_t len, unsigned flags) |
3400 | 0 | { |
3401 | 0 | int res; |
3402 | 0 | EVUTIL_ASSERT(base); |
3403 | 0 | EVDNS_LOCK(base); |
3404 | 0 | res = evdns_nameserver_add_impl_(base, sa, len); |
3405 | 0 | EVDNS_UNLOCK(base); |
3406 | 0 | return res; |
3407 | 0 | } |
3408 | | |
3409 | | int |
3410 | | evdns_base_get_nameserver_addr(struct evdns_base *base, int idx, |
3411 | | struct sockaddr *sa, ev_socklen_t len) |
3412 | 0 | { |
3413 | 0 | int result = -1; |
3414 | 0 | int i; |
3415 | 0 | struct nameserver *server; |
3416 | 0 | EVDNS_LOCK(base); |
3417 | 0 | server = base->server_head; |
3418 | 0 | for (i = 0; i < idx && server; ++i, server = server->next) { |
3419 | 0 | if (server->next == base->server_head) |
3420 | 0 | goto done; |
3421 | 0 | } |
3422 | 0 | if (! server) |
3423 | 0 | goto done; |
3424 | | |
3425 | 0 | if (server->addrlen > len) { |
3426 | 0 | result = (int) server->addrlen; |
3427 | 0 | goto done; |
3428 | 0 | } |
3429 | | |
3430 | 0 | memcpy(sa, &server->address, server->addrlen); |
3431 | 0 | result = (int) server->addrlen; |
3432 | 0 | done: |
3433 | 0 | EVDNS_UNLOCK(base); |
3434 | 0 | return result; |
3435 | 0 | } |
3436 | | |
3437 | | int |
3438 | | evdns_base_get_nameserver_fd(struct evdns_base *base, int idx) |
3439 | 0 | { |
3440 | 0 | int result = -1; |
3441 | 0 | int i; |
3442 | 0 | struct nameserver *server; |
3443 | 0 | EVDNS_LOCK(base); |
3444 | 0 | server = base->server_head; |
3445 | 0 | for (i = 0; i < idx && server; ++i, server = server->next) { |
3446 | 0 | if (server->next == base->server_head) |
3447 | 0 | goto done; |
3448 | 0 | } |
3449 | 0 | if (! server) |
3450 | 0 | goto done; |
3451 | 0 | result = server->socket; |
3452 | 0 | done: |
3453 | 0 | EVDNS_UNLOCK(base); |
3454 | 0 | return result; |
3455 | 0 | } |
3456 | | |
3457 | | |
3458 | | /* remove from the queue */ |
3459 | | static void |
3460 | | evdns_request_remove(struct request *req, struct request **head) |
3461 | 0 | { |
3462 | 0 | ASSERT_LOCKED(req->base); |
3463 | 0 | ASSERT_VALID_REQUEST(req); |
3464 | |
|
3465 | | #if 0 |
3466 | | { |
3467 | | struct request *ptr; |
3468 | | int found = 0; |
3469 | | EVUTIL_ASSERT(*head != NULL); |
3470 | | |
3471 | | ptr = *head; |
3472 | | do { |
3473 | | if (ptr == req) { |
3474 | | found = 1; |
3475 | | break; |
3476 | | } |
3477 | | ptr = ptr->next; |
3478 | | } while (ptr != *head); |
3479 | | EVUTIL_ASSERT(found); |
3480 | | |
3481 | | EVUTIL_ASSERT(req->next); |
3482 | | } |
3483 | | #endif |
3484 | |
|
3485 | 0 | if (req->next == req) { |
3486 | | /* only item in the list */ |
3487 | 0 | *head = NULL; |
3488 | 0 | } else { |
3489 | 0 | req->next->prev = req->prev; |
3490 | 0 | req->prev->next = req->next; |
3491 | 0 | if (*head == req) *head = req->next; |
3492 | 0 | } |
3493 | 0 | req->next = req->prev = NULL; |
3494 | 0 | } |
3495 | | |
3496 | | /* insert into the tail of the queue */ |
3497 | | static void |
3498 | 0 | evdns_request_insert(struct request *req, struct request **head) { |
3499 | 0 | ASSERT_LOCKED(req->base); |
3500 | 0 | ASSERT_VALID_REQUEST(req); |
3501 | 0 | if (!*head) { |
3502 | 0 | *head = req; |
3503 | 0 | req->next = req->prev = req; |
3504 | 0 | return; |
3505 | 0 | } |
3506 | | |
3507 | 0 | req->prev = (*head)->prev; |
3508 | 0 | req->prev->next = req; |
3509 | 0 | req->next = *head; |
3510 | 0 | (*head)->prev = req; |
3511 | 0 | } |
3512 | | |
3513 | | static int |
3514 | 0 | string_num_dots(const char *s) { |
3515 | 0 | int count = 0; |
3516 | 0 | while ((s = strchr(s, '.'))) { |
3517 | 0 | s++; |
3518 | 0 | count++; |
3519 | 0 | } |
3520 | 0 | return count; |
3521 | 0 | } |
3522 | | |
3523 | | static struct request * |
3524 | | request_new(struct evdns_base *base, struct evdns_request *handle, int type, |
3525 | 0 | const char *name, int flags) { |
3526 | |
|
3527 | 0 | const char issuing_now = |
3528 | 0 | (base->global_requests_inflight < base->global_max_requests_inflight) ? 1 : 0; |
3529 | |
|
3530 | 0 | const size_t name_len = strlen(name); |
3531 | 0 | const size_t request_max_len = evdns_request_len(base, name_len); |
3532 | 0 | const u16 trans_id = issuing_now ? transaction_id_pick(base) : 0xffff; |
3533 | | /* the request data is alloced in a single block with the header */ |
3534 | 0 | struct request *const req = |
3535 | 0 | mm_malloc(sizeof(struct request) + request_max_len); |
3536 | 0 | int rlen; |
3537 | 0 | char namebuf[256]; |
3538 | 0 | (void) flags; |
3539 | |
|
3540 | 0 | ASSERT_LOCKED(base); |
3541 | |
|
3542 | 0 | if (!req) return NULL; |
3543 | | |
3544 | 0 | if (name_len >= sizeof(namebuf)) { |
3545 | 0 | mm_free(req); |
3546 | 0 | return NULL; |
3547 | 0 | } |
3548 | | |
3549 | 0 | memset(req, 0, sizeof(struct request)); |
3550 | 0 | req->request_size = (u16)(sizeof(struct request) + request_max_len); |
3551 | 0 | req->base = base; |
3552 | |
|
3553 | 0 | evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req); |
3554 | |
|
3555 | 0 | if (base->global_randomize_case) { |
3556 | 0 | unsigned i; |
3557 | 0 | char randbits[(sizeof(namebuf)+7)/8]; |
3558 | 0 | strlcpy(namebuf, name, sizeof(namebuf)); |
3559 | 0 | evutil_secure_rng_get_bytes(randbits, (name_len+7)/8); |
3560 | 0 | for (i = 0; i < name_len; ++i) { |
3561 | 0 | if (EVUTIL_ISALPHA_(namebuf[i])) { |
3562 | 0 | if ((randbits[i >> 3] & (1<<(i & 7)))) |
3563 | 0 | namebuf[i] |= 0x20; |
3564 | 0 | else |
3565 | 0 | namebuf[i] &= ~0x20; |
3566 | 0 | } |
3567 | 0 | } |
3568 | 0 | name = namebuf; |
3569 | 0 | } |
3570 | | |
3571 | | /* request data lives just after the header */ |
3572 | 0 | req->request = ((u8 *) req) + sizeof(struct request); |
3573 | | /* denotes that the request data shouldn't be free()ed */ |
3574 | 0 | req->request_appended = 1; |
3575 | 0 | rlen = evdns_request_data_build(base, name, name_len, trans_id, |
3576 | 0 | type, CLASS_INET, req->request, request_max_len); |
3577 | 0 | if (rlen < 0) |
3578 | 0 | goto err1; |
3579 | | |
3580 | 0 | req->request_len = rlen; |
3581 | 0 | req->trans_id = trans_id; |
3582 | 0 | req->tx_count = 0; |
3583 | 0 | req->request_type = type; |
3584 | 0 | req->ns = issuing_now ? nameserver_pick(base) : NULL; |
3585 | 0 | req->next = req->prev = NULL; |
3586 | 0 | req->handle = handle; |
3587 | 0 | if (handle) { |
3588 | 0 | handle->current_req = req; |
3589 | 0 | handle->base = base; |
3590 | 0 | } |
3591 | |
|
3592 | 0 | if (flags & DNS_CNAME_CALLBACK) |
3593 | 0 | req->need_cname = 1; |
3594 | |
|
3595 | 0 | return req; |
3596 | 0 | err1: |
3597 | 0 | mm_free(req); |
3598 | 0 | return NULL; |
3599 | 0 | } |
3600 | | |
3601 | | static struct request * |
3602 | | request_clone(struct evdns_base *base, struct request* current) |
3603 | 0 | { |
3604 | 0 | const char issuing_now = |
3605 | 0 | (base->global_requests_inflight < base->global_max_requests_inflight) ? 1 : 0; |
3606 | 0 | const u16 trans_id = issuing_now ? transaction_id_pick(base) : 0xffff; |
3607 | | /* the request data is alloced in a single block with the header */ |
3608 | 0 | struct request *const req = mm_malloc(current->request_size); |
3609 | 0 | EVUTIL_ASSERT(current && base); |
3610 | 0 | ASSERT_LOCKED(base); |
3611 | |
|
3612 | 0 | if (!req) |
3613 | 0 | return NULL; |
3614 | 0 | memcpy(req, current, current->request_size); |
3615 | |
|
3616 | 0 | evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req); |
3617 | | |
3618 | | /* request data lives just after the header */ |
3619 | 0 | req->request = ((u8 *) req) + sizeof(struct request); |
3620 | | /* We need to replace transact id */ |
3621 | 0 | request_trans_id_set(req, trans_id); |
3622 | |
|
3623 | 0 | req->tx_count = 0; |
3624 | 0 | req->ns = issuing_now ? nameserver_pick(base) : NULL; |
3625 | 0 | req->next = req->prev = NULL; |
3626 | 0 | req->handle = NULL; |
3627 | 0 | log(EVDNS_LOG_DEBUG, "Clone new request TID %d from TID %d", req->trans_id, current->trans_id); |
3628 | |
|
3629 | 0 | return req; |
3630 | 0 | } |
3631 | | |
3632 | | static void |
3633 | 0 | request_submit(struct request *const req) { |
3634 | 0 | struct evdns_base *base = req->base; |
3635 | 0 | ASSERT_LOCKED(base); |
3636 | 0 | ASSERT_VALID_REQUEST(req); |
3637 | 0 | if (req->ns) { |
3638 | | /* if it has a nameserver assigned then this is going */ |
3639 | | /* straight into the inflight queue */ |
3640 | 0 | evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); |
3641 | |
|
3642 | 0 | base->global_requests_inflight++; |
3643 | 0 | req->ns->requests_inflight++; |
3644 | |
|
3645 | 0 | evdns_request_transmit(req); |
3646 | 0 | } else { |
3647 | 0 | evdns_request_insert(req, &base->req_waiting_head); |
3648 | 0 | base->global_requests_waiting++; |
3649 | 0 | } |
3650 | 0 | } |
3651 | | |
3652 | | /* exported function */ |
3653 | | void |
3654 | | evdns_cancel_request(struct evdns_base *base, struct evdns_request *handle) |
3655 | 0 | { |
3656 | 0 | struct request *req; |
3657 | |
|
3658 | 0 | if (!handle->current_req) |
3659 | 0 | return; |
3660 | | |
3661 | 0 | if (!base) { |
3662 | | /* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */ |
3663 | 0 | base = handle->base; |
3664 | 0 | if (!base) |
3665 | 0 | base = handle->current_req->base; |
3666 | 0 | } |
3667 | |
|
3668 | 0 | EVDNS_LOCK(base); |
3669 | 0 | if (handle->pending_cb) { |
3670 | 0 | EVDNS_UNLOCK(base); |
3671 | 0 | return; |
3672 | 0 | } |
3673 | | |
3674 | 0 | req = handle->current_req; |
3675 | 0 | ASSERT_VALID_REQUEST(req); |
3676 | |
|
3677 | 0 | reply_schedule_callback(req, 0, DNS_ERR_CANCEL, NULL); |
3678 | 0 | if (req->ns) { |
3679 | | /* remove from inflight queue */ |
3680 | 0 | request_finished(req, &REQ_HEAD(base, req->trans_id), 1); |
3681 | 0 | } else { |
3682 | | /* remove from global_waiting head */ |
3683 | 0 | request_finished(req, &base->req_waiting_head, 1); |
3684 | 0 | } |
3685 | 0 | EVDNS_UNLOCK(base); |
3686 | 0 | } |
3687 | | |
3688 | | /* exported function */ |
3689 | | struct evdns_request * |
3690 | | evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, |
3691 | 0 | evdns_callback_type callback, void *ptr) { |
3692 | 0 | struct evdns_request *handle; |
3693 | 0 | struct request *req; |
3694 | 0 | log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); |
3695 | 0 | handle = mm_calloc(1, sizeof(*handle)); |
3696 | 0 | if (handle == NULL) |
3697 | 0 | return NULL; |
3698 | 0 | handle->user_callback = callback; |
3699 | 0 | handle->user_pointer = ptr; |
3700 | 0 | EVDNS_LOCK(base); |
3701 | 0 | handle->tcp_flags = base->global_tcp_flags; |
3702 | 0 | handle->tcp_flags |= flags & (DNS_QUERY_USEVC | DNS_QUERY_IGNTC); |
3703 | 0 | if (flags & DNS_QUERY_NO_SEARCH) { |
3704 | 0 | req = |
3705 | 0 | request_new(base, handle, TYPE_A, name, flags); |
3706 | 0 | if (req) |
3707 | 0 | request_submit(req); |
3708 | 0 | } else { |
3709 | 0 | search_request_new(base, handle, TYPE_A, name, flags); |
3710 | 0 | } |
3711 | 0 | if (handle->current_req == NULL) { |
3712 | 0 | mm_free(handle); |
3713 | 0 | handle = NULL; |
3714 | 0 | } |
3715 | 0 | EVDNS_UNLOCK(base); |
3716 | 0 | return handle; |
3717 | 0 | } |
3718 | | |
3719 | | int evdns_resolve_ipv4(const char *name, int flags, |
3720 | | evdns_callback_type callback, void *ptr) |
3721 | 0 | { |
3722 | 0 | return evdns_base_resolve_ipv4(current_base, name, flags, callback, ptr) |
3723 | 0 | ? 0 : -1; |
3724 | 0 | } |
3725 | | |
3726 | | |
3727 | | /* exported function */ |
3728 | | struct evdns_request * |
3729 | | evdns_base_resolve_ipv6(struct evdns_base *base, |
3730 | | const char *name, int flags, |
3731 | | evdns_callback_type callback, void *ptr) |
3732 | 0 | { |
3733 | 0 | struct evdns_request *handle; |
3734 | 0 | struct request *req; |
3735 | 0 | log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); |
3736 | 0 | handle = mm_calloc(1, sizeof(*handle)); |
3737 | 0 | if (handle == NULL) |
3738 | 0 | return NULL; |
3739 | 0 | handle->user_callback = callback; |
3740 | 0 | handle->user_pointer = ptr; |
3741 | 0 | EVDNS_LOCK(base); |
3742 | 0 | handle->tcp_flags = base->global_tcp_flags; |
3743 | 0 | handle->tcp_flags |= flags & (DNS_QUERY_USEVC | DNS_QUERY_IGNTC); |
3744 | 0 | if (flags & DNS_QUERY_NO_SEARCH) { |
3745 | 0 | req = request_new(base, handle, TYPE_AAAA, name, flags); |
3746 | 0 | if (req) |
3747 | 0 | request_submit(req); |
3748 | 0 | } else { |
3749 | 0 | search_request_new(base, handle, TYPE_AAAA, name, flags); |
3750 | 0 | } |
3751 | 0 | if (handle->current_req == NULL) { |
3752 | 0 | mm_free(handle); |
3753 | 0 | handle = NULL; |
3754 | 0 | } |
3755 | 0 | EVDNS_UNLOCK(base); |
3756 | 0 | return handle; |
3757 | 0 | } |
3758 | | |
3759 | | int evdns_resolve_ipv6(const char *name, int flags, |
3760 | 0 | evdns_callback_type callback, void *ptr) { |
3761 | 0 | return evdns_base_resolve_ipv6(current_base, name, flags, callback, ptr) |
3762 | 0 | ? 0 : -1; |
3763 | 0 | } |
3764 | | |
3765 | | struct evdns_request * |
3766 | 0 | evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { |
3767 | 0 | char buf[32]; |
3768 | 0 | struct evdns_request *handle; |
3769 | 0 | struct request *req; |
3770 | 0 | u32 a; |
3771 | 0 | EVUTIL_ASSERT(in); |
3772 | 0 | a = ntohl(in->s_addr); |
3773 | 0 | evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", |
3774 | 0 | (int)(u8)((a )&0xff), |
3775 | 0 | (int)(u8)((a>>8 )&0xff), |
3776 | 0 | (int)(u8)((a>>16)&0xff), |
3777 | 0 | (int)(u8)((a>>24)&0xff)); |
3778 | 0 | handle = mm_calloc(1, sizeof(*handle)); |
3779 | 0 | if (handle == NULL) |
3780 | 0 | return NULL; |
3781 | 0 | handle->user_callback = callback; |
3782 | 0 | handle->user_pointer = ptr; |
3783 | 0 | log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); |
3784 | 0 | EVDNS_LOCK(base); |
3785 | 0 | handle->tcp_flags = base->global_tcp_flags; |
3786 | 0 | handle->tcp_flags |= flags & (DNS_QUERY_USEVC | DNS_QUERY_IGNTC); |
3787 | 0 | req = request_new(base, handle, TYPE_PTR, buf, flags); |
3788 | 0 | if (req) |
3789 | 0 | request_submit(req); |
3790 | 0 | if (handle->current_req == NULL) { |
3791 | 0 | mm_free(handle); |
3792 | 0 | handle = NULL; |
3793 | 0 | } |
3794 | 0 | EVDNS_UNLOCK(base); |
3795 | 0 | return (handle); |
3796 | 0 | } |
3797 | | |
3798 | 0 | int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { |
3799 | 0 | return evdns_base_resolve_reverse(current_base, in, flags, callback, ptr) |
3800 | 0 | ? 0 : -1; |
3801 | 0 | } |
3802 | | |
3803 | | struct evdns_request * |
3804 | 0 | evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { |
3805 | | /* 32 nybbles, 32 periods, "ip6.arpa", NUL. */ |
3806 | 0 | char buf[73]; |
3807 | 0 | char *cp; |
3808 | 0 | struct evdns_request *handle; |
3809 | 0 | struct request *req; |
3810 | 0 | int i; |
3811 | 0 | EVUTIL_ASSERT(in); |
3812 | 0 | cp = buf; |
3813 | 0 | for (i=15; i >= 0; --i) { |
3814 | 0 | u8 byte = in->s6_addr[i]; |
3815 | 0 | *cp++ = "0123456789abcdef"[byte & 0x0f]; |
3816 | 0 | *cp++ = '.'; |
3817 | 0 | *cp++ = "0123456789abcdef"[byte >> 4]; |
3818 | 0 | *cp++ = '.'; |
3819 | 0 | } |
3820 | 0 | EVUTIL_ASSERT(cp + strlen("ip6.arpa") < buf+sizeof(buf)); |
3821 | 0 | memcpy(cp, "ip6.arpa", strlen("ip6.arpa")+1); |
3822 | 0 | handle = mm_calloc(1, sizeof(*handle)); |
3823 | 0 | if (handle == NULL) |
3824 | 0 | return NULL; |
3825 | 0 | handle->user_callback = callback; |
3826 | 0 | handle->user_pointer = ptr; |
3827 | 0 | log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); |
3828 | 0 | EVDNS_LOCK(base); |
3829 | 0 | handle->tcp_flags = base->global_tcp_flags; |
3830 | 0 | handle->tcp_flags |= flags & (DNS_QUERY_USEVC | DNS_QUERY_IGNTC); |
3831 | 0 | req = request_new(base, handle, TYPE_PTR, buf, flags); |
3832 | 0 | if (req) |
3833 | 0 | request_submit(req); |
3834 | 0 | if (handle->current_req == NULL) { |
3835 | 0 | mm_free(handle); |
3836 | 0 | handle = NULL; |
3837 | 0 | } |
3838 | 0 | EVDNS_UNLOCK(base); |
3839 | 0 | return (handle); |
3840 | 0 | } |
3841 | | |
3842 | 0 | int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { |
3843 | 0 | return evdns_base_resolve_reverse_ipv6(current_base, in, flags, callback, ptr) |
3844 | 0 | ? 0 : -1; |
3845 | 0 | } |
3846 | | |
3847 | | /* ================================================================= */ |
3848 | | /* Search support */ |
3849 | | /* */ |
3850 | | /* the libc resolver has support for searching a number of domains */ |
3851 | | /* to find a name. If nothing else then it takes the single domain */ |
3852 | | /* from the gethostname() call. */ |
3853 | | /* */ |
3854 | | /* It can also be configured via the domain and search options in a */ |
3855 | | /* resolv.conf. */ |
3856 | | /* */ |
3857 | | /* The ndots option controls how many dots it takes for the resolver */ |
3858 | | /* to decide that a name is non-local and so try a raw lookup first. */ |
3859 | | |
3860 | | struct search_domain { |
3861 | | int len; |
3862 | | struct search_domain *next; |
3863 | | /* the text string is appended to this structure */ |
3864 | | }; |
3865 | | |
3866 | | struct search_state { |
3867 | | int refcount; |
3868 | | int ndots; |
3869 | | int num_domains; |
3870 | | struct search_domain *head; |
3871 | | }; |
3872 | | |
3873 | | static void |
3874 | 0 | search_state_decref(struct search_state *const state) { |
3875 | 0 | if (!state) return; |
3876 | 0 | state->refcount--; |
3877 | 0 | if (!state->refcount) { |
3878 | 0 | struct search_domain *next, *dom; |
3879 | 0 | for (dom = state->head; dom; dom = next) { |
3880 | 0 | next = dom->next; |
3881 | 0 | mm_free(dom); |
3882 | 0 | } |
3883 | 0 | mm_free(state); |
3884 | 0 | } |
3885 | 0 | } |
3886 | | |
3887 | | static struct search_state * |
3888 | 0 | search_state_new(void) { |
3889 | 0 | struct search_state *state = (struct search_state *) mm_malloc(sizeof(struct search_state)); |
3890 | 0 | if (!state) return NULL; |
3891 | 0 | memset(state, 0, sizeof(struct search_state)); |
3892 | 0 | state->refcount = 1; |
3893 | 0 | state->ndots = 1; |
3894 | |
|
3895 | 0 | return state; |
3896 | 0 | } |
3897 | | |
3898 | | static void |
3899 | 0 | search_postfix_clear(struct evdns_base *base) { |
3900 | 0 | search_state_decref(base->global_search_state); |
3901 | |
|
3902 | 0 | base->global_search_state = search_state_new(); |
3903 | 0 | } |
3904 | | |
3905 | | /* exported function */ |
3906 | | void |
3907 | | evdns_base_search_clear(struct evdns_base *base) |
3908 | 0 | { |
3909 | 0 | EVDNS_LOCK(base); |
3910 | 0 | search_postfix_clear(base); |
3911 | 0 | EVDNS_UNLOCK(base); |
3912 | 0 | } |
3913 | | |
3914 | | void |
3915 | 0 | evdns_search_clear(void) { |
3916 | 0 | evdns_base_search_clear(current_base); |
3917 | 0 | } |
3918 | | |
3919 | | static void |
3920 | 0 | search_postfix_add(struct evdns_base *base, const char *domain) { |
3921 | 0 | size_t domain_len; |
3922 | 0 | struct search_domain *sdomain; |
3923 | 0 | while (domain[0] == '.') domain++; |
3924 | 0 | domain_len = strlen(domain); |
3925 | |
|
3926 | 0 | ASSERT_LOCKED(base); |
3927 | 0 | if (!base->global_search_state) base->global_search_state = search_state_new(); |
3928 | 0 | if (!base->global_search_state) return; |
3929 | 0 | base->global_search_state->num_domains++; |
3930 | |
|
3931 | 0 | sdomain = (struct search_domain *) mm_malloc(sizeof(struct search_domain) + domain_len); |
3932 | 0 | if (!sdomain) return; |
3933 | 0 | memcpy( ((u8 *) sdomain) + sizeof(struct search_domain), domain, domain_len); |
3934 | 0 | sdomain->next = base->global_search_state->head; |
3935 | 0 | sdomain->len = (int) domain_len; |
3936 | |
|
3937 | 0 | base->global_search_state->head = sdomain; |
3938 | 0 | } |
3939 | | |
3940 | | /* reverse the order of members in the postfix list. This is needed because, */ |
3941 | | /* when parsing resolv.conf we push elements in the wrong order */ |
3942 | | static void |
3943 | 0 | search_reverse(struct evdns_base *base) { |
3944 | 0 | struct search_domain *cur, *prev = NULL, *next; |
3945 | 0 | ASSERT_LOCKED(base); |
3946 | 0 | cur = base->global_search_state->head; |
3947 | 0 | while (cur) { |
3948 | 0 | next = cur->next; |
3949 | 0 | cur->next = prev; |
3950 | 0 | prev = cur; |
3951 | 0 | cur = next; |
3952 | 0 | } |
3953 | |
|
3954 | 0 | base->global_search_state->head = prev; |
3955 | 0 | } |
3956 | | |
3957 | | /* exported function */ |
3958 | | void |
3959 | 0 | evdns_base_search_add(struct evdns_base *base, const char *domain) { |
3960 | 0 | EVDNS_LOCK(base); |
3961 | 0 | search_postfix_add(base, domain); |
3962 | 0 | EVDNS_UNLOCK(base); |
3963 | 0 | } |
3964 | | void |
3965 | 0 | evdns_search_add(const char *domain) { |
3966 | 0 | evdns_base_search_add(current_base, domain); |
3967 | 0 | } |
3968 | | |
3969 | | /* exported function */ |
3970 | | void |
3971 | 0 | evdns_base_search_ndots_set(struct evdns_base *base, const int ndots) { |
3972 | 0 | EVDNS_LOCK(base); |
3973 | 0 | if (!base->global_search_state) base->global_search_state = search_state_new(); |
3974 | 0 | if (base->global_search_state) |
3975 | 0 | base->global_search_state->ndots = ndots; |
3976 | 0 | EVDNS_UNLOCK(base); |
3977 | 0 | } |
3978 | | void |
3979 | 0 | evdns_search_ndots_set(const int ndots) { |
3980 | 0 | evdns_base_search_ndots_set(current_base, ndots); |
3981 | 0 | } |
3982 | | |
3983 | | static void |
3984 | 0 | search_set_from_hostname(struct evdns_base *base) { |
3985 | 0 | char hostname[EVDNS_NAME_MAX + 1], *domainname; |
3986 | |
|
3987 | 0 | ASSERT_LOCKED(base); |
3988 | 0 | search_postfix_clear(base); |
3989 | 0 | if (gethostname(hostname, sizeof(hostname))) return; |
3990 | 0 | domainname = strchr(hostname, '.'); |
3991 | 0 | if (!domainname) return; |
3992 | 0 | search_postfix_add(base, domainname); |
3993 | 0 | } |
3994 | | |
3995 | | /* warning: returns malloced string */ |
3996 | | static char * |
3997 | 0 | search_make_new(const struct search_state *const state, int n, const char *const base_name) { |
3998 | 0 | const size_t base_len = strlen(base_name); |
3999 | 0 | char need_to_append_dot; |
4000 | 0 | struct search_domain *dom; |
4001 | |
|
4002 | 0 | if (!base_len) return NULL; |
4003 | 0 | need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; |
4004 | |
|
4005 | 0 | for (dom = state->head; dom; dom = dom->next) { |
4006 | 0 | if (!n--) { |
4007 | | /* this is the postfix we want */ |
4008 | | /* the actual postfix string is kept at the end of the structure */ |
4009 | 0 | const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain); |
4010 | 0 | const int postfix_len = dom->len; |
4011 | 0 | char *const newname = (char *) mm_malloc(base_len + need_to_append_dot + postfix_len + 1); |
4012 | 0 | if (!newname) return NULL; |
4013 | 0 | memcpy(newname, base_name, base_len); |
4014 | 0 | if (need_to_append_dot) newname[base_len] = '.'; |
4015 | 0 | memcpy(newname + base_len + need_to_append_dot, postfix, postfix_len); |
4016 | 0 | newname[base_len + need_to_append_dot + postfix_len] = 0; |
4017 | 0 | return newname; |
4018 | 0 | } |
4019 | 0 | } |
4020 | | |
4021 | | /* we ran off the end of the list and still didn't find the requested string */ |
4022 | 0 | EVUTIL_ASSERT(0); |
4023 | 0 | return NULL; /* unreachable; stops warnings in some compilers. */ |
4024 | 0 | } |
4025 | | |
4026 | | static struct request * |
4027 | | search_request_new(struct evdns_base *base, struct evdns_request *handle, |
4028 | 0 | int type, const char *const name, int flags) { |
4029 | 0 | ASSERT_LOCKED(base); |
4030 | 0 | EVUTIL_ASSERT(type == TYPE_A || type == TYPE_AAAA); |
4031 | 0 | EVUTIL_ASSERT(handle->current_req == NULL); |
4032 | 0 | if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) && |
4033 | 0 | base->global_search_state && |
4034 | 0 | base->global_search_state->num_domains) { |
4035 | | /* we have some domains to search */ |
4036 | 0 | struct request *req; |
4037 | 0 | if (string_num_dots(name) >= base->global_search_state->ndots) { |
4038 | 0 | req = request_new(base, handle, type, name, flags); |
4039 | 0 | if (!req) return NULL; |
4040 | 0 | handle->search_index = -1; |
4041 | 0 | } else { |
4042 | 0 | char *const new_name = search_make_new(base->global_search_state, 0, name); |
4043 | 0 | if (!new_name) return NULL; |
4044 | 0 | req = request_new(base, handle, type, new_name, flags); |
4045 | 0 | mm_free(new_name); |
4046 | 0 | if (!req) return NULL; |
4047 | 0 | handle->search_index = 0; |
4048 | 0 | } |
4049 | 0 | EVUTIL_ASSERT(handle->search_origname == NULL); |
4050 | 0 | handle->search_origname = mm_strdup(name); |
4051 | 0 | if (handle->search_origname == NULL) { |
4052 | | /* XXX Should we dealloc req? If yes, how? */ |
4053 | 0 | if (req) |
4054 | 0 | mm_free(req); |
4055 | 0 | return NULL; |
4056 | 0 | } |
4057 | 0 | handle->search_state = base->global_search_state; |
4058 | 0 | handle->search_flags = flags; |
4059 | 0 | base->global_search_state->refcount++; |
4060 | 0 | request_submit(req); |
4061 | 0 | return req; |
4062 | 0 | } else { |
4063 | 0 | struct request *const req = request_new(base, handle, type, name, flags); |
4064 | 0 | if (!req) return NULL; |
4065 | 0 | request_submit(req); |
4066 | 0 | return req; |
4067 | 0 | } |
4068 | 0 | } |
4069 | | |
4070 | | /* this is called when a request has failed to find a name. We need to check */ |
4071 | | /* if it is part of a search and, if so, try the next name in the list */ |
4072 | | /* returns: */ |
4073 | | /* 0 another request has been submitted */ |
4074 | | /* 1 no more requests needed */ |
4075 | | static int |
4076 | 0 | search_try_next(struct evdns_request *const handle) { |
4077 | 0 | struct request *req = handle->current_req; |
4078 | 0 | struct evdns_base *base = req->base; |
4079 | 0 | struct request *newreq; |
4080 | 0 | ASSERT_LOCKED(base); |
4081 | 0 | if (handle->search_state) { |
4082 | | /* it is part of a search */ |
4083 | 0 | char *new_name; |
4084 | 0 | handle->search_index++; |
4085 | 0 | if (handle->search_index >= handle->search_state->num_domains) { |
4086 | | /* no more postfixes to try, however we may need to try */ |
4087 | | /* this name without a postfix */ |
4088 | 0 | if (string_num_dots(handle->search_origname) < handle->search_state->ndots) { |
4089 | | /* yep, we need to try it raw */ |
4090 | 0 | newreq = request_new(base, NULL, req->request_type, handle->search_origname, handle->search_flags); |
4091 | 0 | log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", handle->search_origname); |
4092 | 0 | if (newreq) { |
4093 | 0 | search_request_finished(handle); |
4094 | 0 | goto submit_next; |
4095 | 0 | } |
4096 | 0 | } |
4097 | 0 | return 1; |
4098 | 0 | } |
4099 | | |
4100 | 0 | new_name = search_make_new(handle->search_state, handle->search_index, handle->search_origname); |
4101 | 0 | if (!new_name) return 1; |
4102 | 0 | log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, handle->search_index); |
4103 | 0 | newreq = request_new(base, NULL, req->request_type, new_name, handle->search_flags); |
4104 | 0 | mm_free(new_name); |
4105 | 0 | if (!newreq) return 1; |
4106 | 0 | goto submit_next; |
4107 | 0 | } |
4108 | 0 | return 1; |
4109 | | |
4110 | 0 | submit_next: |
4111 | 0 | request_finished(req, &REQ_HEAD(req->base, req->trans_id), 0); |
4112 | 0 | handle->current_req = newreq; |
4113 | 0 | newreq->handle = handle; |
4114 | 0 | request_submit(newreq); |
4115 | 0 | return 0; |
4116 | 0 | } |
4117 | | |
4118 | | static void |
4119 | 0 | search_request_finished(struct evdns_request *const handle) { |
4120 | 0 | ASSERT_LOCKED(handle->current_req->base); |
4121 | 0 | if (handle->search_state) { |
4122 | 0 | search_state_decref(handle->search_state); |
4123 | 0 | handle->search_state = NULL; |
4124 | 0 | } |
4125 | 0 | if (handle->search_origname) { |
4126 | 0 | mm_free(handle->search_origname); |
4127 | 0 | handle->search_origname = NULL; |
4128 | 0 | } |
4129 | 0 | } |
4130 | | |
4131 | | /* ================================================================= */ |
4132 | | /* Parsing resolv.conf files */ |
4133 | | |
4134 | | static void |
4135 | 0 | evdns_resolv_set_defaults(struct evdns_base *base, int flags) { |
4136 | 0 | int add_default = flags & DNS_OPTION_NAMESERVERS; |
4137 | 0 | if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT) |
4138 | 0 | add_default = 0; |
4139 | | |
4140 | | /* if the file isn't found then we assume a local resolver */ |
4141 | 0 | ASSERT_LOCKED(base); |
4142 | 0 | if (flags & DNS_OPTION_SEARCH) |
4143 | 0 | search_set_from_hostname(base); |
4144 | 0 | if (add_default) |
4145 | 0 | evdns_base_nameserver_ip_add(base, "127.0.0.1"); |
4146 | 0 | } |
4147 | | |
4148 | | #ifndef EVENT__HAVE_STRTOK_R |
4149 | | static char * |
4150 | | strtok_r(char *s, const char *delim, char **state) { |
4151 | | char *cp, *start; |
4152 | | start = cp = s ? s : *state; |
4153 | | if (!cp) |
4154 | | return NULL; |
4155 | | while (*cp && !strchr(delim, *cp)) |
4156 | | ++cp; |
4157 | | if (!*cp) { |
4158 | | if (cp == start) |
4159 | | return NULL; |
4160 | | *state = NULL; |
4161 | | return start; |
4162 | | } else { |
4163 | | *cp++ = '\0'; |
4164 | | *state = cp; |
4165 | | return start; |
4166 | | } |
4167 | | } |
4168 | | #endif |
4169 | | |
4170 | | /* helper version of atoi which returns -1 on error */ |
4171 | | static int |
4172 | | strtoint(const char *const str) |
4173 | 0 | { |
4174 | 0 | char *endptr; |
4175 | 0 | const int r = strtol(str, &endptr, 10); |
4176 | 0 | if (*endptr) return -1; |
4177 | 0 | return r; |
4178 | 0 | } |
4179 | | |
4180 | | /* Parse a number of seconds into a timeval; return -1 on error. */ |
4181 | | static int |
4182 | | evdns_strtotimeval(const char *const str, struct timeval *out) |
4183 | 0 | { |
4184 | 0 | double d; |
4185 | 0 | char *endptr; |
4186 | 0 | d = strtod(str, &endptr); |
4187 | 0 | if (*endptr) return -1; |
4188 | 0 | if (d < 0) return -1; |
4189 | 0 | out->tv_sec = (int) d; |
4190 | 0 | out->tv_usec = (int) ((d - (int) d)*1000000); |
4191 | 0 | if (out->tv_sec == 0 && out->tv_usec < 1000) /* less than 1 msec */ |
4192 | 0 | return -1; |
4193 | 0 | return 0; |
4194 | 0 | } |
4195 | | |
4196 | | /* helper version of atoi that returns -1 on error and clips to bounds. */ |
4197 | | static int |
4198 | | strtoint_clipped(const char *const str, int min, int max) |
4199 | 0 | { |
4200 | 0 | int r = strtoint(str); |
4201 | 0 | if (r == -1) |
4202 | 0 | return r; |
4203 | 0 | else if (r<min) |
4204 | 0 | return min; |
4205 | 0 | else if (r>max) |
4206 | 0 | return max; |
4207 | 0 | else |
4208 | 0 | return r; |
4209 | 0 | } |
4210 | | |
4211 | | static int |
4212 | | evdns_base_set_max_requests_inflight(struct evdns_base *base, int maxinflight) |
4213 | 0 | { |
4214 | 0 | int old_n_heads = base->n_req_heads, n_heads; |
4215 | 0 | struct request **old_heads = base->req_heads, **new_heads, *req; |
4216 | 0 | int i; |
4217 | |
|
4218 | 0 | ASSERT_LOCKED(base); |
4219 | 0 | if (maxinflight < 1) |
4220 | 0 | maxinflight = 1; |
4221 | 0 | n_heads = (maxinflight+4) / 5; |
4222 | 0 | EVUTIL_ASSERT(n_heads > 0); |
4223 | 0 | new_heads = mm_calloc(n_heads, sizeof(struct request*)); |
4224 | 0 | if (!new_heads) |
4225 | 0 | return (-1); |
4226 | 0 | if (old_heads) { |
4227 | 0 | for (i = 0; i < old_n_heads; ++i) { |
4228 | 0 | while (old_heads[i]) { |
4229 | 0 | req = old_heads[i]; |
4230 | 0 | evdns_request_remove(req, &old_heads[i]); |
4231 | 0 | evdns_request_insert(req, &new_heads[req->trans_id % n_heads]); |
4232 | 0 | } |
4233 | 0 | } |
4234 | 0 | mm_free(old_heads); |
4235 | 0 | } |
4236 | 0 | base->req_heads = new_heads; |
4237 | 0 | base->n_req_heads = n_heads; |
4238 | 0 | base->global_max_requests_inflight = maxinflight; |
4239 | 0 | return (0); |
4240 | 0 | } |
4241 | | |
4242 | | /* exported function */ |
4243 | | int |
4244 | | evdns_base_set_option(struct evdns_base *base, |
4245 | | const char *option, const char *val) |
4246 | 0 | { |
4247 | 0 | int res; |
4248 | 0 | EVDNS_LOCK(base); |
4249 | 0 | res = evdns_base_set_option_impl(base, option, val, DNS_OPTIONS_ALL); |
4250 | 0 | EVDNS_UNLOCK(base); |
4251 | 0 | return res; |
4252 | 0 | } |
4253 | | |
4254 | | static inline int |
4255 | | str_matches_option(const char *s1, const char *optionname) |
4256 | 0 | { |
4257 | | /* Option names are given as "option:" We accept either 'option' in |
4258 | | * s1, or 'option:randomjunk'. The latter form is to implement the |
4259 | | * resolv.conf parser. */ |
4260 | 0 | size_t optlen = strlen(optionname); |
4261 | 0 | size_t slen = strlen(s1); |
4262 | 0 | if (slen == optlen || slen == optlen - 1) |
4263 | 0 | return !strncmp(s1, optionname, slen); |
4264 | 0 | else if (slen > optlen) |
4265 | 0 | return !strncmp(s1, optionname, optlen); |
4266 | 0 | else |
4267 | 0 | return 0; |
4268 | 0 | } |
4269 | | |
4270 | | /* exported function */ |
4271 | | int |
4272 | | evdns_server_port_set_option(struct evdns_server_port *port, |
4273 | | enum evdns_server_option option, size_t value) |
4274 | 0 | { |
4275 | 0 | int res = 0; |
4276 | 0 | EVDNS_LOCK(port); |
4277 | 0 | switch (option) { |
4278 | 0 | case EVDNS_SOPT_TCP_MAX_CLIENTS: |
4279 | 0 | if (!port->listener) { |
4280 | 0 | log(EVDNS_LOG_WARN, "EVDNS_SOPT_TCP_MAX_CLIENTS option can be set only on TCP server"); |
4281 | 0 | res = -1; |
4282 | 0 | goto end; |
4283 | 0 | } |
4284 | 0 | port->max_client_connections = value; |
4285 | 0 | log(EVDNS_LOG_DEBUG, "Setting EVDNS_SOPT_TCP_MAX_CLIENTS to %u", port->max_client_connections); |
4286 | 0 | break; |
4287 | 0 | case EVDNS_SOPT_TCP_IDLE_TIMEOUT: |
4288 | 0 | if (!port->listener) { |
4289 | 0 | log(EVDNS_LOG_WARN, "EVDNS_SOPT_TCP_IDLE_TIMEOUT option can be set only on TCP server"); |
4290 | 0 | res = -1; |
4291 | 0 | goto end; |
4292 | 0 | } |
4293 | 0 | port->tcp_idle_timeout.tv_sec = value; |
4294 | 0 | port->tcp_idle_timeout.tv_usec = 0; |
4295 | 0 | log(EVDNS_LOG_DEBUG, "Setting EVDNS_SOPT_TCP_IDLE_TIMEOUT to %u seconds", |
4296 | 0 | (unsigned)port->tcp_idle_timeout.tv_sec); |
4297 | 0 | break; |
4298 | 0 | default: |
4299 | 0 | log(EVDNS_LOG_WARN, "Invalid DNS server option %d", (int)option); |
4300 | 0 | res = -1; |
4301 | 0 | break; |
4302 | 0 | } |
4303 | 0 | end: |
4304 | 0 | EVDNS_UNLOCK(port); |
4305 | 0 | return res; |
4306 | 0 | } |
4307 | | |
4308 | | static int |
4309 | | evdns_base_set_option_impl(struct evdns_base *base, |
4310 | | const char *option, const char *val, int flags) |
4311 | 0 | { |
4312 | 0 | ASSERT_LOCKED(base); |
4313 | 0 | if (str_matches_option(option, "ndots:")) { |
4314 | 0 | const int ndots = strtoint(val); |
4315 | 0 | if (ndots == -1) return -1; |
4316 | 0 | if (!(flags & DNS_OPTION_SEARCH)) return 0; |
4317 | 0 | log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots); |
4318 | 0 | if (!base->global_search_state) base->global_search_state = search_state_new(); |
4319 | 0 | if (!base->global_search_state) return -1; |
4320 | 0 | base->global_search_state->ndots = ndots; |
4321 | 0 | } else if (str_matches_option(option, "timeout:")) { |
4322 | 0 | struct timeval tv; |
4323 | 0 | if (evdns_strtotimeval(val, &tv) == -1) return -1; |
4324 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4325 | 0 | log(EVDNS_LOG_DEBUG, "Setting timeout to %s", val); |
4326 | 0 | memcpy(&base->global_timeout, &tv, sizeof(struct timeval)); |
4327 | 0 | } else if (str_matches_option(option, "getaddrinfo-allow-skew:")) { |
4328 | 0 | struct timeval tv; |
4329 | 0 | if (evdns_strtotimeval(val, &tv) == -1) return -1; |
4330 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4331 | 0 | log(EVDNS_LOG_DEBUG, "Setting getaddrinfo-allow-skew to %s", |
4332 | 0 | val); |
4333 | 0 | memcpy(&base->global_getaddrinfo_allow_skew, &tv, |
4334 | 0 | sizeof(struct timeval)); |
4335 | 0 | } else if (str_matches_option(option, "max-timeouts:")) { |
4336 | 0 | const int maxtimeout = strtoint_clipped(val, 1, 255); |
4337 | 0 | if (maxtimeout == -1) return -1; |
4338 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4339 | 0 | log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d", |
4340 | 0 | maxtimeout); |
4341 | 0 | base->global_max_nameserver_timeout = maxtimeout; |
4342 | 0 | } else if (str_matches_option(option, "max-inflight:")) { |
4343 | 0 | const int maxinflight = strtoint_clipped(val, 1, 65000); |
4344 | 0 | if (maxinflight == -1) return -1; |
4345 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4346 | 0 | log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d", |
4347 | 0 | maxinflight); |
4348 | 0 | evdns_base_set_max_requests_inflight(base, maxinflight); |
4349 | 0 | } else if (str_matches_option(option, "attempts:")) { |
4350 | 0 | int retries = strtoint(val); |
4351 | 0 | if (retries == -1) return -1; |
4352 | 0 | if (retries > 255) retries = 255; |
4353 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4354 | 0 | log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries); |
4355 | 0 | base->global_max_retransmits = retries; |
4356 | 0 | } else if (str_matches_option(option, "randomize-case:")) { |
4357 | 0 | int randcase = strtoint(val); |
4358 | 0 | if (randcase == -1) return -1; |
4359 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4360 | 0 | base->global_randomize_case = randcase; |
4361 | 0 | } else if (str_matches_option(option, "bind-to:")) { |
4362 | | /* XXX This only applies to successive nameservers, not |
4363 | | * to already-configured ones. We might want to fix that. */ |
4364 | 0 | int len = sizeof(base->global_outgoing_address); |
4365 | 0 | if (!(flags & DNS_OPTION_NAMESERVERS)) return 0; |
4366 | 0 | if (evutil_parse_sockaddr_port(val, |
4367 | 0 | (struct sockaddr*)&base->global_outgoing_address, &len)) |
4368 | 0 | return -1; |
4369 | 0 | base->global_outgoing_addrlen = len; |
4370 | 0 | } else if (str_matches_option(option, "initial-probe-timeout:")) { |
4371 | 0 | struct timeval tv; |
4372 | 0 | if (evdns_strtotimeval(val, &tv) == -1) return -1; |
4373 | 0 | if (tv.tv_sec > 3600) |
4374 | 0 | tv.tv_sec = 3600; |
4375 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4376 | 0 | log(EVDNS_LOG_DEBUG, "Setting initial probe timeout to %s", |
4377 | 0 | val); |
4378 | 0 | memcpy(&base->global_nameserver_probe_initial_timeout, &tv, |
4379 | 0 | sizeof(tv)); |
4380 | 0 | } else if (str_matches_option(option, "max-probe-timeout:")) { |
4381 | 0 | const int max_probe_timeout = strtoint_clipped(val, 1, 3600); |
4382 | 0 | if (max_probe_timeout == -1) return -1; |
4383 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4384 | 0 | log(EVDNS_LOG_DEBUG, "Setting maximum probe timeout to %d", |
4385 | 0 | max_probe_timeout); |
4386 | 0 | base->ns_max_probe_timeout = max_probe_timeout; |
4387 | 0 | if (base->global_nameserver_probe_initial_timeout.tv_sec > max_probe_timeout) { |
4388 | 0 | base->global_nameserver_probe_initial_timeout.tv_sec = max_probe_timeout; |
4389 | 0 | base->global_nameserver_probe_initial_timeout.tv_usec = 0; |
4390 | 0 | log(EVDNS_LOG_DEBUG, "Setting initial probe timeout to %s", |
4391 | 0 | val); |
4392 | 0 | } |
4393 | 0 | } else if (str_matches_option(option, "probe-backoff-factor:")) { |
4394 | 0 | const int backoff_backtor = strtoint_clipped(val, 1, 10); |
4395 | 0 | if (backoff_backtor == -1) return -1; |
4396 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4397 | 0 | log(EVDNS_LOG_DEBUG, "Setting probe timeout backoff factor to %d", |
4398 | 0 | backoff_backtor); |
4399 | 0 | base->ns_timeout_backoff_factor = backoff_backtor; |
4400 | 0 | } else if (str_matches_option(option, "so-rcvbuf:")) { |
4401 | 0 | int buf = strtoint(val); |
4402 | 0 | if (buf == -1) return -1; |
4403 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4404 | 0 | log(EVDNS_LOG_DEBUG, "Setting SO_RCVBUF to %s", val); |
4405 | 0 | base->so_rcvbuf = buf; |
4406 | 0 | } else if (str_matches_option(option, "so-sndbuf:")) { |
4407 | 0 | int buf = strtoint(val); |
4408 | 0 | if (buf == -1) return -1; |
4409 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4410 | 0 | log(EVDNS_LOG_DEBUG, "Setting SO_SNDBUF to %s", val); |
4411 | 0 | base->so_sndbuf = buf; |
4412 | 0 | } else if (str_matches_option(option, "tcp-idle-timeout:")) { |
4413 | 0 | struct timeval tv; |
4414 | 0 | if (evdns_strtotimeval(val, &tv) == -1) return -1; |
4415 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4416 | 0 | log(EVDNS_LOG_DEBUG, "Setting tcp idle timeout to %s", val); |
4417 | 0 | memcpy(&base->global_tcp_idle_timeout, &tv, sizeof(tv)); |
4418 | 0 | } else if (str_matches_option(option, "use-vc:")) { |
4419 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4420 | 0 | if (val && strlen(val)) return -1; |
4421 | 0 | log(EVDNS_LOG_DEBUG, "Setting use-vc option"); |
4422 | 0 | base->global_tcp_flags |= DNS_QUERY_USEVC; |
4423 | 0 | } else if (str_matches_option(option, "ignore-tc:")) { |
4424 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4425 | 0 | if (val && strlen(val)) return -1; |
4426 | 0 | log(EVDNS_LOG_DEBUG, "Setting ignore-tc option"); |
4427 | 0 | base->global_tcp_flags |= DNS_QUERY_IGNTC; |
4428 | 0 | } else if (str_matches_option(option, "edns-udp-size:")) { |
4429 | 0 | const int sz = strtoint_clipped(val, DNS_MAX_UDP_SIZE, EDNS_MAX_UDP_SIZE); |
4430 | 0 | if (sz == -1) return -1; |
4431 | 0 | if (!(flags & DNS_OPTION_MISC)) return 0; |
4432 | 0 | log(EVDNS_LOG_DEBUG, "Setting edns-udp-size to %d", sz); |
4433 | 0 | base->global_max_udp_size = sz; |
4434 | 0 | } |
4435 | 0 | return 0; |
4436 | 0 | } |
4437 | | |
4438 | | int |
4439 | | evdns_set_option(const char *option, const char *val, int flags) |
4440 | 0 | { |
4441 | 0 | if (!current_base) |
4442 | 0 | current_base = evdns_base_new(NULL, 0); |
4443 | 0 | return evdns_base_set_option(current_base, option, val); |
4444 | 0 | } |
4445 | | |
4446 | | static void |
4447 | 0 | resolv_conf_parse_line(struct evdns_base *base, char *const start, int flags) { |
4448 | 0 | char *strtok_state; |
4449 | 0 | static const char *const delims = " \t"; |
4450 | 0 | #define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) |
4451 | | |
4452 | |
|
4453 | 0 | char *const first_token = strtok_r(start, delims, &strtok_state); |
4454 | 0 | ASSERT_LOCKED(base); |
4455 | 0 | if (!first_token) return; |
4456 | | |
4457 | 0 | if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { |
4458 | 0 | const char *const nameserver = NEXT_TOKEN; |
4459 | |
|
4460 | 0 | if (nameserver) |
4461 | 0 | evdns_base_nameserver_ip_add(base, nameserver); |
4462 | 0 | } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) { |
4463 | 0 | const char *const domain = NEXT_TOKEN; |
4464 | 0 | if (domain) { |
4465 | 0 | search_postfix_clear(base); |
4466 | 0 | search_postfix_add(base, domain); |
4467 | 0 | } |
4468 | 0 | } else if (!strcmp(first_token, "search") && (flags & DNS_OPTION_SEARCH)) { |
4469 | 0 | const char *domain; |
4470 | 0 | search_postfix_clear(base); |
4471 | |
|
4472 | 0 | while ((domain = NEXT_TOKEN)) { |
4473 | 0 | search_postfix_add(base, domain); |
4474 | 0 | } |
4475 | 0 | search_reverse(base); |
4476 | 0 | } else if (!strcmp(first_token, "options")) { |
4477 | 0 | const char *option; |
4478 | 0 | while ((option = NEXT_TOKEN)) { |
4479 | 0 | const char *val = strchr(option, ':'); |
4480 | 0 | evdns_base_set_option_impl(base, option, val ? val+1 : "", flags); |
4481 | 0 | } |
4482 | 0 | } |
4483 | 0 | #undef NEXT_TOKEN |
4484 | 0 | } |
4485 | | |
4486 | | /* exported function */ |
4487 | | /* returns: */ |
4488 | | /* EVDNS_ERROR_NONE (0) no errors */ |
4489 | | /* EVDNS_ERROR_FAILED_TO_OPEN_FILE (1) failed to open file */ |
4490 | | /* EVDNS_ERROR_FAILED_TO_STAT_FILE (2) failed to stat file */ |
4491 | | /* EVDNS_ERROR_FILE_TOO_LARGE (3) file too large */ |
4492 | | /* EVDNS_ERROR_OUT_OF_MEMORY (4) out of memory */ |
4493 | | /* EVDNS_ERROR_SHORT_READ_FROM_FILE (5) short read from file */ |
4494 | | /* EVDNS_ERROR_NO_NAMESERVERS_CONFIGURED (6) no nameservers configured */ |
4495 | | int |
4496 | 0 | evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename) { |
4497 | 0 | int res; |
4498 | 0 | EVDNS_LOCK(base); |
4499 | 0 | res = evdns_base_resolv_conf_parse_impl(base, flags, filename); |
4500 | 0 | EVDNS_UNLOCK(base); |
4501 | 0 | return res; |
4502 | 0 | } |
4503 | | |
4504 | | static char * |
4505 | | evdns_get_default_hosts_filename(void) |
4506 | 0 | { |
4507 | | #ifdef _WIN32 |
4508 | | /* Windows is a little coy about where it puts its configuration |
4509 | | * files. Sure, they're _usually_ in C:\windows\system32, but |
4510 | | * there's no reason in principle they couldn't be in |
4511 | | * W:\hoboken chicken emergency\ |
4512 | | */ |
4513 | | char path[MAX_PATH+1]; |
4514 | | static const char hostfile[] = "\\drivers\\etc\\hosts"; |
4515 | | char *path_out; |
4516 | | size_t len_out; |
4517 | | |
4518 | | if (! SHGetSpecialFolderPathA(NULL, path, CSIDL_SYSTEM, 0)) |
4519 | | return NULL; |
4520 | | len_out = strlen(path)+strlen(hostfile)+1; |
4521 | | path_out = mm_malloc(len_out); |
4522 | | evutil_snprintf(path_out, len_out, "%s%s", path, hostfile); |
4523 | | return path_out; |
4524 | | #else |
4525 | 0 | return mm_strdup("/etc/hosts"); |
4526 | 0 | #endif |
4527 | 0 | } |
4528 | | |
4529 | | static int |
4530 | 0 | evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename) { |
4531 | 0 | size_t n; |
4532 | 0 | char *resolv; |
4533 | 0 | char *start; |
4534 | 0 | int err = EVDNS_ERROR_NONE; |
4535 | 0 | int add_default; |
4536 | |
|
4537 | 0 | log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); |
4538 | |
|
4539 | 0 | add_default = flags & DNS_OPTION_NAMESERVERS; |
4540 | 0 | if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT) |
4541 | 0 | add_default = 0; |
4542 | |
|
4543 | 0 | if (flags & DNS_OPTION_HOSTSFILE) { |
4544 | 0 | char *fname = evdns_get_default_hosts_filename(); |
4545 | 0 | evdns_base_load_hosts(base, fname); |
4546 | 0 | if (fname) |
4547 | 0 | mm_free(fname); |
4548 | 0 | } |
4549 | |
|
4550 | 0 | if (!filename) { |
4551 | 0 | evdns_resolv_set_defaults(base, flags); |
4552 | 0 | return EVDNS_ERROR_FAILED_TO_OPEN_FILE; |
4553 | 0 | } |
4554 | | |
4555 | 0 | if ((err = evutil_read_file_(filename, &resolv, &n, 0)) < 0) { |
4556 | 0 | if (err == -1) { |
4557 | | /* No file. */ |
4558 | 0 | evdns_resolv_set_defaults(base, flags); |
4559 | 0 | return EVDNS_ERROR_FAILED_TO_OPEN_FILE; |
4560 | 0 | } else { |
4561 | 0 | return EVDNS_ERROR_FAILED_TO_STAT_FILE; |
4562 | 0 | } |
4563 | 0 | } |
4564 | | |
4565 | 0 | start = resolv; |
4566 | 0 | for (;;) { |
4567 | 0 | char *const newline = strchr(start, '\n'); |
4568 | 0 | if (!newline) { |
4569 | 0 | resolv_conf_parse_line(base, start, flags); |
4570 | 0 | break; |
4571 | 0 | } else { |
4572 | 0 | *newline = 0; |
4573 | 0 | resolv_conf_parse_line(base, start, flags); |
4574 | 0 | start = newline + 1; |
4575 | 0 | } |
4576 | 0 | } |
4577 | |
|
4578 | 0 | if (!base->server_head && add_default) { |
4579 | | /* no nameservers were configured. */ |
4580 | 0 | evdns_base_nameserver_ip_add(base, "127.0.0.1"); |
4581 | 0 | err = EVDNS_ERROR_NO_NAMESERVERS_CONFIGURED; |
4582 | 0 | } |
4583 | 0 | if (flags & DNS_OPTION_SEARCH && (!base->global_search_state || base->global_search_state->num_domains == 0)) { |
4584 | 0 | search_set_from_hostname(base); |
4585 | 0 | } |
4586 | |
|
4587 | 0 | mm_free(resolv); |
4588 | 0 | return err; |
4589 | 0 | } |
4590 | | |
4591 | | int |
4592 | 0 | evdns_resolv_conf_parse(int flags, const char *const filename) { |
4593 | 0 | if (!current_base) |
4594 | 0 | current_base = evdns_base_new(NULL, 0); |
4595 | 0 | return evdns_base_resolv_conf_parse(current_base, flags, filename); |
4596 | 0 | } |
4597 | | |
4598 | | |
4599 | | #ifdef _WIN32 |
4600 | | /* Add multiple nameservers from a space-or-comma-separated list. */ |
4601 | | static int |
4602 | | evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) { |
4603 | | const char *addr; |
4604 | | char *buf; |
4605 | | int r; |
4606 | | ASSERT_LOCKED(base); |
4607 | | while (*ips) { |
4608 | | while (isspace(*ips) || *ips == ',' || *ips == '\t') |
4609 | | ++ips; |
4610 | | addr = ips; |
4611 | | while (isdigit(*ips) || *ips == '.' || *ips == ':' || |
4612 | | *ips=='[' || *ips==']') |
4613 | | ++ips; |
4614 | | buf = mm_malloc(ips-addr+1); |
4615 | | if (!buf) return 4; |
4616 | | memcpy(buf, addr, ips-addr); |
4617 | | buf[ips-addr] = '\0'; |
4618 | | r = evdns_base_nameserver_ip_add(base, buf); |
4619 | | mm_free(buf); |
4620 | | if (r) return r; |
4621 | | } |
4622 | | return 0; |
4623 | | } |
4624 | | |
4625 | | typedef DWORD(WINAPI *GetAdaptersAddresses_fn_t)(ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG); |
4626 | | |
4627 | | /* Use the windows GetAdaptersAddresses interface in iphlpapi.dll to */ |
4628 | | /* figure out what our nameservers are. */ |
4629 | | static int |
4630 | | load_nameservers_with_getadaptersaddresses_unlocked(struct evdns_base *base) |
4631 | | { |
4632 | | PIP_ADAPTER_ADDRESSES addresses = NULL; |
4633 | | HMODULE handle = 0; |
4634 | | ULONG size = sizeof(IP_ADAPTER_ADDRESSES); |
4635 | | void *buf = NULL; |
4636 | | int status = 0, r, added_any = 0; |
4637 | | GetAdaptersAddresses_fn_t fn; |
4638 | | IP_ADAPTER_DNS_SERVER_ADDRESS *dnsserver = NULL; |
4639 | | |
4640 | | ASSERT_LOCKED(base); |
4641 | | if (!(handle = evutil_load_windows_system_library_( |
4642 | | TEXT("iphlpapi.dll")))) { |
4643 | | log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll"); |
4644 | | status = -1; |
4645 | | goto done; |
4646 | | } |
4647 | | if (!(fn = (GetAdaptersAddresses_fn_t) GetProcAddress(handle, "GetAdaptersAddresses"))) { |
4648 | | log(EVDNS_LOG_WARN, "Could not get address of function."); |
4649 | | status = -1; |
4650 | | goto done; |
4651 | | } |
4652 | | |
4653 | | buf = mm_malloc(size); |
4654 | | if (!buf) { status = 4; goto done; } |
4655 | | addresses = buf; |
4656 | | r = fn(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, addresses, &size); |
4657 | | if (r != NO_ERROR && r != ERROR_BUFFER_OVERFLOW) { |
4658 | | status = -1; |
4659 | | goto done; |
4660 | | } |
4661 | | if (r != NO_ERROR) { |
4662 | | mm_free(buf); |
4663 | | buf = mm_malloc(size); |
4664 | | if (!buf) { status = 4; goto done; } |
4665 | | addresses = buf; |
4666 | | r = fn(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, addresses, &size); |
4667 | | if (r != NO_ERROR) { |
4668 | | log(EVDNS_LOG_DEBUG, "fn() failed."); |
4669 | | status = -1; |
4670 | | goto done; |
4671 | | } |
4672 | | } |
4673 | | |
4674 | | while (addresses) { |
4675 | | dnsserver = addresses->FirstDnsServerAddress; |
4676 | | while (dnsserver && (addresses->OperStatus == IfOperStatusUp)) { |
4677 | | char ip[INET6_ADDRSTRLEN] = {0}; |
4678 | | if (AF_INET == dnsserver->Address.lpSockaddr->sa_family) { |
4679 | | inet_ntop(AF_INET, &((SOCKADDR_IN *)dnsserver->Address.lpSockaddr)->sin_addr, ip, sizeof(ip)); |
4680 | | } else if (AF_INET6 == dnsserver->Address.lpSockaddr->sa_family) { |
4681 | | inet_ntop(AF_INET6, &((SOCKADDR_IN6 *)dnsserver->Address.lpSockaddr)->sin6_addr, ip, sizeof(ip)); |
4682 | | } |
4683 | | |
4684 | | dnsserver = dnsserver->Next; |
4685 | | if (strncmp(ip, "fec0:", 5) == 0) { /* remove ipv6 reserved address */ |
4686 | | continue; |
4687 | | } |
4688 | | |
4689 | | r = evdns_base_nameserver_ip_add(base, ip); |
4690 | | if (r) { |
4691 | | log(EVDNS_LOG_DEBUG, "Could not add nameserver %s to list, error: %d", ip, r); |
4692 | | status = r; |
4693 | | } else { |
4694 | | ++added_any; |
4695 | | log(EVDNS_LOG_DEBUG, "Successfully added %s as nameserver", ip); |
4696 | | } |
4697 | | } |
4698 | | |
4699 | | addresses = addresses->Next; |
4700 | | } |
4701 | | |
4702 | | if (!added_any) { |
4703 | | log(EVDNS_LOG_DEBUG, "No nameservers added."); |
4704 | | if (status == 0) |
4705 | | status = -1; |
4706 | | } else { |
4707 | | status = 0; |
4708 | | } |
4709 | | |
4710 | | done: |
4711 | | if (buf) |
4712 | | mm_free(buf); |
4713 | | if (handle) |
4714 | | FreeLibrary(handle); |
4715 | | return status; |
4716 | | } |
4717 | | |
4718 | | int |
4719 | | load_nameservers_with_getadaptersaddresses(struct evdns_base *base) |
4720 | | { |
4721 | | int r; |
4722 | | EVDNS_LOCK(base); |
4723 | | r = load_nameservers_with_getadaptersaddresses_unlocked(base); |
4724 | | EVDNS_UNLOCK(base); |
4725 | | return r; |
4726 | | } |
4727 | | |
4728 | | static int |
4729 | | config_nameserver_from_reg_key(struct evdns_base *base, HKEY key, const TCHAR *subkey) |
4730 | | { |
4731 | | char *buf; |
4732 | | DWORD bufsz = 0, type = 0; |
4733 | | int status = 0; |
4734 | | |
4735 | | ASSERT_LOCKED(base); |
4736 | | if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz) |
4737 | | != ERROR_MORE_DATA) |
4738 | | return -1; |
4739 | | if (!(buf = mm_malloc(bufsz))) |
4740 | | return -1; |
4741 | | |
4742 | | if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz) |
4743 | | == ERROR_SUCCESS && bufsz > 1) { |
4744 | | status = evdns_nameserver_ip_add_line(base,buf); |
4745 | | } |
4746 | | |
4747 | | mm_free(buf); |
4748 | | return status; |
4749 | | } |
4750 | | |
4751 | | #define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\") |
4752 | | #define WIN_NS_9X_KEY SERVICES_KEY TEXT("VxD\\MSTCP") |
4753 | | #define WIN_NS_NT_KEY SERVICES_KEY TEXT("Tcpip\\Parameters") |
4754 | | |
4755 | | static int |
4756 | | load_nameservers_from_registry(struct evdns_base *base) |
4757 | | { |
4758 | | int found = 0; |
4759 | | int r; |
4760 | | #define TRY(k, name) \ |
4761 | | if (!found && config_nameserver_from_reg_key(base,k,TEXT(name)) == 0) { \ |
4762 | | log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ |
4763 | | found = 1; \ |
4764 | | } else if (!found) { \ |
4765 | | log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \ |
4766 | | #k,#name); \ |
4767 | | } |
4768 | | |
4769 | | ASSERT_LOCKED(base); |
4770 | | |
4771 | | if (((int)GetVersion()) > 0) { /* NT */ |
4772 | | HKEY nt_key = 0, interfaces_key = 0; |
4773 | | |
4774 | | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, |
4775 | | KEY_READ, &nt_key) != ERROR_SUCCESS) { |
4776 | | log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); |
4777 | | return -1; |
4778 | | } |
4779 | | r = RegOpenKeyEx(nt_key, TEXT("Interfaces"), 0, |
4780 | | KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, |
4781 | | &interfaces_key); |
4782 | | if (r != ERROR_SUCCESS) { |
4783 | | log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError()); |
4784 | | return -1; |
4785 | | } |
4786 | | TRY(nt_key, "NameServer"); |
4787 | | TRY(nt_key, "DhcpNameServer"); |
4788 | | TRY(interfaces_key, "NameServer"); |
4789 | | TRY(interfaces_key, "DhcpNameServer"); |
4790 | | RegCloseKey(interfaces_key); |
4791 | | RegCloseKey(nt_key); |
4792 | | } else { |
4793 | | HKEY win_key = 0; |
4794 | | if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0, |
4795 | | KEY_READ, &win_key) != ERROR_SUCCESS) { |
4796 | | log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError()); |
4797 | | return -1; |
4798 | | } |
4799 | | TRY(win_key, "NameServer"); |
4800 | | RegCloseKey(win_key); |
4801 | | } |
4802 | | |
4803 | | if (found == 0) { |
4804 | | log(EVDNS_LOG_WARN,"Didn't find any nameservers."); |
4805 | | } |
4806 | | |
4807 | | return found ? 0 : -1; |
4808 | | #undef TRY |
4809 | | } |
4810 | | |
4811 | | int |
4812 | | evdns_base_config_windows_nameservers(struct evdns_base *base) |
4813 | | { |
4814 | | int r; |
4815 | | char *fname; |
4816 | | if (base == NULL) |
4817 | | base = current_base; |
4818 | | if (base == NULL) |
4819 | | return -1; |
4820 | | EVDNS_LOCK(base); |
4821 | | fname = evdns_get_default_hosts_filename(); |
4822 | | log(EVDNS_LOG_DEBUG, "Loading hosts entries from %s", fname); |
4823 | | evdns_base_load_hosts(base, fname); |
4824 | | if (fname) |
4825 | | mm_free(fname); |
4826 | | |
4827 | | if (load_nameservers_with_getadaptersaddresses_unlocked(base) == 0) { |
4828 | | EVDNS_UNLOCK(base); |
4829 | | return 0; |
4830 | | } |
4831 | | r = load_nameservers_from_registry(base); |
4832 | | |
4833 | | EVDNS_UNLOCK(base); |
4834 | | return r; |
4835 | | } |
4836 | | |
4837 | | int |
4838 | | evdns_config_windows_nameservers(void) |
4839 | | { |
4840 | | if (!current_base) { |
4841 | | current_base = evdns_base_new(NULL, 1); |
4842 | | return current_base == NULL ? -1 : 0; |
4843 | | } else { |
4844 | | return evdns_base_config_windows_nameservers(current_base); |
4845 | | } |
4846 | | } |
4847 | | #endif |
4848 | | |
4849 | | struct evdns_base * |
4850 | | evdns_base_new(struct event_base *event_base, int flags) |
4851 | 0 | { |
4852 | 0 | struct evdns_base *base; |
4853 | |
|
4854 | 0 | if (evutil_secure_rng_init() < 0) { |
4855 | 0 | log(EVDNS_LOG_WARN, "Unable to seed random number generator; " |
4856 | 0 | "DNS can't run."); |
4857 | 0 | return NULL; |
4858 | 0 | } |
4859 | | |
4860 | | /* Give the evutil library a hook into its evdns-enabled |
4861 | | * functionality. We can't just call evdns_getaddrinfo directly or |
4862 | | * else libevent-core will depend on libevent-extras. */ |
4863 | 0 | evutil_set_evdns_getaddrinfo_fn_(evdns_getaddrinfo); |
4864 | 0 | evutil_set_evdns_getaddrinfo_cancel_fn_(evdns_getaddrinfo_cancel); |
4865 | |
|
4866 | 0 | base = mm_malloc(sizeof(struct evdns_base)); |
4867 | 0 | if (base == NULL) |
4868 | 0 | return (NULL); |
4869 | 0 | memset(base, 0, sizeof(struct evdns_base)); |
4870 | 0 | base->req_waiting_head = NULL; |
4871 | |
|
4872 | 0 | EVTHREAD_ALLOC_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); |
4873 | 0 | EVDNS_LOCK(base); |
4874 | | |
4875 | | /* Set max requests inflight and allocate req_heads. */ |
4876 | 0 | base->req_heads = NULL; |
4877 | |
|
4878 | 0 | evdns_base_set_max_requests_inflight(base, 64); |
4879 | |
|
4880 | 0 | base->server_head = NULL; |
4881 | 0 | base->event_base = event_base; |
4882 | 0 | base->global_good_nameservers = base->global_requests_inflight = |
4883 | 0 | base->global_requests_waiting = 0; |
4884 | |
|
4885 | 0 | base->global_timeout.tv_sec = 5; |
4886 | 0 | base->global_timeout.tv_usec = 0; |
4887 | 0 | base->global_max_reissues = 1; |
4888 | 0 | base->global_max_retransmits = 3; |
4889 | 0 | base->global_max_nameserver_timeout = 3; |
4890 | 0 | base->global_search_state = NULL; |
4891 | 0 | base->global_randomize_case = 1; |
4892 | 0 | base->global_max_udp_size = DNS_MAX_UDP_SIZE; |
4893 | 0 | base->global_getaddrinfo_allow_skew.tv_sec = 3; |
4894 | 0 | base->global_getaddrinfo_allow_skew.tv_usec = 0; |
4895 | 0 | base->global_nameserver_probe_initial_timeout.tv_sec = 10; |
4896 | 0 | base->global_nameserver_probe_initial_timeout.tv_usec = 0; |
4897 | 0 | base->ns_max_probe_timeout = 3600; |
4898 | 0 | base->ns_timeout_backoff_factor = 3; |
4899 | 0 | base->global_tcp_idle_timeout.tv_sec = CLIENT_IDLE_CONN_TIMEOUT; |
4900 | |
|
4901 | 0 | TAILQ_INIT(&base->hostsdb); |
4902 | 0 | SPLAY_INIT(&base->cache_root); |
4903 | |
|
4904 | 0 | #define EVDNS_BASE_ALL_FLAGS ( \ |
4905 | 0 | EVDNS_BASE_INITIALIZE_NAMESERVERS | \ |
4906 | 0 | EVDNS_BASE_DISABLE_WHEN_INACTIVE | \ |
4907 | 0 | EVDNS_BASE_NAMESERVERS_NO_DEFAULT | \ |
4908 | 0 | EVDNS_BASE_NO_CACHE | \ |
4909 | 0 | 0) |
4910 | |
|
4911 | 0 | if (flags & ~EVDNS_BASE_ALL_FLAGS) { |
4912 | 0 | flags = EVDNS_BASE_INITIALIZE_NAMESERVERS; |
4913 | 0 | log(EVDNS_LOG_WARN, |
4914 | 0 | "Unrecognized flag passed to evdns_base_new(). Assuming " |
4915 | 0 | "you meant EVDNS_BASE_INITIALIZE_NAMESERVERS."); |
4916 | 0 | } |
4917 | 0 | #undef EVDNS_BASE_ALL_FLAGS |
4918 | |
|
4919 | 0 | if (flags & EVDNS_BASE_DISABLE_WHEN_INACTIVE) { |
4920 | 0 | base->disable_when_inactive = 1; |
4921 | 0 | } |
4922 | |
|
4923 | 0 | if (flags & EVDNS_BASE_INITIALIZE_NAMESERVERS) { |
4924 | 0 | int r; |
4925 | 0 | int opts = DNS_OPTIONS_ALL; |
4926 | 0 | if (flags & EVDNS_BASE_NAMESERVERS_NO_DEFAULT) { |
4927 | 0 | opts |= DNS_OPTION_NAMESERVERS_NO_DEFAULT; |
4928 | 0 | } |
4929 | |
|
4930 | | #ifdef _WIN32 |
4931 | | r = evdns_base_config_windows_nameservers(base); |
4932 | | #else |
4933 | 0 | r = evdns_base_resolv_conf_parse(base, opts, evutil_resolvconf_filename_()); |
4934 | 0 | #endif |
4935 | 0 | if (r && (EVDNS_ERROR_NO_NAMESERVERS_CONFIGURED != r)) { |
4936 | 0 | evdns_base_free_and_unlock(base, 0); |
4937 | 0 | return NULL; |
4938 | 0 | } |
4939 | 0 | } |
4940 | | |
4941 | 0 | base->disable_cache = flags & EVDNS_BASE_NO_CACHE; |
4942 | |
|
4943 | 0 | EVDNS_UNLOCK(base); |
4944 | 0 | return base; |
4945 | 0 | } |
4946 | | |
4947 | | int |
4948 | | evdns_init(void) |
4949 | 0 | { |
4950 | 0 | struct evdns_base *base = evdns_base_new(NULL, 1); |
4951 | 0 | if (base) { |
4952 | 0 | current_base = base; |
4953 | 0 | return 0; |
4954 | 0 | } else { |
4955 | 0 | return -1; |
4956 | 0 | } |
4957 | 0 | } |
4958 | | |
4959 | | const char * |
4960 | | evdns_err_to_string(int err) |
4961 | 0 | { |
4962 | 0 | switch (err) { |
4963 | 0 | case DNS_ERR_NONE: return "no error"; |
4964 | 0 | case DNS_ERR_FORMAT: return "misformatted query"; |
4965 | 0 | case DNS_ERR_SERVERFAILED: return "server failed"; |
4966 | 0 | case DNS_ERR_NOTEXIST: return "name does not exist"; |
4967 | 0 | case DNS_ERR_NOTIMPL: return "query not implemented"; |
4968 | 0 | case DNS_ERR_REFUSED: return "refused"; |
4969 | | |
4970 | 0 | case DNS_ERR_TRUNCATED: return "reply truncated or ill-formed"; |
4971 | 0 | case DNS_ERR_UNKNOWN: return "unknown"; |
4972 | 0 | case DNS_ERR_TIMEOUT: return "request timed out"; |
4973 | 0 | case DNS_ERR_SHUTDOWN: return "dns subsystem shut down"; |
4974 | 0 | case DNS_ERR_CANCEL: return "dns request canceled"; |
4975 | 0 | case DNS_ERR_NODATA: return "no records in the reply"; |
4976 | 0 | default: return "[Unknown error code]"; |
4977 | 0 | } |
4978 | 0 | } |
4979 | | |
4980 | | static void |
4981 | | evdns_nameserver_free(struct nameserver *server) |
4982 | 0 | { |
4983 | 0 | if (server->socket >= 0) |
4984 | 0 | evutil_closesocket(server->socket); |
4985 | 0 | (void) event_del(&server->event); |
4986 | 0 | event_debug_unassign(&server->event); |
4987 | 0 | if (server->state == 0) |
4988 | 0 | (void) event_del(&server->timeout_event); |
4989 | 0 | if (server->probe_request) { |
4990 | 0 | evdns_cancel_request(server->base, server->probe_request); |
4991 | 0 | server->probe_request = NULL; |
4992 | 0 | } |
4993 | 0 | event_debug_unassign(&server->timeout_event); |
4994 | 0 | disconnect_and_free_connection(server->connection); |
4995 | 0 | mm_free(server); |
4996 | 0 | } |
4997 | | |
4998 | | static int |
4999 | | evdns_cache_compare(struct evdns_cache *a, struct evdns_cache *b) |
5000 | 0 | { |
5001 | 0 | return strcasecmp(a->name, b->name); |
5002 | 0 | } |
5003 | | |
5004 | | SPLAY_PROTOTYPE(evdns_tree, evdns_cache, node, evdns_cache_compare); |
5005 | | SPLAY_GENERATE(evdns_tree, evdns_cache, node, evdns_cache_compare); |
5006 | | |
5007 | | static void |
5008 | | evdns_cache_free(struct evdns_cache *cache) |
5009 | 0 | { |
5010 | 0 | SPLAY_REMOVE(evdns_tree, &cache->base->cache_root, cache); |
5011 | 0 | mm_free(cache->name); |
5012 | 0 | evtimer_del(&cache->ev_timeout); |
5013 | 0 | evutil_freeaddrinfo(cache->ai); |
5014 | 0 | mm_free(cache); |
5015 | 0 | } |
5016 | | |
5017 | | static void |
5018 | | evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests) |
5019 | 0 | { |
5020 | 0 | struct nameserver *server, *server_next; |
5021 | 0 | struct search_domain *dom, *dom_next; |
5022 | 0 | int i; |
5023 | | |
5024 | | /* Requires that we hold the lock. */ |
5025 | | |
5026 | | /* TODO(nickm) we might need to refcount here. */ |
5027 | |
|
5028 | 0 | while (base->req_waiting_head) { |
5029 | 0 | if (fail_requests) |
5030 | 0 | reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL); |
5031 | 0 | request_finished(base->req_waiting_head, &base->req_waiting_head, 1); |
5032 | 0 | } |
5033 | 0 | for (i = 0; i < base->n_req_heads; ++i) { |
5034 | 0 | while (base->req_heads[i]) { |
5035 | 0 | if (fail_requests) |
5036 | 0 | reply_schedule_callback(base->req_heads[i], 0, DNS_ERR_SHUTDOWN, NULL); |
5037 | 0 | request_finished(base->req_heads[i], &REQ_HEAD(base, base->req_heads[i]->trans_id), 1); |
5038 | 0 | } |
5039 | 0 | } |
5040 | 0 | base->global_requests_inflight = base->global_requests_waiting = 0; |
5041 | |
|
5042 | 0 | for (server = base->server_head; server; server = server_next) { |
5043 | 0 | server_next = server->next; |
5044 | | /** already done something before */ |
5045 | 0 | server->probe_request = NULL; |
5046 | 0 | evdns_nameserver_free(server); |
5047 | 0 | if (server_next == base->server_head) |
5048 | 0 | break; |
5049 | 0 | } |
5050 | 0 | base->server_head = NULL; |
5051 | 0 | base->global_good_nameservers = 0; |
5052 | |
|
5053 | 0 | if (base->global_search_state) { |
5054 | 0 | for (dom = base->global_search_state->head; dom; dom = dom_next) { |
5055 | 0 | dom_next = dom->next; |
5056 | 0 | mm_free(dom); |
5057 | 0 | } |
5058 | 0 | mm_free(base->global_search_state); |
5059 | 0 | base->global_search_state = NULL; |
5060 | 0 | } |
5061 | |
|
5062 | 0 | { |
5063 | 0 | struct hosts_entry *victim; |
5064 | 0 | while ((victim = TAILQ_FIRST(&base->hostsdb))) { |
5065 | 0 | TAILQ_REMOVE(&base->hostsdb, victim, next); |
5066 | 0 | mm_free(victim); |
5067 | 0 | } |
5068 | 0 | } |
5069 | |
|
5070 | 0 | mm_free(base->req_heads); |
5071 | |
|
5072 | 0 | while (!SPLAY_EMPTY(&base->cache_root)) { |
5073 | 0 | evdns_cache_free(SPLAY_ROOT(&base->cache_root)); |
5074 | 0 | } |
5075 | |
|
5076 | 0 | EVDNS_UNLOCK(base); |
5077 | 0 | EVTHREAD_FREE_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); |
5078 | |
|
5079 | 0 | mm_free(base); |
5080 | 0 | } |
5081 | | |
5082 | | void |
5083 | | evdns_base_free(struct evdns_base *base, int fail_requests) |
5084 | 0 | { |
5085 | 0 | EVDNS_LOCK(base); |
5086 | 0 | evdns_base_free_and_unlock(base, fail_requests); |
5087 | 0 | } |
5088 | | |
5089 | | void |
5090 | | evdns_base_clear_host_addresses(struct evdns_base *base) |
5091 | 0 | { |
5092 | 0 | struct hosts_entry *victim; |
5093 | 0 | EVDNS_LOCK(base); |
5094 | 0 | while ((victim = TAILQ_FIRST(&base->hostsdb))) { |
5095 | 0 | TAILQ_REMOVE(&base->hostsdb, victim, next); |
5096 | 0 | mm_free(victim); |
5097 | 0 | } |
5098 | 0 | EVDNS_UNLOCK(base); |
5099 | 0 | } |
5100 | | |
5101 | | void |
5102 | | evdns_shutdown(int fail_requests) |
5103 | 0 | { |
5104 | 0 | if (current_base) { |
5105 | 0 | struct evdns_base *b = current_base; |
5106 | 0 | current_base = NULL; |
5107 | 0 | evdns_base_free(b, fail_requests); |
5108 | 0 | } |
5109 | 0 | evdns_log_fn = NULL; |
5110 | 0 | } |
5111 | | |
5112 | | static int |
5113 | | evdns_base_parse_hosts_line(struct evdns_base *base, char *line) |
5114 | 0 | { |
5115 | 0 | char *strtok_state; |
5116 | 0 | static const char *const delims = " \t"; |
5117 | 0 | char *const addr = strtok_r(line, delims, &strtok_state); |
5118 | 0 | char *hostname, *hash; |
5119 | 0 | struct sockaddr_storage ss; |
5120 | 0 | int socklen = sizeof(ss); |
5121 | 0 | ASSERT_LOCKED(base); |
5122 | |
|
5123 | 0 | #define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) |
5124 | |
|
5125 | 0 | if (!addr || *addr == '#') |
5126 | 0 | return 0; |
5127 | | |
5128 | 0 | memset(&ss, 0, sizeof(ss)); |
5129 | 0 | if (evutil_parse_sockaddr_port(addr, (struct sockaddr*)&ss, &socklen)<0) |
5130 | 0 | return -1; |
5131 | 0 | if (socklen > (int)sizeof(struct sockaddr_in6)) |
5132 | 0 | return -1; |
5133 | | |
5134 | 0 | if (sockaddr_getport((struct sockaddr*)&ss)) |
5135 | 0 | return -1; |
5136 | | |
5137 | 0 | while ((hostname = NEXT_TOKEN)) { |
5138 | 0 | struct hosts_entry *he; |
5139 | 0 | size_t namelen; |
5140 | 0 | if ((hash = strchr(hostname, '#'))) { |
5141 | 0 | if (hash == hostname) |
5142 | 0 | return 0; |
5143 | 0 | *hash = '\0'; |
5144 | 0 | } |
5145 | | |
5146 | 0 | namelen = strlen(hostname); |
5147 | |
|
5148 | 0 | he = mm_calloc(1, sizeof(struct hosts_entry)+namelen); |
5149 | 0 | if (!he) |
5150 | 0 | return -1; |
5151 | 0 | EVUTIL_ASSERT(socklen <= (int)sizeof(he->addr)); |
5152 | 0 | memcpy(&he->addr, &ss, socklen); |
5153 | 0 | memcpy(he->hostname, hostname, namelen+1); |
5154 | 0 | he->addrlen = socklen; |
5155 | |
|
5156 | 0 | TAILQ_INSERT_TAIL(&base->hostsdb, he, next); |
5157 | |
|
5158 | 0 | if (hash) |
5159 | 0 | return 0; |
5160 | 0 | } |
5161 | | |
5162 | 0 | return 0; |
5163 | 0 | #undef NEXT_TOKEN |
5164 | 0 | } |
5165 | | |
5166 | | static int |
5167 | | evdns_base_load_hosts_impl(struct evdns_base *base, const char *hosts_fname) |
5168 | 0 | { |
5169 | 0 | char *str=NULL, *cp, *eol; |
5170 | 0 | size_t len; |
5171 | 0 | int err=0; |
5172 | |
|
5173 | 0 | ASSERT_LOCKED(base); |
5174 | |
|
5175 | 0 | if (hosts_fname == NULL || |
5176 | 0 | (err = evutil_read_file_(hosts_fname, &str, &len, 0)) < 0) { |
5177 | 0 | char tmp[64]; |
5178 | 0 | strlcpy(tmp, "127.0.0.1 localhost", sizeof(tmp)); |
5179 | 0 | evdns_base_parse_hosts_line(base, tmp); |
5180 | 0 | strlcpy(tmp, "::1 localhost", sizeof(tmp)); |
5181 | 0 | evdns_base_parse_hosts_line(base, tmp); |
5182 | 0 | return err ? -1 : 0; |
5183 | 0 | } |
5184 | | |
5185 | | /* This will break early if there is a NUL in the hosts file. |
5186 | | * Probably not a problem.*/ |
5187 | 0 | cp = str; |
5188 | 0 | for (;;) { |
5189 | 0 | eol = strchr(cp, '\n'); |
5190 | |
|
5191 | 0 | if (eol) { |
5192 | 0 | *eol = '\0'; |
5193 | 0 | evdns_base_parse_hosts_line(base, cp); |
5194 | 0 | cp = eol+1; |
5195 | 0 | } else { |
5196 | 0 | evdns_base_parse_hosts_line(base, cp); |
5197 | 0 | break; |
5198 | 0 | } |
5199 | 0 | } |
5200 | |
|
5201 | 0 | mm_free(str); |
5202 | 0 | return 0; |
5203 | 0 | } |
5204 | | |
5205 | | int |
5206 | | evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname) |
5207 | 0 | { |
5208 | 0 | int res; |
5209 | 0 | if (!base) |
5210 | 0 | base = current_base; |
5211 | 0 | EVDNS_LOCK(base); |
5212 | 0 | res = evdns_base_load_hosts_impl(base, hosts_fname); |
5213 | 0 | EVDNS_UNLOCK(base); |
5214 | 0 | return res; |
5215 | 0 | } |
5216 | | |
5217 | | /* A single request for a getaddrinfo, either v4 or v6. */ |
5218 | | struct getaddrinfo_subrequest { |
5219 | | struct evdns_request *r; |
5220 | | ev_uint32_t type; |
5221 | | }; |
5222 | | |
5223 | | /* State data used to implement an in-progress getaddrinfo. */ |
5224 | | struct evdns_getaddrinfo_request { |
5225 | | struct evdns_base *evdns_base; |
5226 | | /* Copy of the modified 'hints' data that we'll use to build |
5227 | | * answers. */ |
5228 | | struct evutil_addrinfo hints; |
5229 | | /* The original requested nodename */ |
5230 | | char *nodename; |
5231 | | /* The callback to invoke when we're done */ |
5232 | | evdns_getaddrinfo_cb user_cb; |
5233 | | /* User-supplied data to give to the callback. */ |
5234 | | void *user_data; |
5235 | | /* The port to use when building sockaddrs. */ |
5236 | | ev_uint16_t port; |
5237 | | /* The sub_request for an A record (if any) */ |
5238 | | struct getaddrinfo_subrequest ipv4_request; |
5239 | | /* The sub_request for an AAAA record (if any) */ |
5240 | | struct getaddrinfo_subrequest ipv6_request; |
5241 | | |
5242 | | /* The cname result that we were told (if any) */ |
5243 | | char *cname_result; |
5244 | | |
5245 | | /* If we have one request answered and one request still inflight, |
5246 | | * then this field holds the answer from the first request... */ |
5247 | | struct evutil_addrinfo *pending_result; |
5248 | | int pending_result_ttl; |
5249 | | /* And this event is a timeout that will tell us to cancel the second |
5250 | | * request if it's taking a long time. */ |
5251 | | struct event timeout; |
5252 | | |
5253 | | /* And this field holds the error code from the first request... */ |
5254 | | int pending_error; |
5255 | | /* If this is set, the user canceled this request. */ |
5256 | | unsigned user_canceled : 1; |
5257 | | /* If this is set, the user can no longer cancel this request; we're |
5258 | | * just waiting for the free. */ |
5259 | | unsigned request_done : 1; |
5260 | | }; |
5261 | | |
5262 | | /* Convert an evdns errors to the equivalent getaddrinfo error. */ |
5263 | | static int |
5264 | | evdns_err_to_getaddrinfo_err(int e1) |
5265 | 0 | { |
5266 | | /* XXX Do this better! */ |
5267 | 0 | if (e1 == DNS_ERR_NONE) |
5268 | 0 | return 0; |
5269 | 0 | else if (e1 == DNS_ERR_NOTEXIST) |
5270 | 0 | return EVUTIL_EAI_NONAME; |
5271 | 0 | else |
5272 | 0 | return EVUTIL_EAI_FAIL; |
5273 | 0 | } |
5274 | | |
5275 | | /* Return the more informative of two getaddrinfo errors. */ |
5276 | | static int |
5277 | | getaddrinfo_merge_err(int e1, int e2) |
5278 | 0 | { |
5279 | | /* XXXX be cleverer here. */ |
5280 | 0 | if (e1 == 0) |
5281 | 0 | return e2; |
5282 | 0 | else |
5283 | 0 | return e1; |
5284 | 0 | } |
5285 | | |
5286 | | static void |
5287 | | free_getaddrinfo_request(struct evdns_getaddrinfo_request *data) |
5288 | 0 | { |
5289 | | /* DO NOT CALL this if either of the requests is pending. Only once |
5290 | | * both callbacks have been invoked is it safe to free the request */ |
5291 | 0 | if (data->pending_result) |
5292 | 0 | evutil_freeaddrinfo(data->pending_result); |
5293 | 0 | if (data->cname_result) |
5294 | 0 | mm_free(data->cname_result); |
5295 | 0 | event_del(&data->timeout); |
5296 | 0 | mm_free(data->nodename); |
5297 | 0 | mm_free(data); |
5298 | 0 | return; |
5299 | 0 | } |
5300 | | |
5301 | | static void |
5302 | | add_cname_to_reply(struct evdns_getaddrinfo_request *data, |
5303 | | struct evutil_addrinfo *ai) |
5304 | 0 | { |
5305 | 0 | if (data->cname_result && ai) { |
5306 | 0 | ai->ai_canonname = data->cname_result; |
5307 | 0 | data->cname_result = NULL; |
5308 | 0 | } |
5309 | 0 | } |
5310 | | |
5311 | | /* Callback: invoked when one request in a mixed-format A/AAAA getaddrinfo |
5312 | | * request has finished, but the other one took too long to answer. Pass |
5313 | | * along the answer we got, and cancel the other request. |
5314 | | */ |
5315 | | static void |
5316 | | evdns_getaddrinfo_timeout_cb(evutil_socket_t fd, short what, void *ptr) |
5317 | 0 | { |
5318 | 0 | int v4_timedout = 0, v6_timedout = 0; |
5319 | 0 | struct evdns_getaddrinfo_request *data = ptr; |
5320 | | |
5321 | | /* Cancel any pending requests, and note which one */ |
5322 | 0 | if (data->ipv4_request.r) { |
5323 | | /* XXXX This does nothing if the request's callback is already |
5324 | | * running (pending_cb is set). */ |
5325 | 0 | evdns_cancel_request(NULL, data->ipv4_request.r); |
5326 | 0 | v4_timedout = 1; |
5327 | 0 | EVDNS_LOCK(data->evdns_base); |
5328 | 0 | ++data->evdns_base->getaddrinfo_ipv4_timeouts; |
5329 | 0 | EVDNS_UNLOCK(data->evdns_base); |
5330 | 0 | } |
5331 | 0 | if (data->ipv6_request.r) { |
5332 | | /* XXXX This does nothing if the request's callback is already |
5333 | | * running (pending_cb is set). */ |
5334 | 0 | evdns_cancel_request(NULL, data->ipv6_request.r); |
5335 | 0 | v6_timedout = 1; |
5336 | 0 | EVDNS_LOCK(data->evdns_base); |
5337 | 0 | ++data->evdns_base->getaddrinfo_ipv6_timeouts; |
5338 | 0 | EVDNS_UNLOCK(data->evdns_base); |
5339 | 0 | } |
5340 | | |
5341 | | /* We only use this timeout callback when we have an answer for |
5342 | | * one address. */ |
5343 | 0 | EVUTIL_ASSERT(!v4_timedout || !v6_timedout); |
5344 | | |
5345 | | /* Report the outcome of the other request that didn't time out. */ |
5346 | 0 | if (data->pending_result) { |
5347 | 0 | add_cname_to_reply(data, data->pending_result); |
5348 | 0 | data->user_cb(0, data->pending_result, data->user_data); |
5349 | 0 | data->pending_result = NULL; |
5350 | 0 | } else { |
5351 | 0 | int e = data->pending_error; |
5352 | 0 | if (!e) |
5353 | 0 | e = EVUTIL_EAI_AGAIN; |
5354 | 0 | data->user_cb(e, NULL, data->user_data); |
5355 | 0 | } |
5356 | |
|
5357 | 0 | data->user_cb = NULL; /* prevent double-call if evdns callbacks are |
5358 | | * in-progress. XXXX It would be better if this |
5359 | | * weren't necessary. */ |
5360 | |
|
5361 | 0 | if (!v4_timedout && !v6_timedout) { |
5362 | | /* should be impossible? XXXX */ |
5363 | 0 | free_getaddrinfo_request(data); |
5364 | 0 | } |
5365 | 0 | } |
5366 | | |
5367 | | static int |
5368 | | evdns_getaddrinfo_set_timeout(struct evdns_base *evdns_base, |
5369 | | struct evdns_getaddrinfo_request *data) |
5370 | 0 | { |
5371 | 0 | return event_add(&data->timeout, &evdns_base->global_getaddrinfo_allow_skew); |
5372 | 0 | } |
5373 | | |
5374 | | static inline int |
5375 | | evdns_result_is_answer(int result) |
5376 | 0 | { |
5377 | 0 | return (result != DNS_ERR_NOTIMPL && result != DNS_ERR_REFUSED && |
5378 | 0 | result != DNS_ERR_SERVERFAILED && result != DNS_ERR_CANCEL); |
5379 | 0 | } |
5380 | | |
5381 | | static void |
5382 | | evdns_ttl_expired(evutil_socket_t fd, short what, void *arg) |
5383 | 0 | { |
5384 | 0 | struct evdns_cache *cache = arg; |
5385 | 0 | struct evdns_base *base = cache->base; |
5386 | 0 | log(EVDNS_LOG_DEBUG, "Expiring cache for %s", cache->name); |
5387 | 0 | EVDNS_LOCK(base); |
5388 | 0 | evdns_cache_free(cache); |
5389 | 0 | EVDNS_UNLOCK(base); |
5390 | 0 | } |
5391 | | |
5392 | | void |
5393 | | evdns_cache_write(struct evdns_base *dns_base, char *nodename, struct evutil_addrinfo *res, int ttl) |
5394 | 0 | { |
5395 | 0 | struct timeval tv; |
5396 | 0 | struct evdns_cache *cache; |
5397 | 0 | struct evdns_cache find; |
5398 | |
|
5399 | 0 | log(EVDNS_LOG_DEBUG, "Writing cache for %s", nodename); |
5400 | 0 | EVDNS_LOCK(dns_base); |
5401 | 0 | find.name = (char *)nodename; |
5402 | 0 | cache = SPLAY_FIND(evdns_tree, &dns_base->cache_root, &find); |
5403 | 0 | if (cache) { |
5404 | 0 | log(EVDNS_LOG_DEBUG, "Ejecting old cache for %s", nodename); |
5405 | 0 | evdns_cache_free(cache); |
5406 | 0 | } |
5407 | 0 | if (res) { |
5408 | 0 | cache = mm_calloc(1, sizeof(struct evdns_cache)); |
5409 | 0 | cache->base = dns_base; |
5410 | 0 | cache->name = mm_strdup(nodename); |
5411 | 0 | cache->ai = evutil_dup_addrinfo_(res); |
5412 | 0 | SPLAY_INSERT(evdns_tree, &cache->base->cache_root, cache); |
5413 | 0 | evtimer_assign(&cache->ev_timeout, dns_base->event_base, evdns_ttl_expired, cache); |
5414 | 0 | timerclear(&tv); |
5415 | 0 | tv.tv_sec = ttl; |
5416 | 0 | evtimer_add(&cache->ev_timeout, &tv); |
5417 | 0 | } |
5418 | 0 | EVDNS_UNLOCK(dns_base); |
5419 | 0 | } |
5420 | | |
5421 | | int |
5422 | | evdns_cache_lookup(struct evdns_base *base, |
5423 | | const char *nodename, struct evutil_addrinfo *hints, ev_uint16_t port, |
5424 | | struct evutil_addrinfo **res) |
5425 | 0 | { |
5426 | 0 | int n_found = 0; |
5427 | 0 | struct evdns_cache *cache; |
5428 | 0 | struct evdns_cache find; |
5429 | 0 | struct evutil_addrinfo *ai = NULL; |
5430 | 0 | int want_cname = hints->ai_flags & EVUTIL_AI_CANONNAME; |
5431 | 0 | int f = hints->ai_family; |
5432 | |
|
5433 | 0 | log(EVDNS_LOG_DEBUG, "Looking in cache for %s", nodename); |
5434 | 0 | EVDNS_LOCK(base); |
5435 | 0 | find.name = (char *)nodename; |
5436 | 0 | cache = SPLAY_FIND(evdns_tree, &base->cache_root, &find); |
5437 | 0 | if (cache) { |
5438 | 0 | struct evutil_addrinfo *e = cache->ai; |
5439 | 0 | log(EVDNS_LOG_DEBUG, "Found cache for %s", cache->name); |
5440 | 0 | for (; e; e = e->ai_next) { |
5441 | 0 | struct evutil_addrinfo *ai_new; |
5442 | | // an existing record might not have the canonname |
5443 | 0 | if (want_cname && e->ai_canonname == NULL) |
5444 | 0 | continue; |
5445 | 0 | ++n_found; |
5446 | 0 | if ((e->ai_addr->sa_family == AF_INET && f == PF_INET6) || |
5447 | 0 | (e->ai_addr->sa_family == AF_INET6 && f == PF_INET)) |
5448 | 0 | continue; |
5449 | 0 | ai_new = evutil_new_addrinfo_(e->ai_addr, e->ai_addrlen, hints); |
5450 | 0 | if (!ai_new) { |
5451 | 0 | n_found = 0; |
5452 | 0 | goto out; |
5453 | 0 | } |
5454 | 0 | if (want_cname) { |
5455 | 0 | ai_new->ai_canonname = mm_strdup(e->ai_canonname); |
5456 | 0 | } |
5457 | 0 | sockaddr_setport(ai_new->ai_addr, port); |
5458 | 0 | ai = evutil_addrinfo_append_(ai, ai_new); |
5459 | 0 | } |
5460 | 0 | } |
5461 | 0 | EVDNS_UNLOCK(base); |
5462 | 0 | out: |
5463 | 0 | if (n_found) { |
5464 | 0 | if (!ai) { |
5465 | 0 | return EVUTIL_EAI_ADDRFAMILY; |
5466 | 0 | } |
5467 | 0 | *res = ai; |
5468 | 0 | return 0; |
5469 | 0 | } else { |
5470 | 0 | if (ai) |
5471 | 0 | evutil_freeaddrinfo(ai); |
5472 | 0 | return -1; |
5473 | 0 | } |
5474 | 0 | } |
5475 | | |
5476 | | static void |
5477 | | evdns_getaddrinfo_gotresolve(int result, char type, int count, |
5478 | | int ttl, void *addresses, void *arg) |
5479 | 0 | { |
5480 | 0 | int i; |
5481 | 0 | struct getaddrinfo_subrequest *req = arg; |
5482 | 0 | struct getaddrinfo_subrequest *other_req; |
5483 | 0 | struct evdns_getaddrinfo_request *data; |
5484 | |
|
5485 | 0 | struct evutil_addrinfo *res; |
5486 | |
|
5487 | 0 | struct sockaddr_in sin; |
5488 | 0 | struct sockaddr_in6 sin6; |
5489 | 0 | struct sockaddr *sa; |
5490 | 0 | int socklen, addrlen; |
5491 | 0 | void *addrp; |
5492 | 0 | int err; |
5493 | 0 | int user_canceled; |
5494 | |
|
5495 | 0 | EVUTIL_ASSERT(req->type == DNS_IPv4_A || req->type == DNS_IPv6_AAAA); |
5496 | 0 | if (req->type == DNS_IPv4_A) { |
5497 | 0 | data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv4_request); |
5498 | 0 | other_req = &data->ipv6_request; |
5499 | 0 | } else { |
5500 | 0 | data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv6_request); |
5501 | 0 | other_req = &data->ipv4_request; |
5502 | 0 | } |
5503 | | |
5504 | | /** Called from evdns_base_free() with @fail_requests == 1 */ |
5505 | 0 | if (result != DNS_ERR_SHUTDOWN) { |
5506 | 0 | EVDNS_LOCK(data->evdns_base); |
5507 | 0 | if (evdns_result_is_answer(result)) { |
5508 | 0 | if (req->type == DNS_IPv4_A) |
5509 | 0 | ++data->evdns_base->getaddrinfo_ipv4_answered; |
5510 | 0 | else |
5511 | 0 | ++data->evdns_base->getaddrinfo_ipv6_answered; |
5512 | 0 | } |
5513 | 0 | user_canceled = data->user_canceled; |
5514 | 0 | if (other_req->r == NULL) |
5515 | 0 | data->request_done = 1; |
5516 | 0 | EVDNS_UNLOCK(data->evdns_base); |
5517 | 0 | } else { |
5518 | 0 | data->evdns_base = NULL; |
5519 | 0 | user_canceled = data->user_canceled; |
5520 | 0 | } |
5521 | |
|
5522 | 0 | req->r = NULL; |
5523 | |
|
5524 | 0 | if (result == DNS_ERR_CANCEL && ! user_canceled) { |
5525 | | /* Internal cancel request from timeout or internal error. |
5526 | | * we already answered the user. */ |
5527 | 0 | if (other_req->r == NULL) |
5528 | 0 | free_getaddrinfo_request(data); |
5529 | 0 | return; |
5530 | 0 | } |
5531 | | |
5532 | 0 | if (data->user_cb == NULL) { |
5533 | | /* We already answered. XXXX This shouldn't be needed; see |
5534 | | * comments in evdns_getaddrinfo_timeout_cb */ |
5535 | 0 | free_getaddrinfo_request(data); |
5536 | 0 | return; |
5537 | 0 | } |
5538 | | |
5539 | 0 | if (result == DNS_ERR_NONE) { |
5540 | 0 | if (count == 0) |
5541 | 0 | err = EVUTIL_EAI_NODATA; |
5542 | 0 | else |
5543 | 0 | err = 0; |
5544 | 0 | } else { |
5545 | 0 | err = evdns_err_to_getaddrinfo_err(result); |
5546 | 0 | } |
5547 | |
|
5548 | 0 | if (err) { |
5549 | | /* Looks like we got an error. */ |
5550 | 0 | if (other_req->r) { |
5551 | | /* The other request is still working; maybe it will |
5552 | | * succeed. */ |
5553 | | /* XXXX handle failure from set_timeout */ |
5554 | 0 | if (result != DNS_ERR_SHUTDOWN) { |
5555 | 0 | evdns_getaddrinfo_set_timeout(data->evdns_base, data); |
5556 | 0 | } |
5557 | 0 | data->pending_error = err; |
5558 | 0 | return; |
5559 | 0 | } |
5560 | | |
5561 | 0 | if (user_canceled) { |
5562 | 0 | data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); |
5563 | 0 | } else if (data->pending_result) { |
5564 | | /* If we have an answer waiting, and we weren't |
5565 | | * canceled, ignore this error. */ |
5566 | 0 | add_cname_to_reply(data, data->pending_result); |
5567 | 0 | if (data->evdns_base && !data->evdns_base->disable_cache) { |
5568 | 0 | evdns_cache_write(data->evdns_base, data->nodename, data->pending_result, data->pending_result_ttl); |
5569 | 0 | } |
5570 | 0 | data->user_cb(0, data->pending_result, data->user_data); |
5571 | 0 | data->pending_result = NULL; |
5572 | 0 | } else { |
5573 | 0 | if (data->pending_error) |
5574 | 0 | err = getaddrinfo_merge_err(err, |
5575 | 0 | data->pending_error); |
5576 | 0 | data->user_cb(err, NULL, data->user_data); |
5577 | 0 | } |
5578 | 0 | free_getaddrinfo_request(data); |
5579 | 0 | return; |
5580 | 0 | } else if (user_canceled) { |
5581 | 0 | if (other_req->r) { |
5582 | | /* The other request is still working; let it hit this |
5583 | | * callback with EVUTIL_EAI_CANCEL callback and report |
5584 | | * the failure. */ |
5585 | 0 | return; |
5586 | 0 | } |
5587 | 0 | data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); |
5588 | 0 | free_getaddrinfo_request(data); |
5589 | 0 | return; |
5590 | 0 | } |
5591 | | |
5592 | | /* Looks like we got some answers. We should turn them into addrinfos |
5593 | | * and then either queue those or return them all. */ |
5594 | 0 | EVUTIL_ASSERT(type == DNS_IPv4_A || type == DNS_IPv6_AAAA); |
5595 | |
|
5596 | 0 | if (type == DNS_IPv4_A) { |
5597 | 0 | memset(&sin, 0, sizeof(sin)); |
5598 | 0 | sin.sin_family = AF_INET; |
5599 | 0 | sin.sin_port = htons(data->port); |
5600 | | #ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN |
5601 | | sin.sin_len = sizeof(sin); |
5602 | | #endif |
5603 | |
|
5604 | 0 | sa = (struct sockaddr *)&sin; |
5605 | 0 | socklen = sizeof(sin); |
5606 | 0 | addrlen = 4; |
5607 | 0 | addrp = &sin.sin_addr.s_addr; |
5608 | 0 | } else { |
5609 | 0 | memset(&sin6, 0, sizeof(sin6)); |
5610 | 0 | sin6.sin6_family = AF_INET6; |
5611 | 0 | sin6.sin6_port = htons(data->port); |
5612 | | #ifdef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN |
5613 | | sin6.sin6_len = sizeof(sin6); |
5614 | | #endif |
5615 | |
|
5616 | 0 | sa = (struct sockaddr *)&sin6; |
5617 | 0 | socklen = sizeof(sin6); |
5618 | 0 | addrlen = 16; |
5619 | 0 | addrp = &sin6.sin6_addr.s6_addr; |
5620 | 0 | } |
5621 | |
|
5622 | 0 | res = NULL; |
5623 | 0 | for (i=0; i < count; ++i) { |
5624 | 0 | struct evutil_addrinfo *ai; |
5625 | 0 | memcpy(addrp, ((char*)addresses)+i*addrlen, addrlen); |
5626 | 0 | ai = evutil_new_addrinfo_(sa, socklen, &data->hints); |
5627 | 0 | if (!ai) { |
5628 | 0 | if (other_req->r) { |
5629 | 0 | evdns_cancel_request(NULL, other_req->r); |
5630 | 0 | } |
5631 | 0 | data->user_cb(EVUTIL_EAI_MEMORY, NULL, data->user_data); |
5632 | 0 | if (res) |
5633 | 0 | evutil_freeaddrinfo(res); |
5634 | |
|
5635 | 0 | if (other_req->r == NULL) |
5636 | 0 | free_getaddrinfo_request(data); |
5637 | 0 | return; |
5638 | 0 | } |
5639 | 0 | res = evutil_addrinfo_append_(res, ai); |
5640 | 0 | } |
5641 | | |
5642 | 0 | if (other_req->r) { |
5643 | | /* The other request is still in progress; wait for it */ |
5644 | | /* XXXX handle failure from set_timeout */ |
5645 | 0 | evdns_getaddrinfo_set_timeout(data->evdns_base, data); |
5646 | 0 | data->pending_result = res; |
5647 | 0 | data->pending_result_ttl = ttl; |
5648 | 0 | return; |
5649 | 0 | } else { |
5650 | | /* The other request is done or never started; append its |
5651 | | * results (if any) and return them. */ |
5652 | 0 | int res_ttl = ttl; |
5653 | 0 | if (data->pending_result) { |
5654 | 0 | if (req->type == DNS_IPv4_A) |
5655 | 0 | res = evutil_addrinfo_append_(res, |
5656 | 0 | data->pending_result); |
5657 | 0 | else |
5658 | 0 | res = evutil_addrinfo_append_( |
5659 | 0 | data->pending_result, res); |
5660 | 0 | res_ttl = data->pending_result_ttl; |
5661 | 0 | data->pending_result = NULL; |
5662 | 0 | } |
5663 | | |
5664 | | /* Call the user callback. */ |
5665 | 0 | add_cname_to_reply(data, res); |
5666 | 0 | if (data->evdns_base && !data->evdns_base->disable_cache) { |
5667 | 0 | evdns_cache_write(data->evdns_base, data->nodename, res, res_ttl); |
5668 | 0 | } |
5669 | 0 | data->user_cb(0, res, data->user_data); |
5670 | | |
5671 | | /* Free data. */ |
5672 | 0 | free_getaddrinfo_request(data); |
5673 | 0 | } |
5674 | 0 | } |
5675 | | |
5676 | | static struct hosts_entry * |
5677 | | find_hosts_entry(struct evdns_base *base, const char *hostname, |
5678 | | struct hosts_entry *find_after) |
5679 | 0 | { |
5680 | 0 | struct hosts_entry *e; |
5681 | |
|
5682 | 0 | if (find_after) |
5683 | 0 | e = TAILQ_NEXT(find_after, next); |
5684 | 0 | else |
5685 | 0 | e = TAILQ_FIRST(&base->hostsdb); |
5686 | |
|
5687 | 0 | for (; e; e = TAILQ_NEXT(e, next)) { |
5688 | 0 | if (!evutil_ascii_strcasecmp(e->hostname, hostname)) |
5689 | 0 | return e; |
5690 | 0 | } |
5691 | 0 | return NULL; |
5692 | 0 | } |
5693 | | |
5694 | | static int |
5695 | | evdns_getaddrinfo_fromhosts(struct evdns_base *base, |
5696 | | const char *nodename, struct evutil_addrinfo *hints, ev_uint16_t port, |
5697 | | struct evutil_addrinfo **res) |
5698 | 0 | { |
5699 | 0 | int n_found = 0; |
5700 | 0 | struct hosts_entry *e; |
5701 | 0 | struct evutil_addrinfo *ai = NULL; |
5702 | 0 | int f = hints->ai_family; |
5703 | |
|
5704 | 0 | EVDNS_LOCK(base); |
5705 | 0 | for (e = find_hosts_entry(base, nodename, NULL); e; |
5706 | 0 | e = find_hosts_entry(base, nodename, e)) { |
5707 | 0 | struct evutil_addrinfo *ai_new; |
5708 | 0 | ++n_found; |
5709 | 0 | if ((e->addr.sa.sa_family == AF_INET && f == PF_INET6) || |
5710 | 0 | (e->addr.sa.sa_family == AF_INET6 && f == PF_INET)) |
5711 | 0 | continue; |
5712 | 0 | ai_new = evutil_new_addrinfo_(&e->addr.sa, e->addrlen, hints); |
5713 | 0 | if (!ai_new) { |
5714 | 0 | n_found = 0; |
5715 | 0 | goto out; |
5716 | 0 | } |
5717 | 0 | sockaddr_setport(ai_new->ai_addr, port); |
5718 | 0 | ai = evutil_addrinfo_append_(ai, ai_new); |
5719 | 0 | } |
5720 | 0 | EVDNS_UNLOCK(base); |
5721 | 0 | out: |
5722 | 0 | if (n_found) { |
5723 | 0 | if (!ai) { |
5724 | 0 | return EVUTIL_EAI_ADDRFAMILY; |
5725 | 0 | } |
5726 | 0 | *res = ai; |
5727 | 0 | return 0; |
5728 | 0 | } else { |
5729 | 0 | if (ai) |
5730 | 0 | evutil_freeaddrinfo(ai); |
5731 | 0 | return -1; |
5732 | 0 | } |
5733 | 0 | } |
5734 | | |
5735 | | struct evdns_getaddrinfo_request * |
5736 | | evdns_getaddrinfo(struct evdns_base *dns_base, |
5737 | | const char *nodename, const char *servname, |
5738 | | const struct evutil_addrinfo *hints_in, |
5739 | | evdns_getaddrinfo_cb cb, void *arg) |
5740 | 0 | { |
5741 | 0 | struct evdns_getaddrinfo_request *data; |
5742 | 0 | struct evutil_addrinfo hints; |
5743 | 0 | struct evutil_addrinfo *res = NULL; |
5744 | 0 | int err; |
5745 | 0 | int port = 0; |
5746 | 0 | int want_cname = 0; |
5747 | 0 | int started = 0; |
5748 | |
|
5749 | 0 | if (!dns_base) { |
5750 | 0 | dns_base = current_base; |
5751 | 0 | if (!dns_base) { |
5752 | 0 | log(EVDNS_LOG_WARN, |
5753 | 0 | "Call to getaddrinfo_async with no " |
5754 | 0 | "evdns_base configured."); |
5755 | 0 | cb(EVUTIL_EAI_FAIL, NULL, arg); /* ??? better error? */ |
5756 | 0 | return NULL; |
5757 | 0 | } |
5758 | 0 | } |
5759 | | |
5760 | | /* If we _must_ answer this immediately, do so. */ |
5761 | 0 | if ((hints_in && (hints_in->ai_flags & EVUTIL_AI_NUMERICHOST))) { |
5762 | 0 | res = NULL; |
5763 | 0 | err = evutil_getaddrinfo(nodename, servname, hints_in, &res); |
5764 | 0 | cb(err, res, arg); |
5765 | 0 | return NULL; |
5766 | 0 | } |
5767 | | |
5768 | 0 | if (hints_in) { |
5769 | 0 | memcpy(&hints, hints_in, sizeof(hints)); |
5770 | 0 | } else { |
5771 | 0 | memset(&hints, 0, sizeof(hints)); |
5772 | 0 | hints.ai_family = PF_UNSPEC; |
5773 | 0 | } |
5774 | |
|
5775 | 0 | evutil_adjust_hints_for_addrconfig_(&hints); |
5776 | | |
5777 | | /* Now try to see if we _can_ answer immediately. */ |
5778 | | /* (It would be nice to do this by calling getaddrinfo directly, with |
5779 | | * AI_NUMERICHOST, on platforms that have it, but we can't: there isn't |
5780 | | * a reliable way to distinguish the "that wasn't a numeric host!" case |
5781 | | * from any other EAI_NONAME cases.) */ |
5782 | 0 | err = evutil_getaddrinfo_common_(nodename, servname, &hints, &res, &port); |
5783 | 0 | if (err != EVUTIL_EAI_NEED_RESOLVE) { |
5784 | 0 | cb(err, res, arg); |
5785 | 0 | return NULL; |
5786 | 0 | } |
5787 | | |
5788 | | /* If there is an entry in the hosts file, we should give it now. */ |
5789 | 0 | err = evdns_getaddrinfo_fromhosts(dns_base, nodename, &hints, port, &res); |
5790 | 0 | if (!err || err == EVUTIL_EAI_ADDRFAMILY) { |
5791 | 0 | cb(err, res, arg); |
5792 | 0 | return NULL; |
5793 | 0 | } |
5794 | | |
5795 | | /* See if we have it in the cache */ |
5796 | 0 | if (!dns_base->disable_cache) { |
5797 | 0 | err = evdns_cache_lookup(dns_base, nodename, &hints, port, &res); |
5798 | 0 | if (!err || err == EVUTIL_EAI_ADDRFAMILY) { |
5799 | 0 | cb(err, res, arg); |
5800 | 0 | return NULL; |
5801 | 0 | } |
5802 | 0 | } |
5803 | | |
5804 | | /* Okay, things are serious now. We're going to need to actually |
5805 | | * launch a request. |
5806 | | */ |
5807 | 0 | data = mm_calloc(1,sizeof(struct evdns_getaddrinfo_request)); |
5808 | 0 | if (!data) { |
5809 | 0 | cb(EVUTIL_EAI_MEMORY, NULL, arg); |
5810 | 0 | return NULL; |
5811 | 0 | } |
5812 | | |
5813 | 0 | memcpy(&data->hints, &hints, sizeof(data->hints)); |
5814 | 0 | data->port = (ev_uint16_t)port; |
5815 | 0 | data->ipv4_request.type = DNS_IPv4_A; |
5816 | 0 | data->ipv6_request.type = DNS_IPv6_AAAA; |
5817 | 0 | data->user_cb = cb; |
5818 | 0 | data->user_data = arg; |
5819 | 0 | data->evdns_base = dns_base; |
5820 | 0 | data->nodename = mm_strdup(nodename); |
5821 | |
|
5822 | 0 | want_cname = (hints.ai_flags & EVUTIL_AI_CANONNAME); |
5823 | | |
5824 | | /* If we are asked for a PF_UNSPEC address, we launch two requests in |
5825 | | * parallel: one for an A address and one for an AAAA address. We |
5826 | | * can't send just one request, since many servers only answer one |
5827 | | * question per DNS request. |
5828 | | * |
5829 | | * Once we have the answer to one request, we allow for a short |
5830 | | * timeout before we report it, to see if the other one arrives. If |
5831 | | * they both show up in time, then we report both the answers. |
5832 | | * |
5833 | | * If too many addresses of one type time out or fail, we should stop |
5834 | | * launching those requests. (XXX we don't do that yet.) |
5835 | | */ |
5836 | |
|
5837 | 0 | EVDNS_LOCK(dns_base); |
5838 | |
|
5839 | 0 | if (hints.ai_family != PF_INET6) { |
5840 | 0 | log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p", |
5841 | 0 | nodename, (void *)&data->ipv4_request); |
5842 | |
|
5843 | 0 | data->ipv4_request.r = evdns_base_resolve_ipv4(dns_base, |
5844 | 0 | nodename, 0, evdns_getaddrinfo_gotresolve, |
5845 | 0 | &data->ipv4_request); |
5846 | 0 | if (want_cname && data->ipv4_request.r) |
5847 | 0 | data->ipv4_request.r->current_req->put_cname_in_ptr = |
5848 | 0 | &data->cname_result; |
5849 | 0 | } |
5850 | 0 | if (hints.ai_family != PF_INET) { |
5851 | 0 | log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv6 as %p", |
5852 | 0 | nodename, (void *)&data->ipv6_request); |
5853 | |
|
5854 | 0 | data->ipv6_request.r = evdns_base_resolve_ipv6(dns_base, |
5855 | 0 | nodename, 0, evdns_getaddrinfo_gotresolve, |
5856 | 0 | &data->ipv6_request); |
5857 | 0 | if (want_cname && data->ipv6_request.r) |
5858 | 0 | data->ipv6_request.r->current_req->put_cname_in_ptr = |
5859 | 0 | &data->cname_result; |
5860 | 0 | } |
5861 | |
|
5862 | 0 | evtimer_assign(&data->timeout, dns_base->event_base, |
5863 | 0 | evdns_getaddrinfo_timeout_cb, data); |
5864 | |
|
5865 | 0 | started = (data->ipv4_request.r || data->ipv6_request.r); |
5866 | |
|
5867 | 0 | EVDNS_UNLOCK(dns_base); |
5868 | |
|
5869 | 0 | if (started) { |
5870 | 0 | return data; |
5871 | 0 | } else { |
5872 | 0 | free_getaddrinfo_request(data); |
5873 | 0 | cb(EVUTIL_EAI_FAIL, NULL, arg); |
5874 | 0 | return NULL; |
5875 | 0 | } |
5876 | 0 | } |
5877 | | |
5878 | | void |
5879 | | evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *data) |
5880 | 0 | { |
5881 | 0 | EVDNS_LOCK(data->evdns_base); |
5882 | 0 | if (data->request_done) { |
5883 | 0 | EVDNS_UNLOCK(data->evdns_base); |
5884 | 0 | return; |
5885 | 0 | } |
5886 | 0 | event_del(&data->timeout); |
5887 | 0 | data->user_canceled = 1; |
5888 | 0 | if (data->ipv4_request.r) |
5889 | 0 | evdns_cancel_request(data->evdns_base, data->ipv4_request.r); |
5890 | 0 | if (data->ipv6_request.r) |
5891 | 0 | evdns_cancel_request(data->evdns_base, data->ipv6_request.r); |
5892 | 0 | EVDNS_UNLOCK(data->evdns_base); |
5893 | 0 | } |