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