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  | }  |