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