LCOV - code coverage report
Current view: top level - ipc/chromium/src/third_party/libevent - evdns.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 2133 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 140 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13