1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/evdns.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,4655 @@ 1.4 +/* Copyright 2006-2007 Niels Provos 1.5 + * Copyright 2007-2012 Nick Mathewson and Niels Provos 1.6 + * 1.7 + * Redistribution and use in source and binary forms, with or without 1.8 + * modification, are permitted provided that the following conditions 1.9 + * are met: 1.10 + * 1. Redistributions of source code must retain the above copyright 1.11 + * notice, this list of conditions and the following disclaimer. 1.12 + * 2. Redistributions in binary form must reproduce the above copyright 1.13 + * notice, this list of conditions and the following disclaimer in the 1.14 + * documentation and/or other materials provided with the distribution. 1.15 + * 3. The name of the author may not be used to endorse or promote products 1.16 + * derived from this software without specific prior written permission. 1.17 + * 1.18 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.19 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.20 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.21 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.22 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.23 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.24 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.25 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.26 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.27 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.28 + */ 1.29 + 1.30 +/* Based on software by Adam Langly. Adam's original message: 1.31 + * 1.32 + * Async DNS Library 1.33 + * Adam Langley <agl@imperialviolet.org> 1.34 + * http://www.imperialviolet.org/eventdns.html 1.35 + * Public Domain code 1.36 + * 1.37 + * This software is Public Domain. To view a copy of the public domain dedication, 1.38 + * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to 1.39 + * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. 1.40 + * 1.41 + * I ask and expect, but do not require, that all derivative works contain an 1.42 + * attribution similar to: 1.43 + * Parts developed by Adam Langley <agl@imperialviolet.org> 1.44 + * 1.45 + * You may wish to replace the word "Parts" with something else depending on 1.46 + * the amount of original code. 1.47 + * 1.48 + * (Derivative works does not include programs which link against, run or include 1.49 + * the source verbatim in their source distributions) 1.50 + * 1.51 + * Version: 0.1b 1.52 + */ 1.53 + 1.54 +#include <sys/types.h> 1.55 +#include "event2/event-config.h" 1.56 + 1.57 +#ifndef _FORTIFY_SOURCE 1.58 +#define _FORTIFY_SOURCE 3 1.59 +#endif 1.60 + 1.61 +#include <string.h> 1.62 +#include <fcntl.h> 1.63 +#ifdef _EVENT_HAVE_SYS_TIME_H 1.64 +#include <sys/time.h> 1.65 +#endif 1.66 +#ifdef _EVENT_HAVE_STDINT_H 1.67 +#include <stdint.h> 1.68 +#endif 1.69 +#include <stdlib.h> 1.70 +#include <string.h> 1.71 +#include <errno.h> 1.72 +#ifdef _EVENT_HAVE_UNISTD_H 1.73 +#include <unistd.h> 1.74 +#endif 1.75 +#include <limits.h> 1.76 +#include <sys/stat.h> 1.77 +#include <stdio.h> 1.78 +#include <stdarg.h> 1.79 +#ifdef WIN32 1.80 +#include <winsock2.h> 1.81 +#include <ws2tcpip.h> 1.82 +#ifndef _WIN32_IE 1.83 +#define _WIN32_IE 0x400 1.84 +#endif 1.85 +#include <shlobj.h> 1.86 +#endif 1.87 + 1.88 +#include "event2/dns.h" 1.89 +#include "event2/dns_struct.h" 1.90 +#include "event2/dns_compat.h" 1.91 +#include "event2/util.h" 1.92 +#include "event2/event.h" 1.93 +#include "event2/event_struct.h" 1.94 +#include "event2/thread.h" 1.95 + 1.96 +#include "event2/bufferevent.h" 1.97 +#include "event2/bufferevent_struct.h" 1.98 +#include "bufferevent-internal.h" 1.99 + 1.100 +#include "defer-internal.h" 1.101 +#include "log-internal.h" 1.102 +#include "mm-internal.h" 1.103 +#include "strlcpy-internal.h" 1.104 +#include "ipv6-internal.h" 1.105 +#include "util-internal.h" 1.106 +#include "evthread-internal.h" 1.107 +#ifdef WIN32 1.108 +#include <ctype.h> 1.109 +#include <winsock2.h> 1.110 +#include <windows.h> 1.111 +#include <iphlpapi.h> 1.112 +#include <io.h> 1.113 +#else 1.114 +#include <sys/socket.h> 1.115 +#include <netinet/in.h> 1.116 +#include <arpa/inet.h> 1.117 +#endif 1.118 + 1.119 +#ifdef _EVENT_HAVE_NETINET_IN6_H 1.120 +#include <netinet/in6.h> 1.121 +#endif 1.122 + 1.123 +#define EVDNS_LOG_DEBUG 0 1.124 +#define EVDNS_LOG_WARN 1 1.125 +#define EVDNS_LOG_MSG 2 1.126 + 1.127 +#ifndef HOST_NAME_MAX 1.128 +#define HOST_NAME_MAX 255 1.129 +#endif 1.130 + 1.131 +#include <stdio.h> 1.132 + 1.133 +#undef MIN 1.134 +#define MIN(a,b) ((a)<(b)?(a):(b)) 1.135 + 1.136 +#define ASSERT_VALID_REQUEST(req) \ 1.137 + EVUTIL_ASSERT((req)->handle && (req)->handle->current_req == (req)) 1.138 + 1.139 +#define u64 ev_uint64_t 1.140 +#define u32 ev_uint32_t 1.141 +#define u16 ev_uint16_t 1.142 +#define u8 ev_uint8_t 1.143 + 1.144 +/* maximum number of addresses from a single packet */ 1.145 +/* that we bother recording */ 1.146 +#define MAX_V4_ADDRS 32 1.147 +#define MAX_V6_ADDRS 32 1.148 + 1.149 + 1.150 +#define TYPE_A EVDNS_TYPE_A 1.151 +#define TYPE_CNAME 5 1.152 +#define TYPE_PTR EVDNS_TYPE_PTR 1.153 +#define TYPE_SOA EVDNS_TYPE_SOA 1.154 +#define TYPE_AAAA EVDNS_TYPE_AAAA 1.155 + 1.156 +#define CLASS_INET EVDNS_CLASS_INET 1.157 + 1.158 +/* Persistent handle. We keep this separate from 'struct request' since we 1.159 + * need some object to last for as long as an evdns_request is outstanding so 1.160 + * that it can be canceled, whereas a search request can lead to multiple 1.161 + * 'struct request' instances being created over its lifetime. */ 1.162 +struct evdns_request { 1.163 + struct request *current_req; 1.164 + struct evdns_base *base; 1.165 + 1.166 + int pending_cb; /* Waiting for its callback to be invoked; not 1.167 + * owned by event base any more. */ 1.168 + 1.169 + /* elements used by the searching code */ 1.170 + int search_index; 1.171 + struct search_state *search_state; 1.172 + char *search_origname; /* needs to be free()ed */ 1.173 + int search_flags; 1.174 +}; 1.175 + 1.176 +struct request { 1.177 + u8 *request; /* the dns packet data */ 1.178 + u8 request_type; /* TYPE_PTR or TYPE_A or TYPE_AAAA */ 1.179 + unsigned int request_len; 1.180 + int reissue_count; 1.181 + int tx_count; /* the number of times that this packet has been sent */ 1.182 + void *user_pointer; /* the pointer given to us for this request */ 1.183 + evdns_callback_type user_callback; 1.184 + struct nameserver *ns; /* the server which we last sent it */ 1.185 + 1.186 + /* these objects are kept in a circular list */ 1.187 + /* XXX We could turn this into a CIRCLEQ. */ 1.188 + struct request *next, *prev; 1.189 + 1.190 + struct event timeout_event; 1.191 + 1.192 + u16 trans_id; /* the transaction id */ 1.193 + unsigned request_appended :1; /* true if the request pointer is data which follows this struct */ 1.194 + unsigned transmit_me :1; /* needs to be transmitted */ 1.195 + 1.196 + /* XXXX This is a horrible hack. */ 1.197 + char **put_cname_in_ptr; /* store the cname here if we get one. */ 1.198 + 1.199 + struct evdns_base *base; 1.200 + 1.201 + struct evdns_request *handle; 1.202 +}; 1.203 + 1.204 +struct reply { 1.205 + unsigned int type; 1.206 + unsigned int have_answer : 1; 1.207 + union { 1.208 + struct { 1.209 + u32 addrcount; 1.210 + u32 addresses[MAX_V4_ADDRS]; 1.211 + } a; 1.212 + struct { 1.213 + u32 addrcount; 1.214 + struct in6_addr addresses[MAX_V6_ADDRS]; 1.215 + } aaaa; 1.216 + struct { 1.217 + char name[HOST_NAME_MAX]; 1.218 + } ptr; 1.219 + } data; 1.220 +}; 1.221 + 1.222 +struct nameserver { 1.223 + evutil_socket_t socket; /* a connected UDP socket */ 1.224 + struct sockaddr_storage address; 1.225 + ev_socklen_t addrlen; 1.226 + int failed_times; /* number of times which we have given this server a chance */ 1.227 + int timedout; /* number of times in a row a request has timed out */ 1.228 + struct event event; 1.229 + /* these objects are kept in a circular list */ 1.230 + struct nameserver *next, *prev; 1.231 + struct event timeout_event; /* used to keep the timeout for */ 1.232 + /* when we next probe this server. */ 1.233 + /* Valid if state == 0 */ 1.234 + /* Outstanding probe request for this nameserver, if any */ 1.235 + struct evdns_request *probe_request; 1.236 + char state; /* zero if we think that this server is down */ 1.237 + char choked; /* true if we have an EAGAIN from this server's socket */ 1.238 + char write_waiting; /* true if we are waiting for EV_WRITE events */ 1.239 + struct evdns_base *base; 1.240 +}; 1.241 + 1.242 + 1.243 +/* Represents a local port where we're listening for DNS requests. Right now, */ 1.244 +/* only UDP is supported. */ 1.245 +struct evdns_server_port { 1.246 + evutil_socket_t socket; /* socket we use to read queries and write replies. */ 1.247 + int refcnt; /* reference count. */ 1.248 + char choked; /* Are we currently blocked from writing? */ 1.249 + char closing; /* Are we trying to close this port, pending writes? */ 1.250 + evdns_request_callback_fn_type user_callback; /* Fn to handle requests */ 1.251 + void *user_data; /* Opaque pointer passed to user_callback */ 1.252 + struct event event; /* Read/write event */ 1.253 + /* circular list of replies that we want to write. */ 1.254 + struct server_request *pending_replies; 1.255 + struct event_base *event_base; 1.256 + 1.257 +#ifndef _EVENT_DISABLE_THREAD_SUPPORT 1.258 + void *lock; 1.259 +#endif 1.260 +}; 1.261 + 1.262 +/* Represents part of a reply being built. (That is, a single RR.) */ 1.263 +struct server_reply_item { 1.264 + struct server_reply_item *next; /* next item in sequence. */ 1.265 + char *name; /* name part of the RR */ 1.266 + u16 type; /* The RR type */ 1.267 + u16 class; /* The RR class (usually CLASS_INET) */ 1.268 + u32 ttl; /* The RR TTL */ 1.269 + char is_name; /* True iff data is a label */ 1.270 + u16 datalen; /* Length of data; -1 if data is a label */ 1.271 + void *data; /* The contents of the RR */ 1.272 +}; 1.273 + 1.274 +/* Represents a request that we've received as a DNS server, and holds */ 1.275 +/* the components of the reply as we're constructing it. */ 1.276 +struct server_request { 1.277 + /* Pointers to the next and previous entries on the list of replies */ 1.278 + /* that we're waiting to write. Only set if we have tried to respond */ 1.279 + /* and gotten EAGAIN. */ 1.280 + struct server_request *next_pending; 1.281 + struct server_request *prev_pending; 1.282 + 1.283 + u16 trans_id; /* Transaction id. */ 1.284 + struct evdns_server_port *port; /* Which port received this request on? */ 1.285 + struct sockaddr_storage addr; /* Where to send the response */ 1.286 + ev_socklen_t addrlen; /* length of addr */ 1.287 + 1.288 + int n_answer; /* how many answer RRs have been set? */ 1.289 + int n_authority; /* how many authority RRs have been set? */ 1.290 + int n_additional; /* how many additional RRs have been set? */ 1.291 + 1.292 + struct server_reply_item *answer; /* linked list of answer RRs */ 1.293 + struct server_reply_item *authority; /* linked list of authority RRs */ 1.294 + struct server_reply_item *additional; /* linked list of additional RRs */ 1.295 + 1.296 + /* Constructed response. Only set once we're ready to send a reply. */ 1.297 + /* Once this is set, the RR fields are cleared, and no more should be set. */ 1.298 + char *response; 1.299 + size_t response_len; 1.300 + 1.301 + /* Caller-visible fields: flags, questions. */ 1.302 + struct evdns_server_request base; 1.303 +}; 1.304 + 1.305 +struct evdns_base { 1.306 + /* An array of n_req_heads circular lists for inflight requests. 1.307 + * Each inflight request req is in req_heads[req->trans_id % n_req_heads]. 1.308 + */ 1.309 + struct request **req_heads; 1.310 + /* A circular list of requests that we're waiting to send, but haven't 1.311 + * sent yet because there are too many requests inflight */ 1.312 + struct request *req_waiting_head; 1.313 + /* A circular list of nameservers. */ 1.314 + struct nameserver *server_head; 1.315 + int n_req_heads; 1.316 + 1.317 + struct event_base *event_base; 1.318 + 1.319 + /* The number of good nameservers that we have */ 1.320 + int global_good_nameservers; 1.321 + 1.322 + /* inflight requests are contained in the req_head list */ 1.323 + /* and are actually going out across the network */ 1.324 + int global_requests_inflight; 1.325 + /* requests which aren't inflight are in the waiting list */ 1.326 + /* and are counted here */ 1.327 + int global_requests_waiting; 1.328 + 1.329 + int global_max_requests_inflight; 1.330 + 1.331 + struct timeval global_timeout; /* 5 seconds by default */ 1.332 + int global_max_reissues; /* a reissue occurs when we get some errors from the server */ 1.333 + int global_max_retransmits; /* number of times we'll retransmit a request which timed out */ 1.334 + /* number of timeouts in a row before we consider this server to be down */ 1.335 + int global_max_nameserver_timeout; 1.336 + /* true iff we will use the 0x20 hack to prevent poisoning attacks. */ 1.337 + int global_randomize_case; 1.338 + 1.339 + /* The first time that a nameserver fails, how long do we wait before 1.340 + * probing to see if it has returned? */ 1.341 + struct timeval global_nameserver_probe_initial_timeout; 1.342 + 1.343 + /** Port to bind to for outgoing DNS packets. */ 1.344 + struct sockaddr_storage global_outgoing_address; 1.345 + /** ev_socklen_t for global_outgoing_address. 0 if it isn't set. */ 1.346 + ev_socklen_t global_outgoing_addrlen; 1.347 + 1.348 + struct timeval global_getaddrinfo_allow_skew; 1.349 + 1.350 + int getaddrinfo_ipv4_timeouts; 1.351 + int getaddrinfo_ipv6_timeouts; 1.352 + int getaddrinfo_ipv4_answered; 1.353 + int getaddrinfo_ipv6_answered; 1.354 + 1.355 + struct search_state *global_search_state; 1.356 + 1.357 + TAILQ_HEAD(hosts_list, hosts_entry) hostsdb; 1.358 + 1.359 +#ifndef _EVENT_DISABLE_THREAD_SUPPORT 1.360 + void *lock; 1.361 +#endif 1.362 +}; 1.363 + 1.364 +struct hosts_entry { 1.365 + TAILQ_ENTRY(hosts_entry) next; 1.366 + union { 1.367 + struct sockaddr sa; 1.368 + struct sockaddr_in sin; 1.369 + struct sockaddr_in6 sin6; 1.370 + } addr; 1.371 + int addrlen; 1.372 + char hostname[1]; 1.373 +}; 1.374 + 1.375 +static struct evdns_base *current_base = NULL; 1.376 + 1.377 +struct evdns_base * 1.378 +evdns_get_global_base(void) 1.379 +{ 1.380 + return current_base; 1.381 +} 1.382 + 1.383 +/* Given a pointer to an evdns_server_request, get the corresponding */ 1.384 +/* server_request. */ 1.385 +#define TO_SERVER_REQUEST(base_ptr) \ 1.386 + ((struct server_request*) \ 1.387 + (((char*)(base_ptr) - evutil_offsetof(struct server_request, base)))) 1.388 + 1.389 +#define REQ_HEAD(base, id) ((base)->req_heads[id % (base)->n_req_heads]) 1.390 + 1.391 +static struct nameserver *nameserver_pick(struct evdns_base *base); 1.392 +static void evdns_request_insert(struct request *req, struct request **head); 1.393 +static void evdns_request_remove(struct request *req, struct request **head); 1.394 +static void nameserver_ready_callback(evutil_socket_t fd, short events, void *arg); 1.395 +static int evdns_transmit(struct evdns_base *base); 1.396 +static int evdns_request_transmit(struct request *req); 1.397 +static void nameserver_send_probe(struct nameserver *const ns); 1.398 +static void search_request_finished(struct evdns_request *const); 1.399 +static int search_try_next(struct evdns_request *const req); 1.400 +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); 1.401 +static void evdns_requests_pump_waiting_queue(struct evdns_base *base); 1.402 +static u16 transaction_id_pick(struct evdns_base *base); 1.403 +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); 1.404 +static void request_submit(struct request *const req); 1.405 + 1.406 +static int server_request_free(struct server_request *req); 1.407 +static void server_request_free_answers(struct server_request *req); 1.408 +static void server_port_free(struct evdns_server_port *port); 1.409 +static void server_port_ready_callback(evutil_socket_t fd, short events, void *arg); 1.410 +static int evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename); 1.411 +static int evdns_base_set_option_impl(struct evdns_base *base, 1.412 + const char *option, const char *val, int flags); 1.413 +static void evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests); 1.414 + 1.415 +static int strtoint(const char *const str); 1.416 + 1.417 +#ifdef _EVENT_DISABLE_THREAD_SUPPORT 1.418 +#define EVDNS_LOCK(base) _EVUTIL_NIL_STMT 1.419 +#define EVDNS_UNLOCK(base) _EVUTIL_NIL_STMT 1.420 +#define ASSERT_LOCKED(base) _EVUTIL_NIL_STMT 1.421 +#else 1.422 +#define EVDNS_LOCK(base) \ 1.423 + EVLOCK_LOCK((base)->lock, 0) 1.424 +#define EVDNS_UNLOCK(base) \ 1.425 + EVLOCK_UNLOCK((base)->lock, 0) 1.426 +#define ASSERT_LOCKED(base) \ 1.427 + EVLOCK_ASSERT_LOCKED((base)->lock) 1.428 +#endif 1.429 + 1.430 +static void 1.431 +default_evdns_log_fn(int warning, const char *buf) 1.432 +{ 1.433 + if (warning == EVDNS_LOG_WARN) 1.434 + event_warnx("[evdns] %s", buf); 1.435 + else if (warning == EVDNS_LOG_MSG) 1.436 + event_msgx("[evdns] %s", buf); 1.437 + else 1.438 + event_debug(("[evdns] %s", buf)); 1.439 +} 1.440 + 1.441 +static evdns_debug_log_fn_type evdns_log_fn = NULL; 1.442 + 1.443 +void 1.444 +evdns_set_log_fn(evdns_debug_log_fn_type fn) 1.445 +{ 1.446 + evdns_log_fn = fn; 1.447 +} 1.448 + 1.449 +#ifdef __GNUC__ 1.450 +#define EVDNS_LOG_CHECK __attribute__ ((format(printf, 2, 3))) 1.451 +#else 1.452 +#define EVDNS_LOG_CHECK 1.453 +#endif 1.454 + 1.455 +static void _evdns_log(int warn, const char *fmt, ...) EVDNS_LOG_CHECK; 1.456 +static void 1.457 +_evdns_log(int warn, const char *fmt, ...) 1.458 +{ 1.459 + va_list args; 1.460 + char buf[512]; 1.461 + if (!evdns_log_fn) 1.462 + return; 1.463 + va_start(args,fmt); 1.464 + evutil_vsnprintf(buf, sizeof(buf), fmt, args); 1.465 + va_end(args); 1.466 + if (evdns_log_fn) { 1.467 + if (warn == EVDNS_LOG_MSG) 1.468 + warn = EVDNS_LOG_WARN; 1.469 + evdns_log_fn(warn, buf); 1.470 + } else { 1.471 + default_evdns_log_fn(warn, buf); 1.472 + } 1.473 + 1.474 +} 1.475 + 1.476 +#define log _evdns_log 1.477 + 1.478 +/* This walks the list of inflight requests to find the */ 1.479 +/* one with a matching transaction id. Returns NULL on */ 1.480 +/* failure */ 1.481 +static struct request * 1.482 +request_find_from_trans_id(struct evdns_base *base, u16 trans_id) { 1.483 + struct request *req = REQ_HEAD(base, trans_id); 1.484 + struct request *const started_at = req; 1.485 + 1.486 + ASSERT_LOCKED(base); 1.487 + 1.488 + if (req) { 1.489 + do { 1.490 + if (req->trans_id == trans_id) return req; 1.491 + req = req->next; 1.492 + } while (req != started_at); 1.493 + } 1.494 + 1.495 + return NULL; 1.496 +} 1.497 + 1.498 +/* a libevent callback function which is called when a nameserver */ 1.499 +/* has gone down and we want to test if it has came back to life yet */ 1.500 +static void 1.501 +nameserver_prod_callback(evutil_socket_t fd, short events, void *arg) { 1.502 + struct nameserver *const ns = (struct nameserver *) arg; 1.503 + (void)fd; 1.504 + (void)events; 1.505 + 1.506 + EVDNS_LOCK(ns->base); 1.507 + nameserver_send_probe(ns); 1.508 + EVDNS_UNLOCK(ns->base); 1.509 +} 1.510 + 1.511 +/* a libevent callback which is called when a nameserver probe (to see if */ 1.512 +/* it has come back to life) times out. We increment the count of failed_times */ 1.513 +/* and wait longer to send the next probe packet. */ 1.514 +static void 1.515 +nameserver_probe_failed(struct nameserver *const ns) { 1.516 + struct timeval timeout; 1.517 + int i; 1.518 + 1.519 + ASSERT_LOCKED(ns->base); 1.520 + (void) evtimer_del(&ns->timeout_event); 1.521 + if (ns->state == 1) { 1.522 + /* This can happen if the nameserver acts in a way which makes us mark */ 1.523 + /* it as bad and then starts sending good replies. */ 1.524 + return; 1.525 + } 1.526 + 1.527 +#define MAX_PROBE_TIMEOUT 3600 1.528 +#define TIMEOUT_BACKOFF_FACTOR 3 1.529 + 1.530 + memcpy(&timeout, &ns->base->global_nameserver_probe_initial_timeout, 1.531 + sizeof(struct timeval)); 1.532 + for (i=ns->failed_times; i > 0 && timeout.tv_sec < MAX_PROBE_TIMEOUT; --i) { 1.533 + timeout.tv_sec *= TIMEOUT_BACKOFF_FACTOR; 1.534 + timeout.tv_usec *= TIMEOUT_BACKOFF_FACTOR; 1.535 + if (timeout.tv_usec > 1000000) { 1.536 + timeout.tv_sec += timeout.tv_usec / 1000000; 1.537 + timeout.tv_usec %= 1000000; 1.538 + } 1.539 + } 1.540 + if (timeout.tv_sec > MAX_PROBE_TIMEOUT) { 1.541 + timeout.tv_sec = MAX_PROBE_TIMEOUT; 1.542 + timeout.tv_usec = 0; 1.543 + } 1.544 + 1.545 + ns->failed_times++; 1.546 + 1.547 + if (evtimer_add(&ns->timeout_event, &timeout) < 0) { 1.548 + char addrbuf[128]; 1.549 + log(EVDNS_LOG_WARN, 1.550 + "Error from libevent when adding timer event for %s", 1.551 + evutil_format_sockaddr_port( 1.552 + (struct sockaddr *)&ns->address, 1.553 + addrbuf, sizeof(addrbuf))); 1.554 + } 1.555 +} 1.556 + 1.557 +/* called when a nameserver has been deemed to have failed. For example, too */ 1.558 +/* many packets have timed out etc */ 1.559 +static void 1.560 +nameserver_failed(struct nameserver *const ns, const char *msg) { 1.561 + struct request *req, *started_at; 1.562 + struct evdns_base *base = ns->base; 1.563 + int i; 1.564 + char addrbuf[128]; 1.565 + 1.566 + ASSERT_LOCKED(base); 1.567 + /* if this nameserver has already been marked as failed */ 1.568 + /* then don't do anything */ 1.569 + if (!ns->state) return; 1.570 + 1.571 + log(EVDNS_LOG_MSG, "Nameserver %s has failed: %s", 1.572 + evutil_format_sockaddr_port( 1.573 + (struct sockaddr *)&ns->address, 1.574 + addrbuf, sizeof(addrbuf)), 1.575 + msg); 1.576 + 1.577 + base->global_good_nameservers--; 1.578 + EVUTIL_ASSERT(base->global_good_nameservers >= 0); 1.579 + if (base->global_good_nameservers == 0) { 1.580 + log(EVDNS_LOG_MSG, "All nameservers have failed"); 1.581 + } 1.582 + 1.583 + ns->state = 0; 1.584 + ns->failed_times = 1; 1.585 + 1.586 + if (evtimer_add(&ns->timeout_event, 1.587 + &base->global_nameserver_probe_initial_timeout) < 0) { 1.588 + log(EVDNS_LOG_WARN, 1.589 + "Error from libevent when adding timer event for %s", 1.590 + evutil_format_sockaddr_port( 1.591 + (struct sockaddr *)&ns->address, 1.592 + addrbuf, sizeof(addrbuf))); 1.593 + /* ???? Do more? */ 1.594 + } 1.595 + 1.596 + /* walk the list of inflight requests to see if any can be reassigned to */ 1.597 + /* a different server. Requests in the waiting queue don't have a */ 1.598 + /* nameserver assigned yet */ 1.599 + 1.600 + /* if we don't have *any* good nameservers then there's no point */ 1.601 + /* trying to reassign requests to one */ 1.602 + if (!base->global_good_nameservers) return; 1.603 + 1.604 + for (i = 0; i < base->n_req_heads; ++i) { 1.605 + req = started_at = base->req_heads[i]; 1.606 + if (req) { 1.607 + do { 1.608 + if (req->tx_count == 0 && req->ns == ns) { 1.609 + /* still waiting to go out, can be moved */ 1.610 + /* to another server */ 1.611 + req->ns = nameserver_pick(base); 1.612 + } 1.613 + req = req->next; 1.614 + } while (req != started_at); 1.615 + } 1.616 + } 1.617 +} 1.618 + 1.619 +static void 1.620 +nameserver_up(struct nameserver *const ns) 1.621 +{ 1.622 + char addrbuf[128]; 1.623 + ASSERT_LOCKED(ns->base); 1.624 + if (ns->state) return; 1.625 + log(EVDNS_LOG_MSG, "Nameserver %s is back up", 1.626 + evutil_format_sockaddr_port( 1.627 + (struct sockaddr *)&ns->address, 1.628 + addrbuf, sizeof(addrbuf))); 1.629 + evtimer_del(&ns->timeout_event); 1.630 + if (ns->probe_request) { 1.631 + evdns_cancel_request(ns->base, ns->probe_request); 1.632 + ns->probe_request = NULL; 1.633 + } 1.634 + ns->state = 1; 1.635 + ns->failed_times = 0; 1.636 + ns->timedout = 0; 1.637 + ns->base->global_good_nameservers++; 1.638 +} 1.639 + 1.640 +static void 1.641 +request_trans_id_set(struct request *const req, const u16 trans_id) { 1.642 + req->trans_id = trans_id; 1.643 + *((u16 *) req->request) = htons(trans_id); 1.644 +} 1.645 + 1.646 +/* Called to remove a request from a list and dealloc it. */ 1.647 +/* head is a pointer to the head of the list it should be */ 1.648 +/* removed from or NULL if the request isn't in a list. */ 1.649 +/* when free_handle is one, free the handle as well. */ 1.650 +static void 1.651 +request_finished(struct request *const req, struct request **head, int free_handle) { 1.652 + struct evdns_base *base = req->base; 1.653 + int was_inflight = (head != &base->req_waiting_head); 1.654 + EVDNS_LOCK(base); 1.655 + ASSERT_VALID_REQUEST(req); 1.656 + 1.657 + if (head) 1.658 + evdns_request_remove(req, head); 1.659 + 1.660 + log(EVDNS_LOG_DEBUG, "Removing timeout for request %p", req); 1.661 + if (was_inflight) { 1.662 + evtimer_del(&req->timeout_event); 1.663 + base->global_requests_inflight--; 1.664 + } else { 1.665 + base->global_requests_waiting--; 1.666 + } 1.667 + /* it was initialized during request_new / evtimer_assign */ 1.668 + event_debug_unassign(&req->timeout_event); 1.669 + 1.670 + if (!req->request_appended) { 1.671 + /* need to free the request data on it's own */ 1.672 + mm_free(req->request); 1.673 + } else { 1.674 + /* the request data is appended onto the header */ 1.675 + /* so everything gets free()ed when we: */ 1.676 + } 1.677 + 1.678 + if (req->handle) { 1.679 + EVUTIL_ASSERT(req->handle->current_req == req); 1.680 + 1.681 + if (free_handle) { 1.682 + search_request_finished(req->handle); 1.683 + req->handle->current_req = NULL; 1.684 + if (! req->handle->pending_cb) { 1.685 + /* If we're planning to run the callback, 1.686 + * don't free the handle until later. */ 1.687 + mm_free(req->handle); 1.688 + } 1.689 + req->handle = NULL; /* If we have a bug, let's crash 1.690 + * early */ 1.691 + } else { 1.692 + req->handle->current_req = NULL; 1.693 + } 1.694 + } 1.695 + 1.696 + mm_free(req); 1.697 + 1.698 + evdns_requests_pump_waiting_queue(base); 1.699 + EVDNS_UNLOCK(base); 1.700 +} 1.701 + 1.702 +/* This is called when a server returns a funny error code. */ 1.703 +/* We try the request again with another server. */ 1.704 +/* */ 1.705 +/* return: */ 1.706 +/* 0 ok */ 1.707 +/* 1 failed/reissue is pointless */ 1.708 +static int 1.709 +request_reissue(struct request *req) { 1.710 + const struct nameserver *const last_ns = req->ns; 1.711 + ASSERT_LOCKED(req->base); 1.712 + ASSERT_VALID_REQUEST(req); 1.713 + /* the last nameserver should have been marked as failing */ 1.714 + /* by the caller of this function, therefore pick will try */ 1.715 + /* not to return it */ 1.716 + req->ns = nameserver_pick(req->base); 1.717 + if (req->ns == last_ns) { 1.718 + /* ... but pick did return it */ 1.719 + /* not a lot of point in trying again with the */ 1.720 + /* same server */ 1.721 + return 1; 1.722 + } 1.723 + 1.724 + req->reissue_count++; 1.725 + req->tx_count = 0; 1.726 + req->transmit_me = 1; 1.727 + 1.728 + return 0; 1.729 +} 1.730 + 1.731 +/* this function looks for space on the inflight queue and promotes */ 1.732 +/* requests from the waiting queue if it can. */ 1.733 +static void 1.734 +evdns_requests_pump_waiting_queue(struct evdns_base *base) { 1.735 + ASSERT_LOCKED(base); 1.736 + while (base->global_requests_inflight < base->global_max_requests_inflight && 1.737 + base->global_requests_waiting) { 1.738 + struct request *req; 1.739 + /* move a request from the waiting queue to the inflight queue */ 1.740 + EVUTIL_ASSERT(base->req_waiting_head); 1.741 + req = base->req_waiting_head; 1.742 + evdns_request_remove(req, &base->req_waiting_head); 1.743 + 1.744 + base->global_requests_waiting--; 1.745 + base->global_requests_inflight++; 1.746 + 1.747 + req->ns = nameserver_pick(base); 1.748 + request_trans_id_set(req, transaction_id_pick(base)); 1.749 + 1.750 + evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); 1.751 + evdns_request_transmit(req); 1.752 + evdns_transmit(base); 1.753 + } 1.754 +} 1.755 + 1.756 +/* TODO(nickm) document */ 1.757 +struct deferred_reply_callback { 1.758 + struct deferred_cb deferred; 1.759 + struct evdns_request *handle; 1.760 + u8 request_type; 1.761 + u8 have_reply; 1.762 + u32 ttl; 1.763 + u32 err; 1.764 + evdns_callback_type user_callback; 1.765 + struct reply reply; 1.766 +}; 1.767 + 1.768 +static void 1.769 +reply_run_callback(struct deferred_cb *d, void *user_pointer) 1.770 +{ 1.771 + struct deferred_reply_callback *cb = 1.772 + EVUTIL_UPCAST(d, struct deferred_reply_callback, deferred); 1.773 + 1.774 + switch (cb->request_type) { 1.775 + case TYPE_A: 1.776 + if (cb->have_reply) 1.777 + cb->user_callback(DNS_ERR_NONE, DNS_IPv4_A, 1.778 + cb->reply.data.a.addrcount, cb->ttl, 1.779 + cb->reply.data.a.addresses, 1.780 + user_pointer); 1.781 + else 1.782 + cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); 1.783 + break; 1.784 + case TYPE_PTR: 1.785 + if (cb->have_reply) { 1.786 + char *name = cb->reply.data.ptr.name; 1.787 + cb->user_callback(DNS_ERR_NONE, DNS_PTR, 1, cb->ttl, 1.788 + &name, user_pointer); 1.789 + } else { 1.790 + cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); 1.791 + } 1.792 + break; 1.793 + case TYPE_AAAA: 1.794 + if (cb->have_reply) 1.795 + cb->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA, 1.796 + cb->reply.data.aaaa.addrcount, cb->ttl, 1.797 + cb->reply.data.aaaa.addresses, 1.798 + user_pointer); 1.799 + else 1.800 + cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); 1.801 + break; 1.802 + default: 1.803 + EVUTIL_ASSERT(0); 1.804 + } 1.805 + 1.806 + if (cb->handle && cb->handle->pending_cb) { 1.807 + mm_free(cb->handle); 1.808 + } 1.809 + 1.810 + mm_free(cb); 1.811 +} 1.812 + 1.813 +static void 1.814 +reply_schedule_callback(struct request *const req, u32 ttl, u32 err, struct reply *reply) 1.815 +{ 1.816 + struct deferred_reply_callback *d = mm_calloc(1, sizeof(*d)); 1.817 + 1.818 + if (!d) { 1.819 + event_warn("%s: Couldn't allocate space for deferred callback.", 1.820 + __func__); 1.821 + return; 1.822 + } 1.823 + 1.824 + ASSERT_LOCKED(req->base); 1.825 + 1.826 + d->request_type = req->request_type; 1.827 + d->user_callback = req->user_callback; 1.828 + d->ttl = ttl; 1.829 + d->err = err; 1.830 + if (reply) { 1.831 + d->have_reply = 1; 1.832 + memcpy(&d->reply, reply, sizeof(struct reply)); 1.833 + } 1.834 + 1.835 + if (req->handle) { 1.836 + req->handle->pending_cb = 1; 1.837 + d->handle = req->handle; 1.838 + } 1.839 + 1.840 + event_deferred_cb_init(&d->deferred, reply_run_callback, 1.841 + req->user_pointer); 1.842 + event_deferred_cb_schedule( 1.843 + event_base_get_deferred_cb_queue(req->base->event_base), 1.844 + &d->deferred); 1.845 +} 1.846 + 1.847 +/* this processes a parsed reply packet */ 1.848 +static void 1.849 +reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) { 1.850 + int error; 1.851 + char addrbuf[128]; 1.852 + static const int error_codes[] = { 1.853 + DNS_ERR_FORMAT, DNS_ERR_SERVERFAILED, DNS_ERR_NOTEXIST, 1.854 + DNS_ERR_NOTIMPL, DNS_ERR_REFUSED 1.855 + }; 1.856 + 1.857 + ASSERT_LOCKED(req->base); 1.858 + ASSERT_VALID_REQUEST(req); 1.859 + 1.860 + if (flags & 0x020f || !reply || !reply->have_answer) { 1.861 + /* there was an error */ 1.862 + if (flags & 0x0200) { 1.863 + error = DNS_ERR_TRUNCATED; 1.864 + } else if (flags & 0x000f) { 1.865 + u16 error_code = (flags & 0x000f) - 1; 1.866 + if (error_code > 4) { 1.867 + error = DNS_ERR_UNKNOWN; 1.868 + } else { 1.869 + error = error_codes[error_code]; 1.870 + } 1.871 + } else if (reply && !reply->have_answer) { 1.872 + error = DNS_ERR_NODATA; 1.873 + } else { 1.874 + error = DNS_ERR_UNKNOWN; 1.875 + } 1.876 + 1.877 + switch (error) { 1.878 + case DNS_ERR_NOTIMPL: 1.879 + case DNS_ERR_REFUSED: 1.880 + /* we regard these errors as marking a bad nameserver */ 1.881 + if (req->reissue_count < req->base->global_max_reissues) { 1.882 + char msg[64]; 1.883 + evutil_snprintf(msg, sizeof(msg), "Bad response %d (%s)", 1.884 + error, evdns_err_to_string(error)); 1.885 + nameserver_failed(req->ns, msg); 1.886 + if (!request_reissue(req)) return; 1.887 + } 1.888 + break; 1.889 + case DNS_ERR_SERVERFAILED: 1.890 + /* rcode 2 (servfailed) sometimes means "we 1.891 + * are broken" and sometimes (with some binds) 1.892 + * means "that request was very confusing." 1.893 + * Treat this as a timeout, not a failure. 1.894 + */ 1.895 + log(EVDNS_LOG_DEBUG, "Got a SERVERFAILED from nameserver" 1.896 + "at %s; will allow the request to time out.", 1.897 + evutil_format_sockaddr_port( 1.898 + (struct sockaddr *)&req->ns->address, 1.899 + addrbuf, sizeof(addrbuf))); 1.900 + break; 1.901 + default: 1.902 + /* we got a good reply from the nameserver: it is up. */ 1.903 + if (req->handle == req->ns->probe_request) { 1.904 + /* Avoid double-free */ 1.905 + req->ns->probe_request = NULL; 1.906 + } 1.907 + 1.908 + nameserver_up(req->ns); 1.909 + } 1.910 + 1.911 + if (req->handle->search_state && 1.912 + req->request_type != TYPE_PTR) { 1.913 + /* if we have a list of domains to search in, 1.914 + * try the next one */ 1.915 + if (!search_try_next(req->handle)) { 1.916 + /* a new request was issued so this 1.917 + * request is finished and */ 1.918 + /* the user callback will be made when 1.919 + * that request (or a */ 1.920 + /* child of it) finishes. */ 1.921 + return; 1.922 + } 1.923 + } 1.924 + 1.925 + /* all else failed. Pass the failure up */ 1.926 + reply_schedule_callback(req, ttl, error, NULL); 1.927 + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); 1.928 + } else { 1.929 + /* all ok, tell the user */ 1.930 + reply_schedule_callback(req, ttl, 0, reply); 1.931 + if (req->handle == req->ns->probe_request) 1.932 + req->ns->probe_request = NULL; /* Avoid double-free */ 1.933 + nameserver_up(req->ns); 1.934 + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); 1.935 + } 1.936 +} 1.937 + 1.938 +static int 1.939 +name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) { 1.940 + int name_end = -1; 1.941 + int j = *idx; 1.942 + int ptr_count = 0; 1.943 +#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while (0) 1.944 +#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while (0) 1.945 +#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while (0) 1.946 + 1.947 + char *cp = name_out; 1.948 + const char *const end = name_out + name_out_len; 1.949 + 1.950 + /* Normally, names are a series of length prefixed strings terminated */ 1.951 + /* with a length of 0 (the lengths are u8's < 63). */ 1.952 + /* However, the length can start with a pair of 1 bits and that */ 1.953 + /* means that the next 14 bits are a pointer within the current */ 1.954 + /* packet. */ 1.955 + 1.956 + for (;;) { 1.957 + u8 label_len; 1.958 + if (j >= length) return -1; 1.959 + GET8(label_len); 1.960 + if (!label_len) break; 1.961 + if (label_len & 0xc0) { 1.962 + u8 ptr_low; 1.963 + GET8(ptr_low); 1.964 + if (name_end < 0) name_end = j; 1.965 + j = (((int)label_len & 0x3f) << 8) + ptr_low; 1.966 + /* Make sure that the target offset is in-bounds. */ 1.967 + if (j < 0 || j >= length) return -1; 1.968 + /* If we've jumped more times than there are characters in the 1.969 + * message, we must have a loop. */ 1.970 + if (++ptr_count > length) return -1; 1.971 + continue; 1.972 + } 1.973 + if (label_len > 63) return -1; 1.974 + if (cp != name_out) { 1.975 + if (cp + 1 >= end) return -1; 1.976 + *cp++ = '.'; 1.977 + } 1.978 + if (cp + label_len >= end) return -1; 1.979 + memcpy(cp, packet + j, label_len); 1.980 + cp += label_len; 1.981 + j += label_len; 1.982 + } 1.983 + if (cp >= end) return -1; 1.984 + *cp = '\0'; 1.985 + if (name_end < 0) 1.986 + *idx = j; 1.987 + else 1.988 + *idx = name_end; 1.989 + return 0; 1.990 + err: 1.991 + return -1; 1.992 +} 1.993 + 1.994 +/* parses a raw request from a nameserver */ 1.995 +static int 1.996 +reply_parse(struct evdns_base *base, u8 *packet, int length) { 1.997 + int j = 0, k = 0; /* index into packet */ 1.998 + u16 _t; /* used by the macros */ 1.999 + u32 _t32; /* used by the macros */ 1.1000 + char tmp_name[256], cmp_name[256]; /* used by the macros */ 1.1001 + int name_matches = 0; 1.1002 + 1.1003 + u16 trans_id, questions, answers, authority, additional, datalength; 1.1004 + u16 flags = 0; 1.1005 + u32 ttl, ttl_r = 0xffffffff; 1.1006 + struct reply reply; 1.1007 + struct request *req = NULL; 1.1008 + unsigned int i; 1.1009 + 1.1010 + ASSERT_LOCKED(base); 1.1011 + 1.1012 + GET16(trans_id); 1.1013 + GET16(flags); 1.1014 + GET16(questions); 1.1015 + GET16(answers); 1.1016 + GET16(authority); 1.1017 + GET16(additional); 1.1018 + (void) authority; /* suppress "unused variable" warnings. */ 1.1019 + (void) additional; /* suppress "unused variable" warnings. */ 1.1020 + 1.1021 + req = request_find_from_trans_id(base, trans_id); 1.1022 + if (!req) return -1; 1.1023 + EVUTIL_ASSERT(req->base == base); 1.1024 + 1.1025 + memset(&reply, 0, sizeof(reply)); 1.1026 + 1.1027 + /* If it's not an answer, it doesn't correspond to any request. */ 1.1028 + if (!(flags & 0x8000)) return -1; /* must be an answer */ 1.1029 + if ((flags & 0x020f) && (flags & 0x020f) != DNS_ERR_NOTEXIST) { 1.1030 + /* there was an error and it's not NXDOMAIN */ 1.1031 + goto err; 1.1032 + } 1.1033 + /* if (!answers) return; */ /* must have an answer of some form */ 1.1034 + 1.1035 + /* This macro skips a name in the DNS reply. */ 1.1036 +#define SKIP_NAME \ 1.1037 + do { tmp_name[0] = '\0'; \ 1.1038 + if (name_parse(packet, length, &j, tmp_name, \ 1.1039 + sizeof(tmp_name))<0) \ 1.1040 + goto err; \ 1.1041 + } while (0) 1.1042 +#define TEST_NAME \ 1.1043 + do { tmp_name[0] = '\0'; \ 1.1044 + cmp_name[0] = '\0'; \ 1.1045 + k = j; \ 1.1046 + if (name_parse(packet, length, &j, tmp_name, \ 1.1047 + sizeof(tmp_name))<0) \ 1.1048 + goto err; \ 1.1049 + if (name_parse(req->request, req->request_len, &k, \ 1.1050 + cmp_name, sizeof(cmp_name))<0) \ 1.1051 + goto err; \ 1.1052 + if (base->global_randomize_case) { \ 1.1053 + if (strcmp(tmp_name, cmp_name) == 0) \ 1.1054 + name_matches = 1; \ 1.1055 + } else { \ 1.1056 + if (evutil_ascii_strcasecmp(tmp_name, cmp_name) == 0) \ 1.1057 + name_matches = 1; \ 1.1058 + } \ 1.1059 + } while (0) 1.1060 + 1.1061 + reply.type = req->request_type; 1.1062 + 1.1063 + /* skip over each question in the reply */ 1.1064 + for (i = 0; i < questions; ++i) { 1.1065 + /* the question looks like 1.1066 + * <label:name><u16:type><u16:class> 1.1067 + */ 1.1068 + TEST_NAME; 1.1069 + j += 4; 1.1070 + if (j > length) goto err; 1.1071 + } 1.1072 + 1.1073 + if (!name_matches) 1.1074 + goto err; 1.1075 + 1.1076 + /* now we have the answer section which looks like 1.1077 + * <label:name><u16:type><u16:class><u32:ttl><u16:len><data...> 1.1078 + */ 1.1079 + 1.1080 + for (i = 0; i < answers; ++i) { 1.1081 + u16 type, class; 1.1082 + 1.1083 + SKIP_NAME; 1.1084 + GET16(type); 1.1085 + GET16(class); 1.1086 + GET32(ttl); 1.1087 + GET16(datalength); 1.1088 + 1.1089 + if (type == TYPE_A && class == CLASS_INET) { 1.1090 + int addrcount, addrtocopy; 1.1091 + if (req->request_type != TYPE_A) { 1.1092 + j += datalength; continue; 1.1093 + } 1.1094 + if ((datalength & 3) != 0) /* not an even number of As. */ 1.1095 + goto err; 1.1096 + addrcount = datalength >> 2; 1.1097 + addrtocopy = MIN(MAX_V4_ADDRS - reply.data.a.addrcount, (unsigned)addrcount); 1.1098 + 1.1099 + ttl_r = MIN(ttl_r, ttl); 1.1100 + /* we only bother with the first four addresses. */ 1.1101 + if (j + 4*addrtocopy > length) goto err; 1.1102 + memcpy(&reply.data.a.addresses[reply.data.a.addrcount], 1.1103 + packet + j, 4*addrtocopy); 1.1104 + j += 4*addrtocopy; 1.1105 + reply.data.a.addrcount += addrtocopy; 1.1106 + reply.have_answer = 1; 1.1107 + if (reply.data.a.addrcount == MAX_V4_ADDRS) break; 1.1108 + } else if (type == TYPE_PTR && class == CLASS_INET) { 1.1109 + if (req->request_type != TYPE_PTR) { 1.1110 + j += datalength; continue; 1.1111 + } 1.1112 + if (name_parse(packet, length, &j, reply.data.ptr.name, 1.1113 + sizeof(reply.data.ptr.name))<0) 1.1114 + goto err; 1.1115 + ttl_r = MIN(ttl_r, ttl); 1.1116 + reply.have_answer = 1; 1.1117 + break; 1.1118 + } else if (type == TYPE_CNAME) { 1.1119 + char cname[HOST_NAME_MAX]; 1.1120 + if (!req->put_cname_in_ptr || *req->put_cname_in_ptr) { 1.1121 + j += datalength; continue; 1.1122 + } 1.1123 + if (name_parse(packet, length, &j, cname, 1.1124 + sizeof(cname))<0) 1.1125 + goto err; 1.1126 + *req->put_cname_in_ptr = mm_strdup(cname); 1.1127 + } else if (type == TYPE_AAAA && class == CLASS_INET) { 1.1128 + int addrcount, addrtocopy; 1.1129 + if (req->request_type != TYPE_AAAA) { 1.1130 + j += datalength; continue; 1.1131 + } 1.1132 + if ((datalength & 15) != 0) /* not an even number of AAAAs. */ 1.1133 + goto err; 1.1134 + addrcount = datalength >> 4; /* each address is 16 bytes long */ 1.1135 + addrtocopy = MIN(MAX_V6_ADDRS - reply.data.aaaa.addrcount, (unsigned)addrcount); 1.1136 + ttl_r = MIN(ttl_r, ttl); 1.1137 + 1.1138 + /* we only bother with the first four addresses. */ 1.1139 + if (j + 16*addrtocopy > length) goto err; 1.1140 + memcpy(&reply.data.aaaa.addresses[reply.data.aaaa.addrcount], 1.1141 + packet + j, 16*addrtocopy); 1.1142 + reply.data.aaaa.addrcount += addrtocopy; 1.1143 + j += 16*addrtocopy; 1.1144 + reply.have_answer = 1; 1.1145 + if (reply.data.aaaa.addrcount == MAX_V6_ADDRS) break; 1.1146 + } else { 1.1147 + /* skip over any other type of resource */ 1.1148 + j += datalength; 1.1149 + } 1.1150 + } 1.1151 + 1.1152 + if (!reply.have_answer) { 1.1153 + for (i = 0; i < authority; ++i) { 1.1154 + u16 type, class; 1.1155 + SKIP_NAME; 1.1156 + GET16(type); 1.1157 + GET16(class); 1.1158 + GET32(ttl); 1.1159 + GET16(datalength); 1.1160 + if (type == TYPE_SOA && class == CLASS_INET) { 1.1161 + u32 serial, refresh, retry, expire, minimum; 1.1162 + SKIP_NAME; 1.1163 + SKIP_NAME; 1.1164 + GET32(serial); 1.1165 + GET32(refresh); 1.1166 + GET32(retry); 1.1167 + GET32(expire); 1.1168 + GET32(minimum); 1.1169 + (void)expire; 1.1170 + (void)retry; 1.1171 + (void)refresh; 1.1172 + (void)serial; 1.1173 + ttl_r = MIN(ttl_r, ttl); 1.1174 + ttl_r = MIN(ttl_r, minimum); 1.1175 + } else { 1.1176 + /* skip over any other type of resource */ 1.1177 + j += datalength; 1.1178 + } 1.1179 + } 1.1180 + } 1.1181 + 1.1182 + if (ttl_r == 0xffffffff) 1.1183 + ttl_r = 0; 1.1184 + 1.1185 + reply_handle(req, flags, ttl_r, &reply); 1.1186 + return 0; 1.1187 + err: 1.1188 + if (req) 1.1189 + reply_handle(req, flags, 0, NULL); 1.1190 + return -1; 1.1191 +} 1.1192 + 1.1193 +/* Parse a raw request (packet,length) sent to a nameserver port (port) from */ 1.1194 +/* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */ 1.1195 +/* callback. */ 1.1196 +static int 1.1197 +request_parse(u8 *packet, int length, struct evdns_server_port *port, struct sockaddr *addr, ev_socklen_t addrlen) 1.1198 +{ 1.1199 + int j = 0; /* index into packet */ 1.1200 + u16 _t; /* used by the macros */ 1.1201 + char tmp_name[256]; /* used by the macros */ 1.1202 + 1.1203 + int i; 1.1204 + u16 trans_id, flags, questions, answers, authority, additional; 1.1205 + struct server_request *server_req = NULL; 1.1206 + 1.1207 + ASSERT_LOCKED(port); 1.1208 + 1.1209 + /* Get the header fields */ 1.1210 + GET16(trans_id); 1.1211 + GET16(flags); 1.1212 + GET16(questions); 1.1213 + GET16(answers); 1.1214 + GET16(authority); 1.1215 + GET16(additional); 1.1216 + (void)answers; 1.1217 + (void)additional; 1.1218 + (void)authority; 1.1219 + 1.1220 + if (flags & 0x8000) return -1; /* Must not be an answer. */ 1.1221 + flags &= 0x0110; /* Only RD and CD get preserved. */ 1.1222 + 1.1223 + server_req = mm_malloc(sizeof(struct server_request)); 1.1224 + if (server_req == NULL) return -1; 1.1225 + memset(server_req, 0, sizeof(struct server_request)); 1.1226 + 1.1227 + server_req->trans_id = trans_id; 1.1228 + memcpy(&server_req->addr, addr, addrlen); 1.1229 + server_req->addrlen = addrlen; 1.1230 + 1.1231 + server_req->base.flags = flags; 1.1232 + server_req->base.nquestions = 0; 1.1233 + server_req->base.questions = mm_calloc(sizeof(struct evdns_server_question *), questions); 1.1234 + if (server_req->base.questions == NULL) 1.1235 + goto err; 1.1236 + 1.1237 + for (i = 0; i < questions; ++i) { 1.1238 + u16 type, class; 1.1239 + struct evdns_server_question *q; 1.1240 + int namelen; 1.1241 + if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) 1.1242 + goto err; 1.1243 + GET16(type); 1.1244 + GET16(class); 1.1245 + namelen = (int)strlen(tmp_name); 1.1246 + q = mm_malloc(sizeof(struct evdns_server_question) + namelen); 1.1247 + if (!q) 1.1248 + goto err; 1.1249 + q->type = type; 1.1250 + q->dns_question_class = class; 1.1251 + memcpy(q->name, tmp_name, namelen+1); 1.1252 + server_req->base.questions[server_req->base.nquestions++] = q; 1.1253 + } 1.1254 + 1.1255 + /* Ignore answers, authority, and additional. */ 1.1256 + 1.1257 + server_req->port = port; 1.1258 + port->refcnt++; 1.1259 + 1.1260 + /* Only standard queries are supported. */ 1.1261 + if (flags & 0x7800) { 1.1262 + evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL); 1.1263 + return -1; 1.1264 + } 1.1265 + 1.1266 + port->user_callback(&(server_req->base), port->user_data); 1.1267 + 1.1268 + return 0; 1.1269 +err: 1.1270 + if (server_req) { 1.1271 + if (server_req->base.questions) { 1.1272 + for (i = 0; i < server_req->base.nquestions; ++i) 1.1273 + mm_free(server_req->base.questions[i]); 1.1274 + mm_free(server_req->base.questions); 1.1275 + } 1.1276 + mm_free(server_req); 1.1277 + } 1.1278 + return -1; 1.1279 + 1.1280 +#undef SKIP_NAME 1.1281 +#undef GET32 1.1282 +#undef GET16 1.1283 +#undef GET8 1.1284 +} 1.1285 + 1.1286 + 1.1287 +void 1.1288 +evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void)) 1.1289 +{ 1.1290 +} 1.1291 + 1.1292 +void 1.1293 +evdns_set_random_bytes_fn(void (*fn)(char *, size_t)) 1.1294 +{ 1.1295 +} 1.1296 + 1.1297 +/* Try to choose a strong transaction id which isn't already in flight */ 1.1298 +static u16 1.1299 +transaction_id_pick(struct evdns_base *base) { 1.1300 + ASSERT_LOCKED(base); 1.1301 + for (;;) { 1.1302 + u16 trans_id; 1.1303 + evutil_secure_rng_get_bytes(&trans_id, sizeof(trans_id)); 1.1304 + 1.1305 + if (trans_id == 0xffff) continue; 1.1306 + /* now check to see if that id is already inflight */ 1.1307 + if (request_find_from_trans_id(base, trans_id) == NULL) 1.1308 + return trans_id; 1.1309 + } 1.1310 +} 1.1311 + 1.1312 +/* choose a namesever to use. This function will try to ignore */ 1.1313 +/* nameservers which we think are down and load balance across the rest */ 1.1314 +/* by updating the server_head global each time. */ 1.1315 +static struct nameserver * 1.1316 +nameserver_pick(struct evdns_base *base) { 1.1317 + struct nameserver *started_at = base->server_head, *picked; 1.1318 + ASSERT_LOCKED(base); 1.1319 + if (!base->server_head) return NULL; 1.1320 + 1.1321 + /* if we don't have any good nameservers then there's no */ 1.1322 + /* point in trying to find one. */ 1.1323 + if (!base->global_good_nameservers) { 1.1324 + base->server_head = base->server_head->next; 1.1325 + return base->server_head; 1.1326 + } 1.1327 + 1.1328 + /* remember that nameservers are in a circular list */ 1.1329 + for (;;) { 1.1330 + if (base->server_head->state) { 1.1331 + /* we think this server is currently good */ 1.1332 + picked = base->server_head; 1.1333 + base->server_head = base->server_head->next; 1.1334 + return picked; 1.1335 + } 1.1336 + 1.1337 + base->server_head = base->server_head->next; 1.1338 + if (base->server_head == started_at) { 1.1339 + /* all the nameservers seem to be down */ 1.1340 + /* so we just return this one and hope for the */ 1.1341 + /* best */ 1.1342 + EVUTIL_ASSERT(base->global_good_nameservers == 0); 1.1343 + picked = base->server_head; 1.1344 + base->server_head = base->server_head->next; 1.1345 + return picked; 1.1346 + } 1.1347 + } 1.1348 +} 1.1349 + 1.1350 +/* this is called when a namesever socket is ready for reading */ 1.1351 +static void 1.1352 +nameserver_read(struct nameserver *ns) { 1.1353 + struct sockaddr_storage ss; 1.1354 + ev_socklen_t addrlen = sizeof(ss); 1.1355 + u8 packet[1500]; 1.1356 + char addrbuf[128]; 1.1357 + ASSERT_LOCKED(ns->base); 1.1358 + 1.1359 + for (;;) { 1.1360 + const int r = recvfrom(ns->socket, (void*)packet, 1.1361 + sizeof(packet), 0, 1.1362 + (struct sockaddr*)&ss, &addrlen); 1.1363 + if (r < 0) { 1.1364 + int err = evutil_socket_geterror(ns->socket); 1.1365 + if (EVUTIL_ERR_RW_RETRIABLE(err)) 1.1366 + return; 1.1367 + nameserver_failed(ns, 1.1368 + evutil_socket_error_to_string(err)); 1.1369 + return; 1.1370 + } 1.1371 + if (evutil_sockaddr_cmp((struct sockaddr*)&ss, 1.1372 + (struct sockaddr*)&ns->address, 0)) { 1.1373 + log(EVDNS_LOG_WARN, "Address mismatch on received " 1.1374 + "DNS packet. Apparent source was %s", 1.1375 + evutil_format_sockaddr_port( 1.1376 + (struct sockaddr *)&ss, 1.1377 + addrbuf, sizeof(addrbuf))); 1.1378 + return; 1.1379 + } 1.1380 + 1.1381 + ns->timedout = 0; 1.1382 + reply_parse(ns->base, packet, r); 1.1383 + } 1.1384 +} 1.1385 + 1.1386 +/* Read a packet from a DNS client on a server port s, parse it, and */ 1.1387 +/* act accordingly. */ 1.1388 +static void 1.1389 +server_port_read(struct evdns_server_port *s) { 1.1390 + u8 packet[1500]; 1.1391 + struct sockaddr_storage addr; 1.1392 + ev_socklen_t addrlen; 1.1393 + int r; 1.1394 + ASSERT_LOCKED(s); 1.1395 + 1.1396 + for (;;) { 1.1397 + addrlen = sizeof(struct sockaddr_storage); 1.1398 + r = recvfrom(s->socket, (void*)packet, sizeof(packet), 0, 1.1399 + (struct sockaddr*) &addr, &addrlen); 1.1400 + if (r < 0) { 1.1401 + int err = evutil_socket_geterror(s->socket); 1.1402 + if (EVUTIL_ERR_RW_RETRIABLE(err)) 1.1403 + return; 1.1404 + log(EVDNS_LOG_WARN, 1.1405 + "Error %s (%d) while reading request.", 1.1406 + evutil_socket_error_to_string(err), err); 1.1407 + return; 1.1408 + } 1.1409 + request_parse(packet, r, s, (struct sockaddr*) &addr, addrlen); 1.1410 + } 1.1411 +} 1.1412 + 1.1413 +/* Try to write all pending replies on a given DNS server port. */ 1.1414 +static void 1.1415 +server_port_flush(struct evdns_server_port *port) 1.1416 +{ 1.1417 + struct server_request *req = port->pending_replies; 1.1418 + ASSERT_LOCKED(port); 1.1419 + while (req) { 1.1420 + int r = sendto(port->socket, req->response, (int)req->response_len, 0, 1.1421 + (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); 1.1422 + if (r < 0) { 1.1423 + int err = evutil_socket_geterror(port->socket); 1.1424 + if (EVUTIL_ERR_RW_RETRIABLE(err)) 1.1425 + return; 1.1426 + log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", evutil_socket_error_to_string(err), err); 1.1427 + } 1.1428 + if (server_request_free(req)) { 1.1429 + /* we released the last reference to req->port. */ 1.1430 + return; 1.1431 + } else { 1.1432 + EVUTIL_ASSERT(req != port->pending_replies); 1.1433 + req = port->pending_replies; 1.1434 + } 1.1435 + } 1.1436 + 1.1437 + /* We have no more pending requests; stop listening for 'writeable' events. */ 1.1438 + (void) event_del(&port->event); 1.1439 + event_assign(&port->event, port->event_base, 1.1440 + port->socket, EV_READ | EV_PERSIST, 1.1441 + server_port_ready_callback, port); 1.1442 + 1.1443 + if (event_add(&port->event, NULL) < 0) { 1.1444 + log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server."); 1.1445 + /* ???? Do more? */ 1.1446 + } 1.1447 +} 1.1448 + 1.1449 +/* set if we are waiting for the ability to write to this server. */ 1.1450 +/* if waiting is true then we ask libevent for EV_WRITE events, otherwise */ 1.1451 +/* we stop these events. */ 1.1452 +static void 1.1453 +nameserver_write_waiting(struct nameserver *ns, char waiting) { 1.1454 + ASSERT_LOCKED(ns->base); 1.1455 + if (ns->write_waiting == waiting) return; 1.1456 + 1.1457 + ns->write_waiting = waiting; 1.1458 + (void) event_del(&ns->event); 1.1459 + event_assign(&ns->event, ns->base->event_base, 1.1460 + ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST, 1.1461 + nameserver_ready_callback, ns); 1.1462 + if (event_add(&ns->event, NULL) < 0) { 1.1463 + char addrbuf[128]; 1.1464 + log(EVDNS_LOG_WARN, "Error from libevent when adding event for %s", 1.1465 + evutil_format_sockaddr_port( 1.1466 + (struct sockaddr *)&ns->address, 1.1467 + addrbuf, sizeof(addrbuf))); 1.1468 + /* ???? Do more? */ 1.1469 + } 1.1470 +} 1.1471 + 1.1472 +/* a callback function. Called by libevent when the kernel says that */ 1.1473 +/* a nameserver socket is ready for writing or reading */ 1.1474 +static void 1.1475 +nameserver_ready_callback(evutil_socket_t fd, short events, void *arg) { 1.1476 + struct nameserver *ns = (struct nameserver *) arg; 1.1477 + (void)fd; 1.1478 + 1.1479 + EVDNS_LOCK(ns->base); 1.1480 + if (events & EV_WRITE) { 1.1481 + ns->choked = 0; 1.1482 + if (!evdns_transmit(ns->base)) { 1.1483 + nameserver_write_waiting(ns, 0); 1.1484 + } 1.1485 + } 1.1486 + if (events & EV_READ) { 1.1487 + nameserver_read(ns); 1.1488 + } 1.1489 + EVDNS_UNLOCK(ns->base); 1.1490 +} 1.1491 + 1.1492 +/* a callback function. Called by libevent when the kernel says that */ 1.1493 +/* a server socket is ready for writing or reading. */ 1.1494 +static void 1.1495 +server_port_ready_callback(evutil_socket_t fd, short events, void *arg) { 1.1496 + struct evdns_server_port *port = (struct evdns_server_port *) arg; 1.1497 + (void) fd; 1.1498 + 1.1499 + EVDNS_LOCK(port); 1.1500 + if (events & EV_WRITE) { 1.1501 + port->choked = 0; 1.1502 + server_port_flush(port); 1.1503 + } 1.1504 + if (events & EV_READ) { 1.1505 + server_port_read(port); 1.1506 + } 1.1507 + EVDNS_UNLOCK(port); 1.1508 +} 1.1509 + 1.1510 +/* This is an inefficient representation; only use it via the dnslabel_table_* 1.1511 + * functions, so that is can be safely replaced with something smarter later. */ 1.1512 +#define MAX_LABELS 128 1.1513 +/* Structures used to implement name compression */ 1.1514 +struct dnslabel_entry { char *v; off_t pos; }; 1.1515 +struct dnslabel_table { 1.1516 + int n_labels; /* number of current entries */ 1.1517 + /* map from name to position in message */ 1.1518 + struct dnslabel_entry labels[MAX_LABELS]; 1.1519 +}; 1.1520 + 1.1521 +/* Initialize dnslabel_table. */ 1.1522 +static void 1.1523 +dnslabel_table_init(struct dnslabel_table *table) 1.1524 +{ 1.1525 + table->n_labels = 0; 1.1526 +} 1.1527 + 1.1528 +/* Free all storage held by table, but not the table itself. */ 1.1529 +static void 1.1530 +dnslabel_clear(struct dnslabel_table *table) 1.1531 +{ 1.1532 + int i; 1.1533 + for (i = 0; i < table->n_labels; ++i) 1.1534 + mm_free(table->labels[i].v); 1.1535 + table->n_labels = 0; 1.1536 +} 1.1537 + 1.1538 +/* return the position of the label in the current message, or -1 if the label */ 1.1539 +/* hasn't been used yet. */ 1.1540 +static int 1.1541 +dnslabel_table_get_pos(const struct dnslabel_table *table, const char *label) 1.1542 +{ 1.1543 + int i; 1.1544 + for (i = 0; i < table->n_labels; ++i) { 1.1545 + if (!strcmp(label, table->labels[i].v)) 1.1546 + return table->labels[i].pos; 1.1547 + } 1.1548 + return -1; 1.1549 +} 1.1550 + 1.1551 +/* remember that we've used the label at position pos */ 1.1552 +static int 1.1553 +dnslabel_table_add(struct dnslabel_table *table, const char *label, off_t pos) 1.1554 +{ 1.1555 + char *v; 1.1556 + int p; 1.1557 + if (table->n_labels == MAX_LABELS) 1.1558 + return (-1); 1.1559 + v = mm_strdup(label); 1.1560 + if (v == NULL) 1.1561 + return (-1); 1.1562 + p = table->n_labels++; 1.1563 + table->labels[p].v = v; 1.1564 + table->labels[p].pos = pos; 1.1565 + 1.1566 + return (0); 1.1567 +} 1.1568 + 1.1569 +/* Converts a string to a length-prefixed set of DNS labels, starting */ 1.1570 +/* at buf[j]. name and buf must not overlap. name_len should be the length */ 1.1571 +/* of name. table is optional, and is used for compression. */ 1.1572 +/* */ 1.1573 +/* Input: abc.def */ 1.1574 +/* Output: <3>abc<3>def<0> */ 1.1575 +/* */ 1.1576 +/* Returns the first index after the encoded name, or negative on error. */ 1.1577 +/* -1 label was > 63 bytes */ 1.1578 +/* -2 name too long to fit in buffer. */ 1.1579 +/* */ 1.1580 +static off_t 1.1581 +dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j, 1.1582 + const char *name, const size_t name_len, 1.1583 + struct dnslabel_table *table) { 1.1584 + const char *end = name + name_len; 1.1585 + int ref = 0; 1.1586 + u16 _t; 1.1587 + 1.1588 +#define APPEND16(x) do { \ 1.1589 + if (j + 2 > (off_t)buf_len) \ 1.1590 + goto overflow; \ 1.1591 + _t = htons(x); \ 1.1592 + memcpy(buf + j, &_t, 2); \ 1.1593 + j += 2; \ 1.1594 + } while (0) 1.1595 +#define APPEND32(x) do { \ 1.1596 + if (j + 4 > (off_t)buf_len) \ 1.1597 + goto overflow; \ 1.1598 + _t32 = htonl(x); \ 1.1599 + memcpy(buf + j, &_t32, 4); \ 1.1600 + j += 4; \ 1.1601 + } while (0) 1.1602 + 1.1603 + if (name_len > 255) return -2; 1.1604 + 1.1605 + for (;;) { 1.1606 + const char *const start = name; 1.1607 + if (table && (ref = dnslabel_table_get_pos(table, name)) >= 0) { 1.1608 + APPEND16(ref | 0xc000); 1.1609 + return j; 1.1610 + } 1.1611 + name = strchr(name, '.'); 1.1612 + if (!name) { 1.1613 + const size_t label_len = end - start; 1.1614 + if (label_len > 63) return -1; 1.1615 + if ((size_t)(j+label_len+1) > buf_len) return -2; 1.1616 + if (table) dnslabel_table_add(table, start, j); 1.1617 + buf[j++] = (ev_uint8_t)label_len; 1.1618 + 1.1619 + memcpy(buf + j, start, label_len); 1.1620 + j += (int) label_len; 1.1621 + break; 1.1622 + } else { 1.1623 + /* append length of the label. */ 1.1624 + const size_t label_len = name - start; 1.1625 + if (label_len > 63) return -1; 1.1626 + if ((size_t)(j+label_len+1) > buf_len) return -2; 1.1627 + if (table) dnslabel_table_add(table, start, j); 1.1628 + buf[j++] = (ev_uint8_t)label_len; 1.1629 + 1.1630 + memcpy(buf + j, start, label_len); 1.1631 + j += (int) label_len; 1.1632 + /* hop over the '.' */ 1.1633 + name++; 1.1634 + } 1.1635 + } 1.1636 + 1.1637 + /* the labels must be terminated by a 0. */ 1.1638 + /* It's possible that the name ended in a . */ 1.1639 + /* in which case the zero is already there */ 1.1640 + if (!j || buf[j-1]) buf[j++] = 0; 1.1641 + return j; 1.1642 + overflow: 1.1643 + return (-2); 1.1644 +} 1.1645 + 1.1646 +/* Finds the length of a dns request for a DNS name of the given */ 1.1647 +/* length. The actual request may be smaller than the value returned */ 1.1648 +/* here */ 1.1649 +static size_t 1.1650 +evdns_request_len(const size_t name_len) { 1.1651 + return 96 + /* length of the DNS standard header */ 1.1652 + name_len + 2 + 1.1653 + 4; /* space for the resource type */ 1.1654 +} 1.1655 + 1.1656 +/* build a dns request packet into buf. buf should be at least as long */ 1.1657 +/* as evdns_request_len told you it should be. */ 1.1658 +/* */ 1.1659 +/* Returns the amount of space used. Negative on error. */ 1.1660 +static int 1.1661 +evdns_request_data_build(const char *const name, const size_t name_len, 1.1662 + const u16 trans_id, const u16 type, const u16 class, 1.1663 + u8 *const buf, size_t buf_len) { 1.1664 + off_t j = 0; /* current offset into buf */ 1.1665 + u16 _t; /* used by the macros */ 1.1666 + 1.1667 + APPEND16(trans_id); 1.1668 + APPEND16(0x0100); /* standard query, recusion needed */ 1.1669 + APPEND16(1); /* one question */ 1.1670 + APPEND16(0); /* no answers */ 1.1671 + APPEND16(0); /* no authority */ 1.1672 + APPEND16(0); /* no additional */ 1.1673 + 1.1674 + j = dnsname_to_labels(buf, buf_len, j, name, name_len, NULL); 1.1675 + if (j < 0) { 1.1676 + return (int)j; 1.1677 + } 1.1678 + 1.1679 + APPEND16(type); 1.1680 + APPEND16(class); 1.1681 + 1.1682 + return (int)j; 1.1683 + overflow: 1.1684 + return (-1); 1.1685 +} 1.1686 + 1.1687 +/* exported function */ 1.1688 +struct evdns_server_port * 1.1689 +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) 1.1690 +{ 1.1691 + struct evdns_server_port *port; 1.1692 + if (flags) 1.1693 + return NULL; /* flags not yet implemented */ 1.1694 + if (!(port = mm_malloc(sizeof(struct evdns_server_port)))) 1.1695 + return NULL; 1.1696 + memset(port, 0, sizeof(struct evdns_server_port)); 1.1697 + 1.1698 + 1.1699 + port->socket = socket; 1.1700 + port->refcnt = 1; 1.1701 + port->choked = 0; 1.1702 + port->closing = 0; 1.1703 + port->user_callback = cb; 1.1704 + port->user_data = user_data; 1.1705 + port->pending_replies = NULL; 1.1706 + port->event_base = base; 1.1707 + 1.1708 + event_assign(&port->event, port->event_base, 1.1709 + port->socket, EV_READ | EV_PERSIST, 1.1710 + server_port_ready_callback, port); 1.1711 + if (event_add(&port->event, NULL) < 0) { 1.1712 + mm_free(port); 1.1713 + return NULL; 1.1714 + } 1.1715 + EVTHREAD_ALLOC_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.1716 + return port; 1.1717 +} 1.1718 + 1.1719 +struct evdns_server_port * 1.1720 +evdns_add_server_port(evutil_socket_t socket, int flags, evdns_request_callback_fn_type cb, void *user_data) 1.1721 +{ 1.1722 + return evdns_add_server_port_with_base(NULL, socket, flags, cb, user_data); 1.1723 +} 1.1724 + 1.1725 +/* exported function */ 1.1726 +void 1.1727 +evdns_close_server_port(struct evdns_server_port *port) 1.1728 +{ 1.1729 + EVDNS_LOCK(port); 1.1730 + if (--port->refcnt == 0) { 1.1731 + EVDNS_UNLOCK(port); 1.1732 + server_port_free(port); 1.1733 + } else { 1.1734 + port->closing = 1; 1.1735 + } 1.1736 +} 1.1737 + 1.1738 +/* exported function */ 1.1739 +int 1.1740 +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) 1.1741 +{ 1.1742 + struct server_request *req = TO_SERVER_REQUEST(_req); 1.1743 + struct server_reply_item **itemp, *item; 1.1744 + int *countp; 1.1745 + int result = -1; 1.1746 + 1.1747 + EVDNS_LOCK(req->port); 1.1748 + if (req->response) /* have we already answered? */ 1.1749 + goto done; 1.1750 + 1.1751 + switch (section) { 1.1752 + case EVDNS_ANSWER_SECTION: 1.1753 + itemp = &req->answer; 1.1754 + countp = &req->n_answer; 1.1755 + break; 1.1756 + case EVDNS_AUTHORITY_SECTION: 1.1757 + itemp = &req->authority; 1.1758 + countp = &req->n_authority; 1.1759 + break; 1.1760 + case EVDNS_ADDITIONAL_SECTION: 1.1761 + itemp = &req->additional; 1.1762 + countp = &req->n_additional; 1.1763 + break; 1.1764 + default: 1.1765 + goto done; 1.1766 + } 1.1767 + while (*itemp) { 1.1768 + itemp = &((*itemp)->next); 1.1769 + } 1.1770 + item = mm_malloc(sizeof(struct server_reply_item)); 1.1771 + if (!item) 1.1772 + goto done; 1.1773 + item->next = NULL; 1.1774 + if (!(item->name = mm_strdup(name))) { 1.1775 + mm_free(item); 1.1776 + goto done; 1.1777 + } 1.1778 + item->type = type; 1.1779 + item->dns_question_class = class; 1.1780 + item->ttl = ttl; 1.1781 + item->is_name = is_name != 0; 1.1782 + item->datalen = 0; 1.1783 + item->data = NULL; 1.1784 + if (data) { 1.1785 + if (item->is_name) { 1.1786 + if (!(item->data = mm_strdup(data))) { 1.1787 + mm_free(item->name); 1.1788 + mm_free(item); 1.1789 + goto done; 1.1790 + } 1.1791 + item->datalen = (u16)-1; 1.1792 + } else { 1.1793 + if (!(item->data = mm_malloc(datalen))) { 1.1794 + mm_free(item->name); 1.1795 + mm_free(item); 1.1796 + goto done; 1.1797 + } 1.1798 + item->datalen = datalen; 1.1799 + memcpy(item->data, data, datalen); 1.1800 + } 1.1801 + } 1.1802 + 1.1803 + *itemp = item; 1.1804 + ++(*countp); 1.1805 + result = 0; 1.1806 +done: 1.1807 + EVDNS_UNLOCK(req->port); 1.1808 + return result; 1.1809 +} 1.1810 + 1.1811 +/* exported function */ 1.1812 +int 1.1813 +evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl) 1.1814 +{ 1.1815 + return evdns_server_request_add_reply( 1.1816 + req, EVDNS_ANSWER_SECTION, name, TYPE_A, CLASS_INET, 1.1817 + ttl, n*4, 0, addrs); 1.1818 +} 1.1819 + 1.1820 +/* exported function */ 1.1821 +int 1.1822 +evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl) 1.1823 +{ 1.1824 + return evdns_server_request_add_reply( 1.1825 + req, EVDNS_ANSWER_SECTION, name, TYPE_AAAA, CLASS_INET, 1.1826 + ttl, n*16, 0, addrs); 1.1827 +} 1.1828 + 1.1829 +/* exported function */ 1.1830 +int 1.1831 +evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl) 1.1832 +{ 1.1833 + u32 a; 1.1834 + char buf[32]; 1.1835 + if (in && inaddr_name) 1.1836 + return -1; 1.1837 + else if (!in && !inaddr_name) 1.1838 + return -1; 1.1839 + if (in) { 1.1840 + a = ntohl(in->s_addr); 1.1841 + evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", 1.1842 + (int)(u8)((a )&0xff), 1.1843 + (int)(u8)((a>>8 )&0xff), 1.1844 + (int)(u8)((a>>16)&0xff), 1.1845 + (int)(u8)((a>>24)&0xff)); 1.1846 + inaddr_name = buf; 1.1847 + } 1.1848 + return evdns_server_request_add_reply( 1.1849 + req, EVDNS_ANSWER_SECTION, inaddr_name, TYPE_PTR, CLASS_INET, 1.1850 + ttl, -1, 1, hostname); 1.1851 +} 1.1852 + 1.1853 +/* exported function */ 1.1854 +int 1.1855 +evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl) 1.1856 +{ 1.1857 + return evdns_server_request_add_reply( 1.1858 + req, EVDNS_ANSWER_SECTION, name, TYPE_CNAME, CLASS_INET, 1.1859 + ttl, -1, 1, cname); 1.1860 +} 1.1861 + 1.1862 +/* exported function */ 1.1863 +void 1.1864 +evdns_server_request_set_flags(struct evdns_server_request *exreq, int flags) 1.1865 +{ 1.1866 + struct server_request *req = TO_SERVER_REQUEST(exreq); 1.1867 + req->base.flags &= ~(EVDNS_FLAGS_AA|EVDNS_FLAGS_RD); 1.1868 + req->base.flags |= flags; 1.1869 +} 1.1870 + 1.1871 +static int 1.1872 +evdns_server_request_format_response(struct server_request *req, int err) 1.1873 +{ 1.1874 + unsigned char buf[1500]; 1.1875 + size_t buf_len = sizeof(buf); 1.1876 + off_t j = 0, r; 1.1877 + u16 _t; 1.1878 + u32 _t32; 1.1879 + int i; 1.1880 + u16 flags; 1.1881 + struct dnslabel_table table; 1.1882 + 1.1883 + if (err < 0 || err > 15) return -1; 1.1884 + 1.1885 + /* Set response bit and error code; copy OPCODE and RD fields from 1.1886 + * question; copy RA and AA if set by caller. */ 1.1887 + flags = req->base.flags; 1.1888 + flags |= (0x8000 | err); 1.1889 + 1.1890 + dnslabel_table_init(&table); 1.1891 + APPEND16(req->trans_id); 1.1892 + APPEND16(flags); 1.1893 + APPEND16(req->base.nquestions); 1.1894 + APPEND16(req->n_answer); 1.1895 + APPEND16(req->n_authority); 1.1896 + APPEND16(req->n_additional); 1.1897 + 1.1898 + /* Add questions. */ 1.1899 + for (i=0; i < req->base.nquestions; ++i) { 1.1900 + const char *s = req->base.questions[i]->name; 1.1901 + j = dnsname_to_labels(buf, buf_len, j, s, strlen(s), &table); 1.1902 + if (j < 0) { 1.1903 + dnslabel_clear(&table); 1.1904 + return (int) j; 1.1905 + } 1.1906 + APPEND16(req->base.questions[i]->type); 1.1907 + APPEND16(req->base.questions[i]->dns_question_class); 1.1908 + } 1.1909 + 1.1910 + /* Add answer, authority, and additional sections. */ 1.1911 + for (i=0; i<3; ++i) { 1.1912 + struct server_reply_item *item; 1.1913 + if (i==0) 1.1914 + item = req->answer; 1.1915 + else if (i==1) 1.1916 + item = req->authority; 1.1917 + else 1.1918 + item = req->additional; 1.1919 + while (item) { 1.1920 + r = dnsname_to_labels(buf, buf_len, j, item->name, strlen(item->name), &table); 1.1921 + if (r < 0) 1.1922 + goto overflow; 1.1923 + j = r; 1.1924 + 1.1925 + APPEND16(item->type); 1.1926 + APPEND16(item->dns_question_class); 1.1927 + APPEND32(item->ttl); 1.1928 + if (item->is_name) { 1.1929 + off_t len_idx = j, name_start; 1.1930 + j += 2; 1.1931 + name_start = j; 1.1932 + r = dnsname_to_labels(buf, buf_len, j, item->data, strlen(item->data), &table); 1.1933 + if (r < 0) 1.1934 + goto overflow; 1.1935 + j = r; 1.1936 + _t = htons( (short) (j-name_start) ); 1.1937 + memcpy(buf+len_idx, &_t, 2); 1.1938 + } else { 1.1939 + APPEND16(item->datalen); 1.1940 + if (j+item->datalen > (off_t)buf_len) 1.1941 + goto overflow; 1.1942 + memcpy(buf+j, item->data, item->datalen); 1.1943 + j += item->datalen; 1.1944 + } 1.1945 + item = item->next; 1.1946 + } 1.1947 + } 1.1948 + 1.1949 + if (j > 512) { 1.1950 +overflow: 1.1951 + j = 512; 1.1952 + buf[2] |= 0x02; /* set the truncated bit. */ 1.1953 + } 1.1954 + 1.1955 + req->response_len = j; 1.1956 + 1.1957 + if (!(req->response = mm_malloc(req->response_len))) { 1.1958 + server_request_free_answers(req); 1.1959 + dnslabel_clear(&table); 1.1960 + return (-1); 1.1961 + } 1.1962 + memcpy(req->response, buf, req->response_len); 1.1963 + server_request_free_answers(req); 1.1964 + dnslabel_clear(&table); 1.1965 + return (0); 1.1966 +} 1.1967 + 1.1968 +/* exported function */ 1.1969 +int 1.1970 +evdns_server_request_respond(struct evdns_server_request *_req, int err) 1.1971 +{ 1.1972 + struct server_request *req = TO_SERVER_REQUEST(_req); 1.1973 + struct evdns_server_port *port = req->port; 1.1974 + int r = -1; 1.1975 + 1.1976 + EVDNS_LOCK(port); 1.1977 + if (!req->response) { 1.1978 + if ((r = evdns_server_request_format_response(req, err))<0) 1.1979 + goto done; 1.1980 + } 1.1981 + 1.1982 + r = sendto(port->socket, req->response, (int)req->response_len, 0, 1.1983 + (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); 1.1984 + if (r<0) { 1.1985 + int sock_err = evutil_socket_geterror(port->socket); 1.1986 + if (EVUTIL_ERR_RW_RETRIABLE(sock_err)) 1.1987 + goto done; 1.1988 + 1.1989 + if (port->pending_replies) { 1.1990 + req->prev_pending = port->pending_replies->prev_pending; 1.1991 + req->next_pending = port->pending_replies; 1.1992 + req->prev_pending->next_pending = 1.1993 + req->next_pending->prev_pending = req; 1.1994 + } else { 1.1995 + req->prev_pending = req->next_pending = req; 1.1996 + port->pending_replies = req; 1.1997 + port->choked = 1; 1.1998 + 1.1999 + (void) event_del(&port->event); 1.2000 + event_assign(&port->event, port->event_base, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV_PERSIST, server_port_ready_callback, port); 1.2001 + 1.2002 + if (event_add(&port->event, NULL) < 0) { 1.2003 + log(EVDNS_LOG_WARN, "Error from libevent when adding event for DNS server"); 1.2004 + } 1.2005 + 1.2006 + } 1.2007 + 1.2008 + r = 1; 1.2009 + goto done; 1.2010 + } 1.2011 + if (server_request_free(req)) { 1.2012 + r = 0; 1.2013 + goto done; 1.2014 + } 1.2015 + 1.2016 + if (port->pending_replies) 1.2017 + server_port_flush(port); 1.2018 + 1.2019 + r = 0; 1.2020 +done: 1.2021 + EVDNS_UNLOCK(port); 1.2022 + return r; 1.2023 +} 1.2024 + 1.2025 +/* Free all storage held by RRs in req. */ 1.2026 +static void 1.2027 +server_request_free_answers(struct server_request *req) 1.2028 +{ 1.2029 + struct server_reply_item *victim, *next, **list; 1.2030 + int i; 1.2031 + for (i = 0; i < 3; ++i) { 1.2032 + if (i==0) 1.2033 + list = &req->answer; 1.2034 + else if (i==1) 1.2035 + list = &req->authority; 1.2036 + else 1.2037 + list = &req->additional; 1.2038 + 1.2039 + victim = *list; 1.2040 + while (victim) { 1.2041 + next = victim->next; 1.2042 + mm_free(victim->name); 1.2043 + if (victim->data) 1.2044 + mm_free(victim->data); 1.2045 + mm_free(victim); 1.2046 + victim = next; 1.2047 + } 1.2048 + *list = NULL; 1.2049 + } 1.2050 +} 1.2051 + 1.2052 +/* Free all storage held by req, and remove links to it. */ 1.2053 +/* return true iff we just wound up freeing the server_port. */ 1.2054 +static int 1.2055 +server_request_free(struct server_request *req) 1.2056 +{ 1.2057 + int i, rc=1, lock=0; 1.2058 + if (req->base.questions) { 1.2059 + for (i = 0; i < req->base.nquestions; ++i) 1.2060 + mm_free(req->base.questions[i]); 1.2061 + mm_free(req->base.questions); 1.2062 + } 1.2063 + 1.2064 + if (req->port) { 1.2065 + EVDNS_LOCK(req->port); 1.2066 + lock=1; 1.2067 + if (req->port->pending_replies == req) { 1.2068 + if (req->next_pending && req->next_pending != req) 1.2069 + req->port->pending_replies = req->next_pending; 1.2070 + else 1.2071 + req->port->pending_replies = NULL; 1.2072 + } 1.2073 + rc = --req->port->refcnt; 1.2074 + } 1.2075 + 1.2076 + if (req->response) { 1.2077 + mm_free(req->response); 1.2078 + } 1.2079 + 1.2080 + server_request_free_answers(req); 1.2081 + 1.2082 + if (req->next_pending && req->next_pending != req) { 1.2083 + req->next_pending->prev_pending = req->prev_pending; 1.2084 + req->prev_pending->next_pending = req->next_pending; 1.2085 + } 1.2086 + 1.2087 + if (rc == 0) { 1.2088 + EVDNS_UNLOCK(req->port); /* ????? nickm */ 1.2089 + server_port_free(req->port); 1.2090 + mm_free(req); 1.2091 + return (1); 1.2092 + } 1.2093 + if (lock) 1.2094 + EVDNS_UNLOCK(req->port); 1.2095 + mm_free(req); 1.2096 + return (0); 1.2097 +} 1.2098 + 1.2099 +/* Free all storage held by an evdns_server_port. Only called when */ 1.2100 +static void 1.2101 +server_port_free(struct evdns_server_port *port) 1.2102 +{ 1.2103 + EVUTIL_ASSERT(port); 1.2104 + EVUTIL_ASSERT(!port->refcnt); 1.2105 + EVUTIL_ASSERT(!port->pending_replies); 1.2106 + if (port->socket > 0) { 1.2107 + evutil_closesocket(port->socket); 1.2108 + port->socket = -1; 1.2109 + } 1.2110 + (void) event_del(&port->event); 1.2111 + event_debug_unassign(&port->event); 1.2112 + EVTHREAD_FREE_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.2113 + mm_free(port); 1.2114 +} 1.2115 + 1.2116 +/* exported function */ 1.2117 +int 1.2118 +evdns_server_request_drop(struct evdns_server_request *_req) 1.2119 +{ 1.2120 + struct server_request *req = TO_SERVER_REQUEST(_req); 1.2121 + server_request_free(req); 1.2122 + return 0; 1.2123 +} 1.2124 + 1.2125 +/* exported function */ 1.2126 +int 1.2127 +evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len) 1.2128 +{ 1.2129 + struct server_request *req = TO_SERVER_REQUEST(_req); 1.2130 + if (addr_len < (int)req->addrlen) 1.2131 + return -1; 1.2132 + memcpy(sa, &(req->addr), req->addrlen); 1.2133 + return req->addrlen; 1.2134 +} 1.2135 + 1.2136 +#undef APPEND16 1.2137 +#undef APPEND32 1.2138 + 1.2139 +/* this is a libevent callback function which is called when a request */ 1.2140 +/* has timed out. */ 1.2141 +static void 1.2142 +evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) { 1.2143 + struct request *const req = (struct request *) arg; 1.2144 + struct evdns_base *base = req->base; 1.2145 + 1.2146 + (void) fd; 1.2147 + (void) events; 1.2148 + 1.2149 + log(EVDNS_LOG_DEBUG, "Request %p timed out", arg); 1.2150 + EVDNS_LOCK(base); 1.2151 + 1.2152 + req->ns->timedout++; 1.2153 + if (req->ns->timedout > req->base->global_max_nameserver_timeout) { 1.2154 + req->ns->timedout = 0; 1.2155 + nameserver_failed(req->ns, "request timed out."); 1.2156 + } 1.2157 + 1.2158 + if (req->tx_count >= req->base->global_max_retransmits) { 1.2159 + /* this request has failed */ 1.2160 + log(EVDNS_LOG_DEBUG, "Giving up on request %p; tx_count==%d", 1.2161 + arg, req->tx_count); 1.2162 + reply_schedule_callback(req, 0, DNS_ERR_TIMEOUT, NULL); 1.2163 + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); 1.2164 + } else { 1.2165 + /* retransmit it */ 1.2166 + struct nameserver *new_ns; 1.2167 + log(EVDNS_LOG_DEBUG, "Retransmitting request %p; tx_count==%d", 1.2168 + arg, req->tx_count); 1.2169 + (void) evtimer_del(&req->timeout_event); 1.2170 + new_ns = nameserver_pick(base); 1.2171 + if (new_ns) 1.2172 + req->ns = new_ns; 1.2173 + evdns_request_transmit(req); 1.2174 + } 1.2175 + EVDNS_UNLOCK(base); 1.2176 +} 1.2177 + 1.2178 +/* try to send a request to a given server. */ 1.2179 +/* */ 1.2180 +/* return: */ 1.2181 +/* 0 ok */ 1.2182 +/* 1 temporary failure */ 1.2183 +/* 2 other failure */ 1.2184 +static int 1.2185 +evdns_request_transmit_to(struct request *req, struct nameserver *server) { 1.2186 + int r; 1.2187 + ASSERT_LOCKED(req->base); 1.2188 + ASSERT_VALID_REQUEST(req); 1.2189 + r = sendto(server->socket, (void*)req->request, req->request_len, 0, 1.2190 + (struct sockaddr *)&server->address, server->addrlen); 1.2191 + if (r < 0) { 1.2192 + int err = evutil_socket_geterror(server->socket); 1.2193 + if (EVUTIL_ERR_RW_RETRIABLE(err)) 1.2194 + return 1; 1.2195 + nameserver_failed(req->ns, evutil_socket_error_to_string(err)); 1.2196 + return 2; 1.2197 + } else if (r != (int)req->request_len) { 1.2198 + return 1; /* short write */ 1.2199 + } else { 1.2200 + return 0; 1.2201 + } 1.2202 +} 1.2203 + 1.2204 +/* try to send a request, updating the fields of the request */ 1.2205 +/* as needed */ 1.2206 +/* */ 1.2207 +/* return: */ 1.2208 +/* 0 ok */ 1.2209 +/* 1 failed */ 1.2210 +static int 1.2211 +evdns_request_transmit(struct request *req) { 1.2212 + int retcode = 0, r; 1.2213 + 1.2214 + ASSERT_LOCKED(req->base); 1.2215 + ASSERT_VALID_REQUEST(req); 1.2216 + /* if we fail to send this packet then this flag marks it */ 1.2217 + /* for evdns_transmit */ 1.2218 + req->transmit_me = 1; 1.2219 + EVUTIL_ASSERT(req->trans_id != 0xffff); 1.2220 + 1.2221 + if (req->ns->choked) { 1.2222 + /* don't bother trying to write to a socket */ 1.2223 + /* which we have had EAGAIN from */ 1.2224 + return 1; 1.2225 + } 1.2226 + 1.2227 + r = evdns_request_transmit_to(req, req->ns); 1.2228 + switch (r) { 1.2229 + case 1: 1.2230 + /* temp failure */ 1.2231 + req->ns->choked = 1; 1.2232 + nameserver_write_waiting(req->ns, 1); 1.2233 + return 1; 1.2234 + case 2: 1.2235 + /* failed to transmit the request entirely. */ 1.2236 + retcode = 1; 1.2237 + /* fall through: we'll set a timeout, which will time out, 1.2238 + * and make us retransmit the request anyway. */ 1.2239 + default: 1.2240 + /* all ok */ 1.2241 + log(EVDNS_LOG_DEBUG, 1.2242 + "Setting timeout for request %p, sent to nameserver %p", req, req->ns); 1.2243 + if (evtimer_add(&req->timeout_event, &req->base->global_timeout) < 0) { 1.2244 + log(EVDNS_LOG_WARN, 1.2245 + "Error from libevent when adding timer for request %p", 1.2246 + req); 1.2247 + /* ???? Do more? */ 1.2248 + } 1.2249 + req->tx_count++; 1.2250 + req->transmit_me = 0; 1.2251 + return retcode; 1.2252 + } 1.2253 +} 1.2254 + 1.2255 +static void 1.2256 +nameserver_probe_callback(int result, char type, int count, int ttl, void *addresses, void *arg) { 1.2257 + struct nameserver *const ns = (struct nameserver *) arg; 1.2258 + (void) type; 1.2259 + (void) count; 1.2260 + (void) ttl; 1.2261 + (void) addresses; 1.2262 + 1.2263 + if (result == DNS_ERR_CANCEL) { 1.2264 + /* We canceled this request because the nameserver came up 1.2265 + * for some other reason. Do not change our opinion about 1.2266 + * the nameserver. */ 1.2267 + return; 1.2268 + } 1.2269 + 1.2270 + EVDNS_LOCK(ns->base); 1.2271 + ns->probe_request = NULL; 1.2272 + if (result == DNS_ERR_NONE || result == DNS_ERR_NOTEXIST) { 1.2273 + /* this is a good reply */ 1.2274 + nameserver_up(ns); 1.2275 + } else { 1.2276 + nameserver_probe_failed(ns); 1.2277 + } 1.2278 + EVDNS_UNLOCK(ns->base); 1.2279 +} 1.2280 + 1.2281 +static void 1.2282 +nameserver_send_probe(struct nameserver *const ns) { 1.2283 + struct evdns_request *handle; 1.2284 + struct request *req; 1.2285 + char addrbuf[128]; 1.2286 + /* here we need to send a probe to a given nameserver */ 1.2287 + /* in the hope that it is up now. */ 1.2288 + 1.2289 + ASSERT_LOCKED(ns->base); 1.2290 + log(EVDNS_LOG_DEBUG, "Sending probe to %s", 1.2291 + evutil_format_sockaddr_port( 1.2292 + (struct sockaddr *)&ns->address, 1.2293 + addrbuf, sizeof(addrbuf))); 1.2294 + handle = mm_calloc(1, sizeof(*handle)); 1.2295 + if (!handle) return; 1.2296 + req = request_new(ns->base, handle, TYPE_A, "google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_callback, ns); 1.2297 + if (!req) { 1.2298 + mm_free(handle); 1.2299 + return; 1.2300 + } 1.2301 + ns->probe_request = handle; 1.2302 + /* we force this into the inflight queue no matter what */ 1.2303 + request_trans_id_set(req, transaction_id_pick(ns->base)); 1.2304 + req->ns = ns; 1.2305 + request_submit(req); 1.2306 +} 1.2307 + 1.2308 +/* returns: */ 1.2309 +/* 0 didn't try to transmit anything */ 1.2310 +/* 1 tried to transmit something */ 1.2311 +static int 1.2312 +evdns_transmit(struct evdns_base *base) { 1.2313 + char did_try_to_transmit = 0; 1.2314 + int i; 1.2315 + 1.2316 + ASSERT_LOCKED(base); 1.2317 + for (i = 0; i < base->n_req_heads; ++i) { 1.2318 + if (base->req_heads[i]) { 1.2319 + struct request *const started_at = base->req_heads[i], *req = started_at; 1.2320 + /* first transmit all the requests which are currently waiting */ 1.2321 + do { 1.2322 + if (req->transmit_me) { 1.2323 + did_try_to_transmit = 1; 1.2324 + evdns_request_transmit(req); 1.2325 + } 1.2326 + 1.2327 + req = req->next; 1.2328 + } while (req != started_at); 1.2329 + } 1.2330 + } 1.2331 + 1.2332 + return did_try_to_transmit; 1.2333 +} 1.2334 + 1.2335 +/* exported function */ 1.2336 +int 1.2337 +evdns_base_count_nameservers(struct evdns_base *base) 1.2338 +{ 1.2339 + const struct nameserver *server; 1.2340 + int n = 0; 1.2341 + 1.2342 + EVDNS_LOCK(base); 1.2343 + server = base->server_head; 1.2344 + if (!server) 1.2345 + goto done; 1.2346 + do { 1.2347 + ++n; 1.2348 + server = server->next; 1.2349 + } while (server != base->server_head); 1.2350 +done: 1.2351 + EVDNS_UNLOCK(base); 1.2352 + return n; 1.2353 +} 1.2354 + 1.2355 +int 1.2356 +evdns_count_nameservers(void) 1.2357 +{ 1.2358 + return evdns_base_count_nameservers(current_base); 1.2359 +} 1.2360 + 1.2361 +/* exported function */ 1.2362 +int 1.2363 +evdns_base_clear_nameservers_and_suspend(struct evdns_base *base) 1.2364 +{ 1.2365 + struct nameserver *server, *started_at; 1.2366 + int i; 1.2367 + 1.2368 + EVDNS_LOCK(base); 1.2369 + server = base->server_head; 1.2370 + started_at = base->server_head; 1.2371 + if (!server) { 1.2372 + EVDNS_UNLOCK(base); 1.2373 + return 0; 1.2374 + } 1.2375 + while (1) { 1.2376 + struct nameserver *next = server->next; 1.2377 + (void) event_del(&server->event); 1.2378 + if (evtimer_initialized(&server->timeout_event)) 1.2379 + (void) evtimer_del(&server->timeout_event); 1.2380 + if (server->probe_request) { 1.2381 + evdns_cancel_request(server->base, server->probe_request); 1.2382 + server->probe_request = NULL; 1.2383 + } 1.2384 + if (server->socket >= 0) 1.2385 + evutil_closesocket(server->socket); 1.2386 + mm_free(server); 1.2387 + if (next == started_at) 1.2388 + break; 1.2389 + server = next; 1.2390 + } 1.2391 + base->server_head = NULL; 1.2392 + base->global_good_nameservers = 0; 1.2393 + 1.2394 + for (i = 0; i < base->n_req_heads; ++i) { 1.2395 + struct request *req, *req_started_at; 1.2396 + req = req_started_at = base->req_heads[i]; 1.2397 + while (req) { 1.2398 + struct request *next = req->next; 1.2399 + req->tx_count = req->reissue_count = 0; 1.2400 + req->ns = NULL; 1.2401 + /* ???? What to do about searches? */ 1.2402 + (void) evtimer_del(&req->timeout_event); 1.2403 + req->trans_id = 0; 1.2404 + req->transmit_me = 0; 1.2405 + 1.2406 + base->global_requests_waiting++; 1.2407 + evdns_request_insert(req, &base->req_waiting_head); 1.2408 + /* We want to insert these suspended elements at the front of 1.2409 + * the waiting queue, since they were pending before any of 1.2410 + * the waiting entries were added. This is a circular list, 1.2411 + * so we can just shift the start back by one.*/ 1.2412 + base->req_waiting_head = base->req_waiting_head->prev; 1.2413 + 1.2414 + if (next == req_started_at) 1.2415 + break; 1.2416 + req = next; 1.2417 + } 1.2418 + base->req_heads[i] = NULL; 1.2419 + } 1.2420 + 1.2421 + base->global_requests_inflight = 0; 1.2422 + 1.2423 + EVDNS_UNLOCK(base); 1.2424 + return 0; 1.2425 +} 1.2426 + 1.2427 +int 1.2428 +evdns_clear_nameservers_and_suspend(void) 1.2429 +{ 1.2430 + return evdns_base_clear_nameservers_and_suspend(current_base); 1.2431 +} 1.2432 + 1.2433 + 1.2434 +/* exported function */ 1.2435 +int 1.2436 +evdns_base_resume(struct evdns_base *base) 1.2437 +{ 1.2438 + EVDNS_LOCK(base); 1.2439 + evdns_requests_pump_waiting_queue(base); 1.2440 + EVDNS_UNLOCK(base); 1.2441 + return 0; 1.2442 +} 1.2443 + 1.2444 +int 1.2445 +evdns_resume(void) 1.2446 +{ 1.2447 + return evdns_base_resume(current_base); 1.2448 +} 1.2449 + 1.2450 +static int 1.2451 +_evdns_nameserver_add_impl(struct evdns_base *base, const struct sockaddr *address, int addrlen) { 1.2452 + /* first check to see if we already have this nameserver */ 1.2453 + 1.2454 + const struct nameserver *server = base->server_head, *const started_at = base->server_head; 1.2455 + struct nameserver *ns; 1.2456 + int err = 0; 1.2457 + char addrbuf[128]; 1.2458 + 1.2459 + ASSERT_LOCKED(base); 1.2460 + if (server) { 1.2461 + do { 1.2462 + if (!evutil_sockaddr_cmp((struct sockaddr*)&server->address, address, 1)) return 3; 1.2463 + server = server->next; 1.2464 + } while (server != started_at); 1.2465 + } 1.2466 + if (addrlen > (int)sizeof(ns->address)) { 1.2467 + log(EVDNS_LOG_DEBUG, "Addrlen %d too long.", (int)addrlen); 1.2468 + return 2; 1.2469 + } 1.2470 + 1.2471 + ns = (struct nameserver *) mm_malloc(sizeof(struct nameserver)); 1.2472 + if (!ns) return -1; 1.2473 + 1.2474 + memset(ns, 0, sizeof(struct nameserver)); 1.2475 + ns->base = base; 1.2476 + 1.2477 + evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns); 1.2478 + 1.2479 + ns->socket = socket(address->sa_family, SOCK_DGRAM, 0); 1.2480 + if (ns->socket < 0) { err = 1; goto out1; } 1.2481 + evutil_make_socket_closeonexec(ns->socket); 1.2482 + evutil_make_socket_nonblocking(ns->socket); 1.2483 + 1.2484 + if (base->global_outgoing_addrlen && 1.2485 + !evutil_sockaddr_is_loopback(address)) { 1.2486 + if (bind(ns->socket, 1.2487 + (struct sockaddr*)&base->global_outgoing_address, 1.2488 + base->global_outgoing_addrlen) < 0) { 1.2489 + log(EVDNS_LOG_WARN,"Couldn't bind to outgoing address"); 1.2490 + err = 2; 1.2491 + goto out2; 1.2492 + } 1.2493 + } 1.2494 + 1.2495 + memcpy(&ns->address, address, addrlen); 1.2496 + ns->addrlen = addrlen; 1.2497 + ns->state = 1; 1.2498 + event_assign(&ns->event, ns->base->event_base, ns->socket, EV_READ | EV_PERSIST, nameserver_ready_callback, ns); 1.2499 + if (event_add(&ns->event, NULL) < 0) { 1.2500 + err = 2; 1.2501 + goto out2; 1.2502 + } 1.2503 + 1.2504 + log(EVDNS_LOG_DEBUG, "Added nameserver %s as %p", 1.2505 + evutil_format_sockaddr_port(address, addrbuf, sizeof(addrbuf)), ns); 1.2506 + 1.2507 + /* insert this nameserver into the list of them */ 1.2508 + if (!base->server_head) { 1.2509 + ns->next = ns->prev = ns; 1.2510 + base->server_head = ns; 1.2511 + } else { 1.2512 + ns->next = base->server_head->next; 1.2513 + ns->prev = base->server_head; 1.2514 + base->server_head->next = ns; 1.2515 + ns->next->prev = ns; 1.2516 + } 1.2517 + 1.2518 + base->global_good_nameservers++; 1.2519 + 1.2520 + return 0; 1.2521 + 1.2522 +out2: 1.2523 + evutil_closesocket(ns->socket); 1.2524 +out1: 1.2525 + event_debug_unassign(&ns->event); 1.2526 + mm_free(ns); 1.2527 + log(EVDNS_LOG_WARN, "Unable to add nameserver %s: error %d", 1.2528 + evutil_format_sockaddr_port(address, addrbuf, sizeof(addrbuf)), err); 1.2529 + return err; 1.2530 +} 1.2531 + 1.2532 +/* exported function */ 1.2533 +int 1.2534 +evdns_base_nameserver_add(struct evdns_base *base, unsigned long int address) 1.2535 +{ 1.2536 + struct sockaddr_in sin; 1.2537 + int res; 1.2538 + memset(&sin, 0, sizeof(sin)); 1.2539 + sin.sin_addr.s_addr = address; 1.2540 + sin.sin_port = htons(53); 1.2541 + sin.sin_family = AF_INET; 1.2542 + EVDNS_LOCK(base); 1.2543 + res = _evdns_nameserver_add_impl(base, (struct sockaddr*)&sin, sizeof(sin)); 1.2544 + EVDNS_UNLOCK(base); 1.2545 + return res; 1.2546 +} 1.2547 + 1.2548 +int 1.2549 +evdns_nameserver_add(unsigned long int address) { 1.2550 + if (!current_base) 1.2551 + current_base = evdns_base_new(NULL, 0); 1.2552 + return evdns_base_nameserver_add(current_base, address); 1.2553 +} 1.2554 + 1.2555 +static void 1.2556 +sockaddr_setport(struct sockaddr *sa, ev_uint16_t port) 1.2557 +{ 1.2558 + if (sa->sa_family == AF_INET) { 1.2559 + ((struct sockaddr_in *)sa)->sin_port = htons(port); 1.2560 + } else if (sa->sa_family == AF_INET6) { 1.2561 + ((struct sockaddr_in6 *)sa)->sin6_port = htons(port); 1.2562 + } 1.2563 +} 1.2564 + 1.2565 +static ev_uint16_t 1.2566 +sockaddr_getport(struct sockaddr *sa) 1.2567 +{ 1.2568 + if (sa->sa_family == AF_INET) { 1.2569 + return ntohs(((struct sockaddr_in *)sa)->sin_port); 1.2570 + } else if (sa->sa_family == AF_INET6) { 1.2571 + return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 1.2572 + } else { 1.2573 + return 0; 1.2574 + } 1.2575 +} 1.2576 + 1.2577 +/* exported function */ 1.2578 +int 1.2579 +evdns_base_nameserver_ip_add(struct evdns_base *base, const char *ip_as_string) { 1.2580 + struct sockaddr_storage ss; 1.2581 + struct sockaddr *sa; 1.2582 + int len = sizeof(ss); 1.2583 + int res; 1.2584 + if (evutil_parse_sockaddr_port(ip_as_string, (struct sockaddr *)&ss, 1.2585 + &len)) { 1.2586 + log(EVDNS_LOG_WARN, "Unable to parse nameserver address %s", 1.2587 + ip_as_string); 1.2588 + return 4; 1.2589 + } 1.2590 + sa = (struct sockaddr *) &ss; 1.2591 + if (sockaddr_getport(sa) == 0) 1.2592 + sockaddr_setport(sa, 53); 1.2593 + 1.2594 + EVDNS_LOCK(base); 1.2595 + res = _evdns_nameserver_add_impl(base, sa, len); 1.2596 + EVDNS_UNLOCK(base); 1.2597 + return res; 1.2598 +} 1.2599 + 1.2600 +int 1.2601 +evdns_nameserver_ip_add(const char *ip_as_string) { 1.2602 + if (!current_base) 1.2603 + current_base = evdns_base_new(NULL, 0); 1.2604 + return evdns_base_nameserver_ip_add(current_base, ip_as_string); 1.2605 +} 1.2606 + 1.2607 +int 1.2608 +evdns_base_nameserver_sockaddr_add(struct evdns_base *base, 1.2609 + const struct sockaddr *sa, ev_socklen_t len, unsigned flags) 1.2610 +{ 1.2611 + int res; 1.2612 + EVUTIL_ASSERT(base); 1.2613 + EVDNS_LOCK(base); 1.2614 + res = _evdns_nameserver_add_impl(base, sa, len); 1.2615 + EVDNS_UNLOCK(base); 1.2616 + return res; 1.2617 +} 1.2618 + 1.2619 +/* remove from the queue */ 1.2620 +static void 1.2621 +evdns_request_remove(struct request *req, struct request **head) 1.2622 +{ 1.2623 + ASSERT_LOCKED(req->base); 1.2624 + ASSERT_VALID_REQUEST(req); 1.2625 + 1.2626 +#if 0 1.2627 + { 1.2628 + struct request *ptr; 1.2629 + int found = 0; 1.2630 + EVUTIL_ASSERT(*head != NULL); 1.2631 + 1.2632 + ptr = *head; 1.2633 + do { 1.2634 + if (ptr == req) { 1.2635 + found = 1; 1.2636 + break; 1.2637 + } 1.2638 + ptr = ptr->next; 1.2639 + } while (ptr != *head); 1.2640 + EVUTIL_ASSERT(found); 1.2641 + 1.2642 + EVUTIL_ASSERT(req->next); 1.2643 + } 1.2644 +#endif 1.2645 + 1.2646 + if (req->next == req) { 1.2647 + /* only item in the list */ 1.2648 + *head = NULL; 1.2649 + } else { 1.2650 + req->next->prev = req->prev; 1.2651 + req->prev->next = req->next; 1.2652 + if (*head == req) *head = req->next; 1.2653 + } 1.2654 + req->next = req->prev = NULL; 1.2655 +} 1.2656 + 1.2657 +/* insert into the tail of the queue */ 1.2658 +static void 1.2659 +evdns_request_insert(struct request *req, struct request **head) { 1.2660 + ASSERT_LOCKED(req->base); 1.2661 + ASSERT_VALID_REQUEST(req); 1.2662 + if (!*head) { 1.2663 + *head = req; 1.2664 + req->next = req->prev = req; 1.2665 + return; 1.2666 + } 1.2667 + 1.2668 + req->prev = (*head)->prev; 1.2669 + req->prev->next = req; 1.2670 + req->next = *head; 1.2671 + (*head)->prev = req; 1.2672 +} 1.2673 + 1.2674 +static int 1.2675 +string_num_dots(const char *s) { 1.2676 + int count = 0; 1.2677 + while ((s = strchr(s, '.'))) { 1.2678 + s++; 1.2679 + count++; 1.2680 + } 1.2681 + return count; 1.2682 +} 1.2683 + 1.2684 +static struct request * 1.2685 +request_new(struct evdns_base *base, struct evdns_request *handle, int type, 1.2686 + const char *name, int flags, evdns_callback_type callback, 1.2687 + void *user_ptr) { 1.2688 + 1.2689 + const char issuing_now = 1.2690 + (base->global_requests_inflight < base->global_max_requests_inflight) ? 1 : 0; 1.2691 + 1.2692 + const size_t name_len = strlen(name); 1.2693 + const size_t request_max_len = evdns_request_len(name_len); 1.2694 + const u16 trans_id = issuing_now ? transaction_id_pick(base) : 0xffff; 1.2695 + /* the request data is alloced in a single block with the header */ 1.2696 + struct request *const req = 1.2697 + mm_malloc(sizeof(struct request) + request_max_len); 1.2698 + int rlen; 1.2699 + char namebuf[256]; 1.2700 + (void) flags; 1.2701 + 1.2702 + ASSERT_LOCKED(base); 1.2703 + 1.2704 + if (!req) return NULL; 1.2705 + 1.2706 + if (name_len >= sizeof(namebuf)) { 1.2707 + mm_free(req); 1.2708 + return NULL; 1.2709 + } 1.2710 + 1.2711 + memset(req, 0, sizeof(struct request)); 1.2712 + req->base = base; 1.2713 + 1.2714 + evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req); 1.2715 + 1.2716 + if (base->global_randomize_case) { 1.2717 + unsigned i; 1.2718 + char randbits[(sizeof(namebuf)+7)/8]; 1.2719 + strlcpy(namebuf, name, sizeof(namebuf)); 1.2720 + evutil_secure_rng_get_bytes(randbits, (name_len+7)/8); 1.2721 + for (i = 0; i < name_len; ++i) { 1.2722 + if (EVUTIL_ISALPHA(namebuf[i])) { 1.2723 + if ((randbits[i >> 3] & (1<<(i & 7)))) 1.2724 + namebuf[i] |= 0x20; 1.2725 + else 1.2726 + namebuf[i] &= ~0x20; 1.2727 + } 1.2728 + } 1.2729 + name = namebuf; 1.2730 + } 1.2731 + 1.2732 + /* request data lives just after the header */ 1.2733 + req->request = ((u8 *) req) + sizeof(struct request); 1.2734 + /* denotes that the request data shouldn't be free()ed */ 1.2735 + req->request_appended = 1; 1.2736 + rlen = evdns_request_data_build(name, name_len, trans_id, 1.2737 + type, CLASS_INET, req->request, request_max_len); 1.2738 + if (rlen < 0) 1.2739 + goto err1; 1.2740 + 1.2741 + req->request_len = rlen; 1.2742 + req->trans_id = trans_id; 1.2743 + req->tx_count = 0; 1.2744 + req->request_type = type; 1.2745 + req->user_pointer = user_ptr; 1.2746 + req->user_callback = callback; 1.2747 + req->ns = issuing_now ? nameserver_pick(base) : NULL; 1.2748 + req->next = req->prev = NULL; 1.2749 + req->handle = handle; 1.2750 + if (handle) { 1.2751 + handle->current_req = req; 1.2752 + handle->base = base; 1.2753 + } 1.2754 + 1.2755 + return req; 1.2756 +err1: 1.2757 + mm_free(req); 1.2758 + return NULL; 1.2759 +} 1.2760 + 1.2761 +static void 1.2762 +request_submit(struct request *const req) { 1.2763 + struct evdns_base *base = req->base; 1.2764 + ASSERT_LOCKED(base); 1.2765 + ASSERT_VALID_REQUEST(req); 1.2766 + if (req->ns) { 1.2767 + /* if it has a nameserver assigned then this is going */ 1.2768 + /* straight into the inflight queue */ 1.2769 + evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); 1.2770 + base->global_requests_inflight++; 1.2771 + evdns_request_transmit(req); 1.2772 + } else { 1.2773 + evdns_request_insert(req, &base->req_waiting_head); 1.2774 + base->global_requests_waiting++; 1.2775 + } 1.2776 +} 1.2777 + 1.2778 +/* exported function */ 1.2779 +void 1.2780 +evdns_cancel_request(struct evdns_base *base, struct evdns_request *handle) 1.2781 +{ 1.2782 + struct request *req; 1.2783 + 1.2784 + if (!handle->current_req) 1.2785 + return; 1.2786 + 1.2787 + if (!base) { 1.2788 + /* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */ 1.2789 + base = handle->base; 1.2790 + if (!base) 1.2791 + base = handle->current_req->base; 1.2792 + } 1.2793 + 1.2794 + EVDNS_LOCK(base); 1.2795 + if (handle->pending_cb) { 1.2796 + EVDNS_UNLOCK(base); 1.2797 + return; 1.2798 + } 1.2799 + 1.2800 + req = handle->current_req; 1.2801 + ASSERT_VALID_REQUEST(req); 1.2802 + 1.2803 + reply_schedule_callback(req, 0, DNS_ERR_CANCEL, NULL); 1.2804 + if (req->ns) { 1.2805 + /* remove from inflight queue */ 1.2806 + request_finished(req, &REQ_HEAD(base, req->trans_id), 1); 1.2807 + } else { 1.2808 + /* remove from global_waiting head */ 1.2809 + request_finished(req, &base->req_waiting_head, 1); 1.2810 + } 1.2811 + EVDNS_UNLOCK(base); 1.2812 +} 1.2813 + 1.2814 +/* exported function */ 1.2815 +struct evdns_request * 1.2816 +evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, 1.2817 + evdns_callback_type callback, void *ptr) { 1.2818 + struct evdns_request *handle; 1.2819 + struct request *req; 1.2820 + log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); 1.2821 + handle = mm_calloc(1, sizeof(*handle)); 1.2822 + if (handle == NULL) 1.2823 + return NULL; 1.2824 + EVDNS_LOCK(base); 1.2825 + if (flags & DNS_QUERY_NO_SEARCH) { 1.2826 + req = 1.2827 + request_new(base, handle, TYPE_A, name, flags, 1.2828 + callback, ptr); 1.2829 + if (req) 1.2830 + request_submit(req); 1.2831 + } else { 1.2832 + search_request_new(base, handle, TYPE_A, name, flags, 1.2833 + callback, ptr); 1.2834 + } 1.2835 + if (handle->current_req == NULL) { 1.2836 + mm_free(handle); 1.2837 + handle = NULL; 1.2838 + } 1.2839 + EVDNS_UNLOCK(base); 1.2840 + return handle; 1.2841 +} 1.2842 + 1.2843 +int evdns_resolve_ipv4(const char *name, int flags, 1.2844 + evdns_callback_type callback, void *ptr) 1.2845 +{ 1.2846 + return evdns_base_resolve_ipv4(current_base, name, flags, callback, ptr) 1.2847 + ? 0 : -1; 1.2848 +} 1.2849 + 1.2850 + 1.2851 +/* exported function */ 1.2852 +struct evdns_request * 1.2853 +evdns_base_resolve_ipv6(struct evdns_base *base, 1.2854 + const char *name, int flags, 1.2855 + evdns_callback_type callback, void *ptr) 1.2856 +{ 1.2857 + struct evdns_request *handle; 1.2858 + struct request *req; 1.2859 + log(EVDNS_LOG_DEBUG, "Resolve requested for %s", name); 1.2860 + handle = mm_calloc(1, sizeof(*handle)); 1.2861 + if (handle == NULL) 1.2862 + return NULL; 1.2863 + EVDNS_LOCK(base); 1.2864 + if (flags & DNS_QUERY_NO_SEARCH) { 1.2865 + req = request_new(base, handle, TYPE_AAAA, name, flags, 1.2866 + callback, ptr); 1.2867 + if (req) 1.2868 + request_submit(req); 1.2869 + } else { 1.2870 + search_request_new(base, handle, TYPE_AAAA, name, flags, 1.2871 + callback, ptr); 1.2872 + } 1.2873 + if (handle->current_req == NULL) { 1.2874 + mm_free(handle); 1.2875 + handle = NULL; 1.2876 + } 1.2877 + EVDNS_UNLOCK(base); 1.2878 + return handle; 1.2879 +} 1.2880 + 1.2881 +int evdns_resolve_ipv6(const char *name, int flags, 1.2882 + evdns_callback_type callback, void *ptr) { 1.2883 + return evdns_base_resolve_ipv6(current_base, name, flags, callback, ptr) 1.2884 + ? 0 : -1; 1.2885 +} 1.2886 + 1.2887 +struct evdns_request * 1.2888 +evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { 1.2889 + char buf[32]; 1.2890 + struct evdns_request *handle; 1.2891 + struct request *req; 1.2892 + u32 a; 1.2893 + EVUTIL_ASSERT(in); 1.2894 + a = ntohl(in->s_addr); 1.2895 + evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", 1.2896 + (int)(u8)((a )&0xff), 1.2897 + (int)(u8)((a>>8 )&0xff), 1.2898 + (int)(u8)((a>>16)&0xff), 1.2899 + (int)(u8)((a>>24)&0xff)); 1.2900 + handle = mm_calloc(1, sizeof(*handle)); 1.2901 + if (handle == NULL) 1.2902 + return NULL; 1.2903 + log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); 1.2904 + EVDNS_LOCK(base); 1.2905 + req = request_new(base, handle, TYPE_PTR, buf, flags, callback, ptr); 1.2906 + if (req) 1.2907 + request_submit(req); 1.2908 + if (handle->current_req == NULL) { 1.2909 + mm_free(handle); 1.2910 + handle = NULL; 1.2911 + } 1.2912 + EVDNS_UNLOCK(base); 1.2913 + return (handle); 1.2914 +} 1.2915 + 1.2916 +int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr) { 1.2917 + return evdns_base_resolve_reverse(current_base, in, flags, callback, ptr) 1.2918 + ? 0 : -1; 1.2919 +} 1.2920 + 1.2921 +struct evdns_request * 1.2922 +evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { 1.2923 + /* 32 nybbles, 32 periods, "ip6.arpa", NUL. */ 1.2924 + char buf[73]; 1.2925 + char *cp; 1.2926 + struct evdns_request *handle; 1.2927 + struct request *req; 1.2928 + int i; 1.2929 + EVUTIL_ASSERT(in); 1.2930 + cp = buf; 1.2931 + for (i=15; i >= 0; --i) { 1.2932 + u8 byte = in->s6_addr[i]; 1.2933 + *cp++ = "0123456789abcdef"[byte & 0x0f]; 1.2934 + *cp++ = '.'; 1.2935 + *cp++ = "0123456789abcdef"[byte >> 4]; 1.2936 + *cp++ = '.'; 1.2937 + } 1.2938 + EVUTIL_ASSERT(cp + strlen("ip6.arpa") < buf+sizeof(buf)); 1.2939 + memcpy(cp, "ip6.arpa", strlen("ip6.arpa")+1); 1.2940 + handle = mm_calloc(1, sizeof(*handle)); 1.2941 + if (handle == NULL) 1.2942 + return NULL; 1.2943 + log(EVDNS_LOG_DEBUG, "Resolve requested for %s (reverse)", buf); 1.2944 + EVDNS_LOCK(base); 1.2945 + req = request_new(base, handle, TYPE_PTR, buf, flags, callback, ptr); 1.2946 + if (req) 1.2947 + request_submit(req); 1.2948 + if (handle->current_req == NULL) { 1.2949 + mm_free(handle); 1.2950 + handle = NULL; 1.2951 + } 1.2952 + EVDNS_UNLOCK(base); 1.2953 + return (handle); 1.2954 +} 1.2955 + 1.2956 +int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr) { 1.2957 + return evdns_base_resolve_reverse_ipv6(current_base, in, flags, callback, ptr) 1.2958 + ? 0 : -1; 1.2959 +} 1.2960 + 1.2961 +/* ================================================================= */ 1.2962 +/* Search support */ 1.2963 +/* */ 1.2964 +/* the libc resolver has support for searching a number of domains */ 1.2965 +/* to find a name. If nothing else then it takes the single domain */ 1.2966 +/* from the gethostname() call. */ 1.2967 +/* */ 1.2968 +/* It can also be configured via the domain and search options in a */ 1.2969 +/* resolv.conf. */ 1.2970 +/* */ 1.2971 +/* The ndots option controls how many dots it takes for the resolver */ 1.2972 +/* to decide that a name is non-local and so try a raw lookup first. */ 1.2973 + 1.2974 +struct search_domain { 1.2975 + int len; 1.2976 + struct search_domain *next; 1.2977 + /* the text string is appended to this structure */ 1.2978 +}; 1.2979 + 1.2980 +struct search_state { 1.2981 + int refcount; 1.2982 + int ndots; 1.2983 + int num_domains; 1.2984 + struct search_domain *head; 1.2985 +}; 1.2986 + 1.2987 +static void 1.2988 +search_state_decref(struct search_state *const state) { 1.2989 + if (!state) return; 1.2990 + state->refcount--; 1.2991 + if (!state->refcount) { 1.2992 + struct search_domain *next, *dom; 1.2993 + for (dom = state->head; dom; dom = next) { 1.2994 + next = dom->next; 1.2995 + mm_free(dom); 1.2996 + } 1.2997 + mm_free(state); 1.2998 + } 1.2999 +} 1.3000 + 1.3001 +static struct search_state * 1.3002 +search_state_new(void) { 1.3003 + struct search_state *state = (struct search_state *) mm_malloc(sizeof(struct search_state)); 1.3004 + if (!state) return NULL; 1.3005 + memset(state, 0, sizeof(struct search_state)); 1.3006 + state->refcount = 1; 1.3007 + state->ndots = 1; 1.3008 + 1.3009 + return state; 1.3010 +} 1.3011 + 1.3012 +static void 1.3013 +search_postfix_clear(struct evdns_base *base) { 1.3014 + search_state_decref(base->global_search_state); 1.3015 + 1.3016 + base->global_search_state = search_state_new(); 1.3017 +} 1.3018 + 1.3019 +/* exported function */ 1.3020 +void 1.3021 +evdns_base_search_clear(struct evdns_base *base) 1.3022 +{ 1.3023 + EVDNS_LOCK(base); 1.3024 + search_postfix_clear(base); 1.3025 + EVDNS_UNLOCK(base); 1.3026 +} 1.3027 + 1.3028 +void 1.3029 +evdns_search_clear(void) { 1.3030 + evdns_base_search_clear(current_base); 1.3031 +} 1.3032 + 1.3033 +static void 1.3034 +search_postfix_add(struct evdns_base *base, const char *domain) { 1.3035 + size_t domain_len; 1.3036 + struct search_domain *sdomain; 1.3037 + while (domain[0] == '.') domain++; 1.3038 + domain_len = strlen(domain); 1.3039 + 1.3040 + ASSERT_LOCKED(base); 1.3041 + if (!base->global_search_state) base->global_search_state = search_state_new(); 1.3042 + if (!base->global_search_state) return; 1.3043 + base->global_search_state->num_domains++; 1.3044 + 1.3045 + sdomain = (struct search_domain *) mm_malloc(sizeof(struct search_domain) + domain_len); 1.3046 + if (!sdomain) return; 1.3047 + memcpy( ((u8 *) sdomain) + sizeof(struct search_domain), domain, domain_len); 1.3048 + sdomain->next = base->global_search_state->head; 1.3049 + sdomain->len = (int) domain_len; 1.3050 + 1.3051 + base->global_search_state->head = sdomain; 1.3052 +} 1.3053 + 1.3054 +/* reverse the order of members in the postfix list. This is needed because, */ 1.3055 +/* when parsing resolv.conf we push elements in the wrong order */ 1.3056 +static void 1.3057 +search_reverse(struct evdns_base *base) { 1.3058 + struct search_domain *cur, *prev = NULL, *next; 1.3059 + ASSERT_LOCKED(base); 1.3060 + cur = base->global_search_state->head; 1.3061 + while (cur) { 1.3062 + next = cur->next; 1.3063 + cur->next = prev; 1.3064 + prev = cur; 1.3065 + cur = next; 1.3066 + } 1.3067 + 1.3068 + base->global_search_state->head = prev; 1.3069 +} 1.3070 + 1.3071 +/* exported function */ 1.3072 +void 1.3073 +evdns_base_search_add(struct evdns_base *base, const char *domain) { 1.3074 + EVDNS_LOCK(base); 1.3075 + search_postfix_add(base, domain); 1.3076 + EVDNS_UNLOCK(base); 1.3077 +} 1.3078 +void 1.3079 +evdns_search_add(const char *domain) { 1.3080 + evdns_base_search_add(current_base, domain); 1.3081 +} 1.3082 + 1.3083 +/* exported function */ 1.3084 +void 1.3085 +evdns_base_search_ndots_set(struct evdns_base *base, const int ndots) { 1.3086 + EVDNS_LOCK(base); 1.3087 + if (!base->global_search_state) base->global_search_state = search_state_new(); 1.3088 + if (base->global_search_state) 1.3089 + base->global_search_state->ndots = ndots; 1.3090 + EVDNS_UNLOCK(base); 1.3091 +} 1.3092 +void 1.3093 +evdns_search_ndots_set(const int ndots) { 1.3094 + evdns_base_search_ndots_set(current_base, ndots); 1.3095 +} 1.3096 + 1.3097 +static void 1.3098 +search_set_from_hostname(struct evdns_base *base) { 1.3099 + char hostname[HOST_NAME_MAX + 1], *domainname; 1.3100 + 1.3101 + ASSERT_LOCKED(base); 1.3102 + search_postfix_clear(base); 1.3103 + if (gethostname(hostname, sizeof(hostname))) return; 1.3104 + domainname = strchr(hostname, '.'); 1.3105 + if (!domainname) return; 1.3106 + search_postfix_add(base, domainname); 1.3107 +} 1.3108 + 1.3109 +/* warning: returns malloced string */ 1.3110 +static char * 1.3111 +search_make_new(const struct search_state *const state, int n, const char *const base_name) { 1.3112 + const size_t base_len = strlen(base_name); 1.3113 + const char need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; 1.3114 + struct search_domain *dom; 1.3115 + 1.3116 + for (dom = state->head; dom; dom = dom->next) { 1.3117 + if (!n--) { 1.3118 + /* this is the postfix we want */ 1.3119 + /* the actual postfix string is kept at the end of the structure */ 1.3120 + const u8 *const postfix = ((u8 *) dom) + sizeof(struct search_domain); 1.3121 + const int postfix_len = dom->len; 1.3122 + char *const newname = (char *) mm_malloc(base_len + need_to_append_dot + postfix_len + 1); 1.3123 + if (!newname) return NULL; 1.3124 + memcpy(newname, base_name, base_len); 1.3125 + if (need_to_append_dot) newname[base_len] = '.'; 1.3126 + memcpy(newname + base_len + need_to_append_dot, postfix, postfix_len); 1.3127 + newname[base_len + need_to_append_dot + postfix_len] = 0; 1.3128 + return newname; 1.3129 + } 1.3130 + } 1.3131 + 1.3132 + /* we ran off the end of the list and still didn't find the requested string */ 1.3133 + EVUTIL_ASSERT(0); 1.3134 + return NULL; /* unreachable; stops warnings in some compilers. */ 1.3135 +} 1.3136 + 1.3137 +static struct request * 1.3138 +search_request_new(struct evdns_base *base, struct evdns_request *handle, 1.3139 + int type, const char *const name, int flags, 1.3140 + evdns_callback_type user_callback, void *user_arg) { 1.3141 + ASSERT_LOCKED(base); 1.3142 + EVUTIL_ASSERT(type == TYPE_A || type == TYPE_AAAA); 1.3143 + EVUTIL_ASSERT(handle->current_req == NULL); 1.3144 + if ( ((flags & DNS_QUERY_NO_SEARCH) == 0) && 1.3145 + base->global_search_state && 1.3146 + base->global_search_state->num_domains) { 1.3147 + /* we have some domains to search */ 1.3148 + struct request *req; 1.3149 + if (string_num_dots(name) >= base->global_search_state->ndots) { 1.3150 + req = request_new(base, handle, type, name, flags, user_callback, user_arg); 1.3151 + if (!req) return NULL; 1.3152 + handle->search_index = -1; 1.3153 + } else { 1.3154 + char *const new_name = search_make_new(base->global_search_state, 0, name); 1.3155 + if (!new_name) return NULL; 1.3156 + req = request_new(base, handle, type, new_name, flags, user_callback, user_arg); 1.3157 + mm_free(new_name); 1.3158 + if (!req) return NULL; 1.3159 + handle->search_index = 0; 1.3160 + } 1.3161 + EVUTIL_ASSERT(handle->search_origname == NULL); 1.3162 + handle->search_origname = mm_strdup(name); 1.3163 + if (handle->search_origname == NULL) { 1.3164 + /* XXX Should we dealloc req? If yes, how? */ 1.3165 + if (req) 1.3166 + mm_free(req); 1.3167 + return NULL; 1.3168 + } 1.3169 + handle->search_state = base->global_search_state; 1.3170 + handle->search_flags = flags; 1.3171 + base->global_search_state->refcount++; 1.3172 + request_submit(req); 1.3173 + return req; 1.3174 + } else { 1.3175 + struct request *const req = request_new(base, handle, type, name, flags, user_callback, user_arg); 1.3176 + if (!req) return NULL; 1.3177 + request_submit(req); 1.3178 + return req; 1.3179 + } 1.3180 +} 1.3181 + 1.3182 +/* this is called when a request has failed to find a name. We need to check */ 1.3183 +/* if it is part of a search and, if so, try the next name in the list */ 1.3184 +/* returns: */ 1.3185 +/* 0 another request has been submitted */ 1.3186 +/* 1 no more requests needed */ 1.3187 +static int 1.3188 +search_try_next(struct evdns_request *const handle) { 1.3189 + struct request *req = handle->current_req; 1.3190 + struct evdns_base *base = req->base; 1.3191 + struct request *newreq; 1.3192 + ASSERT_LOCKED(base); 1.3193 + if (handle->search_state) { 1.3194 + /* it is part of a search */ 1.3195 + char *new_name; 1.3196 + handle->search_index++; 1.3197 + if (handle->search_index >= handle->search_state->num_domains) { 1.3198 + /* no more postfixes to try, however we may need to try */ 1.3199 + /* this name without a postfix */ 1.3200 + if (string_num_dots(handle->search_origname) < handle->search_state->ndots) { 1.3201 + /* yep, we need to try it raw */ 1.3202 + newreq = request_new(base, NULL, req->request_type, handle->search_origname, handle->search_flags, req->user_callback, req->user_pointer); 1.3203 + log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", handle->search_origname); 1.3204 + if (newreq) { 1.3205 + search_request_finished(handle); 1.3206 + goto submit_next; 1.3207 + } 1.3208 + } 1.3209 + return 1; 1.3210 + } 1.3211 + 1.3212 + new_name = search_make_new(handle->search_state, handle->search_index, handle->search_origname); 1.3213 + if (!new_name) return 1; 1.3214 + log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, handle->search_index); 1.3215 + newreq = request_new(base, NULL, req->request_type, new_name, handle->search_flags, req->user_callback, req->user_pointer); 1.3216 + mm_free(new_name); 1.3217 + if (!newreq) return 1; 1.3218 + goto submit_next; 1.3219 + } 1.3220 + return 1; 1.3221 + 1.3222 +submit_next: 1.3223 + request_finished(req, &REQ_HEAD(req->base, req->trans_id), 0); 1.3224 + handle->current_req = newreq; 1.3225 + newreq->handle = handle; 1.3226 + request_submit(newreq); 1.3227 + return 0; 1.3228 +} 1.3229 + 1.3230 +static void 1.3231 +search_request_finished(struct evdns_request *const handle) { 1.3232 + ASSERT_LOCKED(handle->current_req->base); 1.3233 + if (handle->search_state) { 1.3234 + search_state_decref(handle->search_state); 1.3235 + handle->search_state = NULL; 1.3236 + } 1.3237 + if (handle->search_origname) { 1.3238 + mm_free(handle->search_origname); 1.3239 + handle->search_origname = NULL; 1.3240 + } 1.3241 +} 1.3242 + 1.3243 +/* ================================================================= */ 1.3244 +/* Parsing resolv.conf files */ 1.3245 + 1.3246 +static void 1.3247 +evdns_resolv_set_defaults(struct evdns_base *base, int flags) { 1.3248 + /* if the file isn't found then we assume a local resolver */ 1.3249 + ASSERT_LOCKED(base); 1.3250 + if (flags & DNS_OPTION_SEARCH) search_set_from_hostname(base); 1.3251 + if (flags & DNS_OPTION_NAMESERVERS) evdns_base_nameserver_ip_add(base,"127.0.0.1"); 1.3252 +} 1.3253 + 1.3254 +#ifndef _EVENT_HAVE_STRTOK_R 1.3255 +static char * 1.3256 +strtok_r(char *s, const char *delim, char **state) { 1.3257 + char *cp, *start; 1.3258 + start = cp = s ? s : *state; 1.3259 + if (!cp) 1.3260 + return NULL; 1.3261 + while (*cp && !strchr(delim, *cp)) 1.3262 + ++cp; 1.3263 + if (!*cp) { 1.3264 + if (cp == start) 1.3265 + return NULL; 1.3266 + *state = NULL; 1.3267 + return start; 1.3268 + } else { 1.3269 + *cp++ = '\0'; 1.3270 + *state = cp; 1.3271 + return start; 1.3272 + } 1.3273 +} 1.3274 +#endif 1.3275 + 1.3276 +/* helper version of atoi which returns -1 on error */ 1.3277 +static int 1.3278 +strtoint(const char *const str) 1.3279 +{ 1.3280 + char *endptr; 1.3281 + const int r = strtol(str, &endptr, 10); 1.3282 + if (*endptr) return -1; 1.3283 + return r; 1.3284 +} 1.3285 + 1.3286 +/* Parse a number of seconds into a timeval; return -1 on error. */ 1.3287 +static int 1.3288 +strtotimeval(const char *const str, struct timeval *out) 1.3289 +{ 1.3290 + double d; 1.3291 + char *endptr; 1.3292 + d = strtod(str, &endptr); 1.3293 + if (*endptr) return -1; 1.3294 + if (d < 0) return -1; 1.3295 + out->tv_sec = (int) d; 1.3296 + out->tv_usec = (int) ((d - (int) d)*1000000); 1.3297 + if (out->tv_sec == 0 && out->tv_usec < 1000) /* less than 1 msec */ 1.3298 + return -1; 1.3299 + return 0; 1.3300 +} 1.3301 + 1.3302 +/* helper version of atoi that returns -1 on error and clips to bounds. */ 1.3303 +static int 1.3304 +strtoint_clipped(const char *const str, int min, int max) 1.3305 +{ 1.3306 + int r = strtoint(str); 1.3307 + if (r == -1) 1.3308 + return r; 1.3309 + else if (r<min) 1.3310 + return min; 1.3311 + else if (r>max) 1.3312 + return max; 1.3313 + else 1.3314 + return r; 1.3315 +} 1.3316 + 1.3317 +static int 1.3318 +evdns_base_set_max_requests_inflight(struct evdns_base *base, int maxinflight) 1.3319 +{ 1.3320 + int old_n_heads = base->n_req_heads, n_heads; 1.3321 + struct request **old_heads = base->req_heads, **new_heads, *req; 1.3322 + int i; 1.3323 + 1.3324 + ASSERT_LOCKED(base); 1.3325 + if (maxinflight < 1) 1.3326 + maxinflight = 1; 1.3327 + n_heads = (maxinflight+4) / 5; 1.3328 + EVUTIL_ASSERT(n_heads > 0); 1.3329 + new_heads = mm_calloc(n_heads, sizeof(struct request*)); 1.3330 + if (!new_heads) 1.3331 + return (-1); 1.3332 + if (old_heads) { 1.3333 + for (i = 0; i < old_n_heads; ++i) { 1.3334 + while (old_heads[i]) { 1.3335 + req = old_heads[i]; 1.3336 + evdns_request_remove(req, &old_heads[i]); 1.3337 + evdns_request_insert(req, &new_heads[req->trans_id % n_heads]); 1.3338 + } 1.3339 + } 1.3340 + mm_free(old_heads); 1.3341 + } 1.3342 + base->req_heads = new_heads; 1.3343 + base->n_req_heads = n_heads; 1.3344 + base->global_max_requests_inflight = maxinflight; 1.3345 + return (0); 1.3346 +} 1.3347 + 1.3348 +/* exported function */ 1.3349 +int 1.3350 +evdns_base_set_option(struct evdns_base *base, 1.3351 + const char *option, const char *val) 1.3352 +{ 1.3353 + int res; 1.3354 + EVDNS_LOCK(base); 1.3355 + res = evdns_base_set_option_impl(base, option, val, DNS_OPTIONS_ALL); 1.3356 + EVDNS_UNLOCK(base); 1.3357 + return res; 1.3358 +} 1.3359 + 1.3360 +static inline int 1.3361 +str_matches_option(const char *s1, const char *optionname) 1.3362 +{ 1.3363 + /* Option names are given as "option:" We accept either 'option' in 1.3364 + * s1, or 'option:randomjunk'. The latter form is to implement the 1.3365 + * resolv.conf parser. */ 1.3366 + size_t optlen = strlen(optionname); 1.3367 + size_t slen = strlen(s1); 1.3368 + if (slen == optlen || slen == optlen - 1) 1.3369 + return !strncmp(s1, optionname, slen); 1.3370 + else if (slen > optlen) 1.3371 + return !strncmp(s1, optionname, optlen); 1.3372 + else 1.3373 + return 0; 1.3374 +} 1.3375 + 1.3376 +static int 1.3377 +evdns_base_set_option_impl(struct evdns_base *base, 1.3378 + const char *option, const char *val, int flags) 1.3379 +{ 1.3380 + ASSERT_LOCKED(base); 1.3381 + if (str_matches_option(option, "ndots:")) { 1.3382 + const int ndots = strtoint(val); 1.3383 + if (ndots == -1) return -1; 1.3384 + if (!(flags & DNS_OPTION_SEARCH)) return 0; 1.3385 + log(EVDNS_LOG_DEBUG, "Setting ndots to %d", ndots); 1.3386 + if (!base->global_search_state) base->global_search_state = search_state_new(); 1.3387 + if (!base->global_search_state) return -1; 1.3388 + base->global_search_state->ndots = ndots; 1.3389 + } else if (str_matches_option(option, "timeout:")) { 1.3390 + struct timeval tv; 1.3391 + if (strtotimeval(val, &tv) == -1) return -1; 1.3392 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3393 + log(EVDNS_LOG_DEBUG, "Setting timeout to %s", val); 1.3394 + memcpy(&base->global_timeout, &tv, sizeof(struct timeval)); 1.3395 + } else if (str_matches_option(option, "getaddrinfo-allow-skew:")) { 1.3396 + struct timeval tv; 1.3397 + if (strtotimeval(val, &tv) == -1) return -1; 1.3398 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3399 + log(EVDNS_LOG_DEBUG, "Setting getaddrinfo-allow-skew to %s", 1.3400 + val); 1.3401 + memcpy(&base->global_getaddrinfo_allow_skew, &tv, 1.3402 + sizeof(struct timeval)); 1.3403 + } else if (str_matches_option(option, "max-timeouts:")) { 1.3404 + const int maxtimeout = strtoint_clipped(val, 1, 255); 1.3405 + if (maxtimeout == -1) return -1; 1.3406 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3407 + log(EVDNS_LOG_DEBUG, "Setting maximum allowed timeouts to %d", 1.3408 + maxtimeout); 1.3409 + base->global_max_nameserver_timeout = maxtimeout; 1.3410 + } else if (str_matches_option(option, "max-inflight:")) { 1.3411 + const int maxinflight = strtoint_clipped(val, 1, 65000); 1.3412 + if (maxinflight == -1) return -1; 1.3413 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3414 + log(EVDNS_LOG_DEBUG, "Setting maximum inflight requests to %d", 1.3415 + maxinflight); 1.3416 + evdns_base_set_max_requests_inflight(base, maxinflight); 1.3417 + } else if (str_matches_option(option, "attempts:")) { 1.3418 + int retries = strtoint(val); 1.3419 + if (retries == -1) return -1; 1.3420 + if (retries > 255) retries = 255; 1.3421 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3422 + log(EVDNS_LOG_DEBUG, "Setting retries to %d", retries); 1.3423 + base->global_max_retransmits = retries; 1.3424 + } else if (str_matches_option(option, "randomize-case:")) { 1.3425 + int randcase = strtoint(val); 1.3426 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3427 + base->global_randomize_case = randcase; 1.3428 + } else if (str_matches_option(option, "bind-to:")) { 1.3429 + /* XXX This only applies to successive nameservers, not 1.3430 + * to already-configured ones. We might want to fix that. */ 1.3431 + int len = sizeof(base->global_outgoing_address); 1.3432 + if (!(flags & DNS_OPTION_NAMESERVERS)) return 0; 1.3433 + if (evutil_parse_sockaddr_port(val, 1.3434 + (struct sockaddr*)&base->global_outgoing_address, &len)) 1.3435 + return -1; 1.3436 + base->global_outgoing_addrlen = len; 1.3437 + } else if (str_matches_option(option, "initial-probe-timeout:")) { 1.3438 + struct timeval tv; 1.3439 + if (strtotimeval(val, &tv) == -1) return -1; 1.3440 + if (tv.tv_sec > 3600) 1.3441 + tv.tv_sec = 3600; 1.3442 + if (!(flags & DNS_OPTION_MISC)) return 0; 1.3443 + log(EVDNS_LOG_DEBUG, "Setting initial probe timeout to %s", 1.3444 + val); 1.3445 + memcpy(&base->global_nameserver_probe_initial_timeout, &tv, 1.3446 + sizeof(tv)); 1.3447 + } 1.3448 + return 0; 1.3449 +} 1.3450 + 1.3451 +int 1.3452 +evdns_set_option(const char *option, const char *val, int flags) 1.3453 +{ 1.3454 + if (!current_base) 1.3455 + current_base = evdns_base_new(NULL, 0); 1.3456 + return evdns_base_set_option(current_base, option, val); 1.3457 +} 1.3458 + 1.3459 +static void 1.3460 +resolv_conf_parse_line(struct evdns_base *base, char *const start, int flags) { 1.3461 + char *strtok_state; 1.3462 + static const char *const delims = " \t"; 1.3463 +#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) 1.3464 + 1.3465 + 1.3466 + char *const first_token = strtok_r(start, delims, &strtok_state); 1.3467 + ASSERT_LOCKED(base); 1.3468 + if (!first_token) return; 1.3469 + 1.3470 + if (!strcmp(first_token, "nameserver") && (flags & DNS_OPTION_NAMESERVERS)) { 1.3471 + const char *const nameserver = NEXT_TOKEN; 1.3472 + 1.3473 + if (nameserver) 1.3474 + evdns_base_nameserver_ip_add(base, nameserver); 1.3475 + } else if (!strcmp(first_token, "domain") && (flags & DNS_OPTION_SEARCH)) { 1.3476 + const char *const domain = NEXT_TOKEN; 1.3477 + if (domain) { 1.3478 + search_postfix_clear(base); 1.3479 + search_postfix_add(base, domain); 1.3480 + } 1.3481 + } else if (!strcmp(first_token, "search") && (flags & DNS_OPTION_SEARCH)) { 1.3482 + const char *domain; 1.3483 + search_postfix_clear(base); 1.3484 + 1.3485 + while ((domain = NEXT_TOKEN)) { 1.3486 + search_postfix_add(base, domain); 1.3487 + } 1.3488 + search_reverse(base); 1.3489 + } else if (!strcmp(first_token, "options")) { 1.3490 + const char *option; 1.3491 + while ((option = NEXT_TOKEN)) { 1.3492 + const char *val = strchr(option, ':'); 1.3493 + evdns_base_set_option_impl(base, option, val ? val+1 : "", flags); 1.3494 + } 1.3495 + } 1.3496 +#undef NEXT_TOKEN 1.3497 +} 1.3498 + 1.3499 +/* exported function */ 1.3500 +/* returns: */ 1.3501 +/* 0 no errors */ 1.3502 +/* 1 failed to open file */ 1.3503 +/* 2 failed to stat file */ 1.3504 +/* 3 file too large */ 1.3505 +/* 4 out of memory */ 1.3506 +/* 5 short read from file */ 1.3507 +int 1.3508 +evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename) { 1.3509 + int res; 1.3510 + EVDNS_LOCK(base); 1.3511 + res = evdns_base_resolv_conf_parse_impl(base, flags, filename); 1.3512 + EVDNS_UNLOCK(base); 1.3513 + return res; 1.3514 +} 1.3515 + 1.3516 +static char * 1.3517 +evdns_get_default_hosts_filename(void) 1.3518 +{ 1.3519 +#ifdef WIN32 1.3520 + /* Windows is a little coy about where it puts its configuration 1.3521 + * files. Sure, they're _usually_ in C:\windows\system32, but 1.3522 + * there's no reason in principle they couldn't be in 1.3523 + * W:\hoboken chicken emergency\ 1.3524 + */ 1.3525 + char path[MAX_PATH+1]; 1.3526 + static const char hostfile[] = "\\drivers\\etc\\hosts"; 1.3527 + char *path_out; 1.3528 + size_t len_out; 1.3529 + 1.3530 + if (! SHGetSpecialFolderPathA(NULL, path, CSIDL_SYSTEM, 0)) 1.3531 + return NULL; 1.3532 + len_out = strlen(path)+strlen(hostfile); 1.3533 + path_out = mm_malloc(len_out+1); 1.3534 + evutil_snprintf(path_out, len_out, "%s%s", path, hostfile); 1.3535 + return path_out; 1.3536 +#else 1.3537 + return mm_strdup("/etc/hosts"); 1.3538 +#endif 1.3539 +} 1.3540 + 1.3541 +static int 1.3542 +evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename) { 1.3543 + size_t n; 1.3544 + char *resolv; 1.3545 + char *start; 1.3546 + int err = 0; 1.3547 + 1.3548 + log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); 1.3549 + 1.3550 + if (flags & DNS_OPTION_HOSTSFILE) { 1.3551 + char *fname = evdns_get_default_hosts_filename(); 1.3552 + evdns_base_load_hosts(base, fname); 1.3553 + if (fname) 1.3554 + mm_free(fname); 1.3555 + } 1.3556 + 1.3557 + if ((err = evutil_read_file(filename, &resolv, &n, 0)) < 0) { 1.3558 + if (err == -1) { 1.3559 + /* No file. */ 1.3560 + evdns_resolv_set_defaults(base, flags); 1.3561 + return 1; 1.3562 + } else { 1.3563 + return 2; 1.3564 + } 1.3565 + } 1.3566 + 1.3567 + start = resolv; 1.3568 + for (;;) { 1.3569 + char *const newline = strchr(start, '\n'); 1.3570 + if (!newline) { 1.3571 + resolv_conf_parse_line(base, start, flags); 1.3572 + break; 1.3573 + } else { 1.3574 + *newline = 0; 1.3575 + resolv_conf_parse_line(base, start, flags); 1.3576 + start = newline + 1; 1.3577 + } 1.3578 + } 1.3579 + 1.3580 + if (!base->server_head && (flags & DNS_OPTION_NAMESERVERS)) { 1.3581 + /* no nameservers were configured. */ 1.3582 + evdns_base_nameserver_ip_add(base, "127.0.0.1"); 1.3583 + err = 6; 1.3584 + } 1.3585 + if (flags & DNS_OPTION_SEARCH && (!base->global_search_state || base->global_search_state->num_domains == 0)) { 1.3586 + search_set_from_hostname(base); 1.3587 + } 1.3588 + 1.3589 + mm_free(resolv); 1.3590 + return err; 1.3591 +} 1.3592 + 1.3593 +int 1.3594 +evdns_resolv_conf_parse(int flags, const char *const filename) { 1.3595 + if (!current_base) 1.3596 + current_base = evdns_base_new(NULL, 0); 1.3597 + return evdns_base_resolv_conf_parse(current_base, flags, filename); 1.3598 +} 1.3599 + 1.3600 + 1.3601 +#ifdef WIN32 1.3602 +/* Add multiple nameservers from a space-or-comma-separated list. */ 1.3603 +static int 1.3604 +evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) { 1.3605 + const char *addr; 1.3606 + char *buf; 1.3607 + int r; 1.3608 + ASSERT_LOCKED(base); 1.3609 + while (*ips) { 1.3610 + while (isspace(*ips) || *ips == ',' || *ips == '\t') 1.3611 + ++ips; 1.3612 + addr = ips; 1.3613 + while (isdigit(*ips) || *ips == '.' || *ips == ':' || 1.3614 + *ips=='[' || *ips==']') 1.3615 + ++ips; 1.3616 + buf = mm_malloc(ips-addr+1); 1.3617 + if (!buf) return 4; 1.3618 + memcpy(buf, addr, ips-addr); 1.3619 + buf[ips-addr] = '\0'; 1.3620 + r = evdns_base_nameserver_ip_add(base, buf); 1.3621 + mm_free(buf); 1.3622 + if (r) return r; 1.3623 + } 1.3624 + return 0; 1.3625 +} 1.3626 + 1.3627 +typedef DWORD(WINAPI *GetNetworkParams_fn_t)(FIXED_INFO *, DWORD*); 1.3628 + 1.3629 +/* Use the windows GetNetworkParams interface in iphlpapi.dll to */ 1.3630 +/* figure out what our nameservers are. */ 1.3631 +static int 1.3632 +load_nameservers_with_getnetworkparams(struct evdns_base *base) 1.3633 +{ 1.3634 + /* Based on MSDN examples and inspection of c-ares code. */ 1.3635 + FIXED_INFO *fixed; 1.3636 + HMODULE handle = 0; 1.3637 + ULONG size = sizeof(FIXED_INFO); 1.3638 + void *buf = NULL; 1.3639 + int status = 0, r, added_any; 1.3640 + IP_ADDR_STRING *ns; 1.3641 + GetNetworkParams_fn_t fn; 1.3642 + 1.3643 + ASSERT_LOCKED(base); 1.3644 + if (!(handle = evutil_load_windows_system_library( 1.3645 + TEXT("iphlpapi.dll")))) { 1.3646 + log(EVDNS_LOG_WARN, "Could not open iphlpapi.dll"); 1.3647 + status = -1; 1.3648 + goto done; 1.3649 + } 1.3650 + if (!(fn = (GetNetworkParams_fn_t) GetProcAddress(handle, "GetNetworkParams"))) { 1.3651 + log(EVDNS_LOG_WARN, "Could not get address of function."); 1.3652 + status = -1; 1.3653 + goto done; 1.3654 + } 1.3655 + 1.3656 + buf = mm_malloc(size); 1.3657 + if (!buf) { status = 4; goto done; } 1.3658 + fixed = buf; 1.3659 + r = fn(fixed, &size); 1.3660 + if (r != ERROR_SUCCESS && r != ERROR_BUFFER_OVERFLOW) { 1.3661 + status = -1; 1.3662 + goto done; 1.3663 + } 1.3664 + if (r != ERROR_SUCCESS) { 1.3665 + mm_free(buf); 1.3666 + buf = mm_malloc(size); 1.3667 + if (!buf) { status = 4; goto done; } 1.3668 + fixed = buf; 1.3669 + r = fn(fixed, &size); 1.3670 + if (r != ERROR_SUCCESS) { 1.3671 + log(EVDNS_LOG_DEBUG, "fn() failed."); 1.3672 + status = -1; 1.3673 + goto done; 1.3674 + } 1.3675 + } 1.3676 + 1.3677 + EVUTIL_ASSERT(fixed); 1.3678 + added_any = 0; 1.3679 + ns = &(fixed->DnsServerList); 1.3680 + while (ns) { 1.3681 + r = evdns_nameserver_ip_add_line(base, ns->IpAddress.String); 1.3682 + if (r) { 1.3683 + log(EVDNS_LOG_DEBUG,"Could not add nameserver %s to list,error: %d", 1.3684 + (ns->IpAddress.String),(int)GetLastError()); 1.3685 + status = r; 1.3686 + } else { 1.3687 + ++added_any; 1.3688 + log(EVDNS_LOG_DEBUG,"Successfully added %s as nameserver",ns->IpAddress.String); 1.3689 + } 1.3690 + 1.3691 + ns = ns->Next; 1.3692 + } 1.3693 + 1.3694 + if (!added_any) { 1.3695 + log(EVDNS_LOG_DEBUG, "No nameservers added."); 1.3696 + if (status == 0) 1.3697 + status = -1; 1.3698 + } else { 1.3699 + status = 0; 1.3700 + } 1.3701 + 1.3702 + done: 1.3703 + if (buf) 1.3704 + mm_free(buf); 1.3705 + if (handle) 1.3706 + FreeLibrary(handle); 1.3707 + return status; 1.3708 +} 1.3709 + 1.3710 +static int 1.3711 +config_nameserver_from_reg_key(struct evdns_base *base, HKEY key, const TCHAR *subkey) 1.3712 +{ 1.3713 + char *buf; 1.3714 + DWORD bufsz = 0, type = 0; 1.3715 + int status = 0; 1.3716 + 1.3717 + ASSERT_LOCKED(base); 1.3718 + if (RegQueryValueEx(key, subkey, 0, &type, NULL, &bufsz) 1.3719 + != ERROR_MORE_DATA) 1.3720 + return -1; 1.3721 + if (!(buf = mm_malloc(bufsz))) 1.3722 + return -1; 1.3723 + 1.3724 + if (RegQueryValueEx(key, subkey, 0, &type, (LPBYTE)buf, &bufsz) 1.3725 + == ERROR_SUCCESS && bufsz > 1) { 1.3726 + status = evdns_nameserver_ip_add_line(base,buf); 1.3727 + } 1.3728 + 1.3729 + mm_free(buf); 1.3730 + return status; 1.3731 +} 1.3732 + 1.3733 +#define SERVICES_KEY TEXT("System\\CurrentControlSet\\Services\\") 1.3734 +#define WIN_NS_9X_KEY SERVICES_KEY TEXT("VxD\\MSTCP") 1.3735 +#define WIN_NS_NT_KEY SERVICES_KEY TEXT("Tcpip\\Parameters") 1.3736 + 1.3737 +static int 1.3738 +load_nameservers_from_registry(struct evdns_base *base) 1.3739 +{ 1.3740 + int found = 0; 1.3741 + int r; 1.3742 +#define TRY(k, name) \ 1.3743 + if (!found && config_nameserver_from_reg_key(base,k,TEXT(name)) == 0) { \ 1.3744 + log(EVDNS_LOG_DEBUG,"Found nameservers in %s/%s",#k,name); \ 1.3745 + found = 1; \ 1.3746 + } else if (!found) { \ 1.3747 + log(EVDNS_LOG_DEBUG,"Didn't find nameservers in %s/%s", \ 1.3748 + #k,#name); \ 1.3749 + } 1.3750 + 1.3751 + ASSERT_LOCKED(base); 1.3752 + 1.3753 + if (((int)GetVersion()) > 0) { /* NT */ 1.3754 + HKEY nt_key = 0, interfaces_key = 0; 1.3755 + 1.3756 + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, 1.3757 + KEY_READ, &nt_key) != ERROR_SUCCESS) { 1.3758 + log(EVDNS_LOG_DEBUG,"Couldn't open nt key, %d",(int)GetLastError()); 1.3759 + return -1; 1.3760 + } 1.3761 + r = RegOpenKeyEx(nt_key, TEXT("Interfaces"), 0, 1.3762 + KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, 1.3763 + &interfaces_key); 1.3764 + if (r != ERROR_SUCCESS) { 1.3765 + log(EVDNS_LOG_DEBUG,"Couldn't open interfaces key, %d",(int)GetLastError()); 1.3766 + return -1; 1.3767 + } 1.3768 + TRY(nt_key, "NameServer"); 1.3769 + TRY(nt_key, "DhcpNameServer"); 1.3770 + TRY(interfaces_key, "NameServer"); 1.3771 + TRY(interfaces_key, "DhcpNameServer"); 1.3772 + RegCloseKey(interfaces_key); 1.3773 + RegCloseKey(nt_key); 1.3774 + } else { 1.3775 + HKEY win_key = 0; 1.3776 + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_9X_KEY, 0, 1.3777 + KEY_READ, &win_key) != ERROR_SUCCESS) { 1.3778 + log(EVDNS_LOG_DEBUG, "Couldn't open registry key, %d", (int)GetLastError()); 1.3779 + return -1; 1.3780 + } 1.3781 + TRY(win_key, "NameServer"); 1.3782 + RegCloseKey(win_key); 1.3783 + } 1.3784 + 1.3785 + if (found == 0) { 1.3786 + log(EVDNS_LOG_WARN,"Didn't find any nameservers."); 1.3787 + } 1.3788 + 1.3789 + return found ? 0 : -1; 1.3790 +#undef TRY 1.3791 +} 1.3792 + 1.3793 +int 1.3794 +evdns_base_config_windows_nameservers(struct evdns_base *base) 1.3795 +{ 1.3796 + int r; 1.3797 + char *fname; 1.3798 + if (base == NULL) 1.3799 + base = current_base; 1.3800 + if (base == NULL) 1.3801 + return -1; 1.3802 + EVDNS_LOCK(base); 1.3803 + if (load_nameservers_with_getnetworkparams(base) == 0) { 1.3804 + EVDNS_UNLOCK(base); 1.3805 + return 0; 1.3806 + } 1.3807 + r = load_nameservers_from_registry(base); 1.3808 + 1.3809 + fname = evdns_get_default_hosts_filename(); 1.3810 + evdns_base_load_hosts(base, fname); 1.3811 + if (fname) 1.3812 + mm_free(fname); 1.3813 + 1.3814 + EVDNS_UNLOCK(base); 1.3815 + return r; 1.3816 +} 1.3817 + 1.3818 +int 1.3819 +evdns_config_windows_nameservers(void) 1.3820 +{ 1.3821 + if (!current_base) { 1.3822 + current_base = evdns_base_new(NULL, 1); 1.3823 + return current_base == NULL ? -1 : 0; 1.3824 + } else { 1.3825 + return evdns_base_config_windows_nameservers(current_base); 1.3826 + } 1.3827 +} 1.3828 +#endif 1.3829 + 1.3830 +struct evdns_base * 1.3831 +evdns_base_new(struct event_base *event_base, int initialize_nameservers) 1.3832 +{ 1.3833 + struct evdns_base *base; 1.3834 + 1.3835 + if (evutil_secure_rng_init() < 0) { 1.3836 + log(EVDNS_LOG_WARN, "Unable to seed random number generator; " 1.3837 + "DNS can't run."); 1.3838 + return NULL; 1.3839 + } 1.3840 + 1.3841 + /* Give the evutil library a hook into its evdns-enabled 1.3842 + * functionality. We can't just call evdns_getaddrinfo directly or 1.3843 + * else libevent-core will depend on libevent-extras. */ 1.3844 + evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo); 1.3845 + 1.3846 + base = mm_malloc(sizeof(struct evdns_base)); 1.3847 + if (base == NULL) 1.3848 + return (NULL); 1.3849 + memset(base, 0, sizeof(struct evdns_base)); 1.3850 + base->req_waiting_head = NULL; 1.3851 + 1.3852 + EVTHREAD_ALLOC_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.3853 + EVDNS_LOCK(base); 1.3854 + 1.3855 + /* Set max requests inflight and allocate req_heads. */ 1.3856 + base->req_heads = NULL; 1.3857 + 1.3858 + evdns_base_set_max_requests_inflight(base, 64); 1.3859 + 1.3860 + base->server_head = NULL; 1.3861 + base->event_base = event_base; 1.3862 + base->global_good_nameservers = base->global_requests_inflight = 1.3863 + base->global_requests_waiting = 0; 1.3864 + 1.3865 + base->global_timeout.tv_sec = 5; 1.3866 + base->global_timeout.tv_usec = 0; 1.3867 + base->global_max_reissues = 1; 1.3868 + base->global_max_retransmits = 3; 1.3869 + base->global_max_nameserver_timeout = 3; 1.3870 + base->global_search_state = NULL; 1.3871 + base->global_randomize_case = 1; 1.3872 + base->global_getaddrinfo_allow_skew.tv_sec = 3; 1.3873 + base->global_getaddrinfo_allow_skew.tv_usec = 0; 1.3874 + base->global_nameserver_probe_initial_timeout.tv_sec = 10; 1.3875 + base->global_nameserver_probe_initial_timeout.tv_usec = 0; 1.3876 + 1.3877 + TAILQ_INIT(&base->hostsdb); 1.3878 + 1.3879 + if (initialize_nameservers) { 1.3880 + int r; 1.3881 +#ifdef WIN32 1.3882 + r = evdns_base_config_windows_nameservers(base); 1.3883 +#else 1.3884 + r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf"); 1.3885 +#endif 1.3886 + if (r == -1) { 1.3887 + evdns_base_free_and_unlock(base, 0); 1.3888 + return NULL; 1.3889 + } 1.3890 + } 1.3891 + EVDNS_UNLOCK(base); 1.3892 + return base; 1.3893 +} 1.3894 + 1.3895 +int 1.3896 +evdns_init(void) 1.3897 +{ 1.3898 + struct evdns_base *base = evdns_base_new(NULL, 1); 1.3899 + if (base) { 1.3900 + current_base = base; 1.3901 + return 0; 1.3902 + } else { 1.3903 + return -1; 1.3904 + } 1.3905 +} 1.3906 + 1.3907 +const char * 1.3908 +evdns_err_to_string(int err) 1.3909 +{ 1.3910 + switch (err) { 1.3911 + case DNS_ERR_NONE: return "no error"; 1.3912 + case DNS_ERR_FORMAT: return "misformatted query"; 1.3913 + case DNS_ERR_SERVERFAILED: return "server failed"; 1.3914 + case DNS_ERR_NOTEXIST: return "name does not exist"; 1.3915 + case DNS_ERR_NOTIMPL: return "query not implemented"; 1.3916 + case DNS_ERR_REFUSED: return "refused"; 1.3917 + 1.3918 + case DNS_ERR_TRUNCATED: return "reply truncated or ill-formed"; 1.3919 + case DNS_ERR_UNKNOWN: return "unknown"; 1.3920 + case DNS_ERR_TIMEOUT: return "request timed out"; 1.3921 + case DNS_ERR_SHUTDOWN: return "dns subsystem shut down"; 1.3922 + case DNS_ERR_CANCEL: return "dns request canceled"; 1.3923 + case DNS_ERR_NODATA: return "no records in the reply"; 1.3924 + default: return "[Unknown error code]"; 1.3925 + } 1.3926 +} 1.3927 + 1.3928 +static void 1.3929 +evdns_nameserver_free(struct nameserver *server) 1.3930 +{ 1.3931 + if (server->socket >= 0) 1.3932 + evutil_closesocket(server->socket); 1.3933 + (void) event_del(&server->event); 1.3934 + event_debug_unassign(&server->event); 1.3935 + if (server->state == 0) 1.3936 + (void) event_del(&server->timeout_event); 1.3937 + event_debug_unassign(&server->timeout_event); 1.3938 + mm_free(server); 1.3939 +} 1.3940 + 1.3941 +static void 1.3942 +evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests) 1.3943 +{ 1.3944 + struct nameserver *server, *server_next; 1.3945 + struct search_domain *dom, *dom_next; 1.3946 + int i; 1.3947 + 1.3948 + /* Requires that we hold the lock. */ 1.3949 + 1.3950 + /* TODO(nickm) we might need to refcount here. */ 1.3951 + 1.3952 + for (i = 0; i < base->n_req_heads; ++i) { 1.3953 + while (base->req_heads[i]) { 1.3954 + if (fail_requests) 1.3955 + reply_schedule_callback(base->req_heads[i], 0, DNS_ERR_SHUTDOWN, NULL); 1.3956 + request_finished(base->req_heads[i], &REQ_HEAD(base, base->req_heads[i]->trans_id), 1); 1.3957 + } 1.3958 + } 1.3959 + while (base->req_waiting_head) { 1.3960 + if (fail_requests) 1.3961 + reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL); 1.3962 + request_finished(base->req_waiting_head, &base->req_waiting_head, 1); 1.3963 + } 1.3964 + base->global_requests_inflight = base->global_requests_waiting = 0; 1.3965 + 1.3966 + for (server = base->server_head; server; server = server_next) { 1.3967 + server_next = server->next; 1.3968 + evdns_nameserver_free(server); 1.3969 + if (server_next == base->server_head) 1.3970 + break; 1.3971 + } 1.3972 + base->server_head = NULL; 1.3973 + base->global_good_nameservers = 0; 1.3974 + 1.3975 + if (base->global_search_state) { 1.3976 + for (dom = base->global_search_state->head; dom; dom = dom_next) { 1.3977 + dom_next = dom->next; 1.3978 + mm_free(dom); 1.3979 + } 1.3980 + mm_free(base->global_search_state); 1.3981 + base->global_search_state = NULL; 1.3982 + } 1.3983 + 1.3984 + { 1.3985 + struct hosts_entry *victim; 1.3986 + while ((victim = TAILQ_FIRST(&base->hostsdb))) { 1.3987 + TAILQ_REMOVE(&base->hostsdb, victim, next); 1.3988 + mm_free(victim); 1.3989 + } 1.3990 + } 1.3991 + 1.3992 + mm_free(base->req_heads); 1.3993 + 1.3994 + EVDNS_UNLOCK(base); 1.3995 + EVTHREAD_FREE_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.3996 + 1.3997 + mm_free(base); 1.3998 +} 1.3999 + 1.4000 +void 1.4001 +evdns_base_free(struct evdns_base *base, int fail_requests) 1.4002 +{ 1.4003 + EVDNS_LOCK(base); 1.4004 + evdns_base_free_and_unlock(base, fail_requests); 1.4005 +} 1.4006 + 1.4007 +void 1.4008 +evdns_shutdown(int fail_requests) 1.4009 +{ 1.4010 + if (current_base) { 1.4011 + struct evdns_base *b = current_base; 1.4012 + current_base = NULL; 1.4013 + evdns_base_free(b, fail_requests); 1.4014 + } 1.4015 + evdns_log_fn = NULL; 1.4016 +} 1.4017 + 1.4018 +static int 1.4019 +evdns_base_parse_hosts_line(struct evdns_base *base, char *line) 1.4020 +{ 1.4021 + char *strtok_state; 1.4022 + static const char *const delims = " \t"; 1.4023 + char *const addr = strtok_r(line, delims, &strtok_state); 1.4024 + char *hostname, *hash; 1.4025 + struct sockaddr_storage ss; 1.4026 + int socklen = sizeof(ss); 1.4027 + ASSERT_LOCKED(base); 1.4028 + 1.4029 +#define NEXT_TOKEN strtok_r(NULL, delims, &strtok_state) 1.4030 + 1.4031 + if (!addr || *addr == '#') 1.4032 + return 0; 1.4033 + 1.4034 + memset(&ss, 0, sizeof(ss)); 1.4035 + if (evutil_parse_sockaddr_port(addr, (struct sockaddr*)&ss, &socklen)<0) 1.4036 + return -1; 1.4037 + if (socklen > (int)sizeof(struct sockaddr_in6)) 1.4038 + return -1; 1.4039 + 1.4040 + if (sockaddr_getport((struct sockaddr*)&ss)) 1.4041 + return -1; 1.4042 + 1.4043 + while ((hostname = NEXT_TOKEN)) { 1.4044 + struct hosts_entry *he; 1.4045 + size_t namelen; 1.4046 + if ((hash = strchr(hostname, '#'))) { 1.4047 + if (hash == hostname) 1.4048 + return 0; 1.4049 + *hash = '\0'; 1.4050 + } 1.4051 + 1.4052 + namelen = strlen(hostname); 1.4053 + 1.4054 + he = mm_calloc(1, sizeof(struct hosts_entry)+namelen); 1.4055 + if (!he) 1.4056 + return -1; 1.4057 + EVUTIL_ASSERT(socklen <= (int)sizeof(he->addr)); 1.4058 + memcpy(&he->addr, &ss, socklen); 1.4059 + memcpy(he->hostname, hostname, namelen+1); 1.4060 + he->addrlen = socklen; 1.4061 + 1.4062 + TAILQ_INSERT_TAIL(&base->hostsdb, he, next); 1.4063 + 1.4064 + if (hash) 1.4065 + return 0; 1.4066 + } 1.4067 + 1.4068 + return 0; 1.4069 +#undef NEXT_TOKEN 1.4070 +} 1.4071 + 1.4072 +static int 1.4073 +evdns_base_load_hosts_impl(struct evdns_base *base, const char *hosts_fname) 1.4074 +{ 1.4075 + char *str=NULL, *cp, *eol; 1.4076 + size_t len; 1.4077 + int err=0; 1.4078 + 1.4079 + ASSERT_LOCKED(base); 1.4080 + 1.4081 + if (hosts_fname == NULL || 1.4082 + (err = evutil_read_file(hosts_fname, &str, &len, 0)) < 0) { 1.4083 + char tmp[64]; 1.4084 + strlcpy(tmp, "127.0.0.1 localhost", sizeof(tmp)); 1.4085 + evdns_base_parse_hosts_line(base, tmp); 1.4086 + strlcpy(tmp, "::1 localhost", sizeof(tmp)); 1.4087 + evdns_base_parse_hosts_line(base, tmp); 1.4088 + return err ? -1 : 0; 1.4089 + } 1.4090 + 1.4091 + /* This will break early if there is a NUL in the hosts file. 1.4092 + * Probably not a problem.*/ 1.4093 + cp = str; 1.4094 + for (;;) { 1.4095 + eol = strchr(cp, '\n'); 1.4096 + 1.4097 + if (eol) { 1.4098 + *eol = '\0'; 1.4099 + evdns_base_parse_hosts_line(base, cp); 1.4100 + cp = eol+1; 1.4101 + } else { 1.4102 + evdns_base_parse_hosts_line(base, cp); 1.4103 + break; 1.4104 + } 1.4105 + } 1.4106 + 1.4107 + mm_free(str); 1.4108 + return 0; 1.4109 +} 1.4110 + 1.4111 +int 1.4112 +evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname) 1.4113 +{ 1.4114 + int res; 1.4115 + if (!base) 1.4116 + base = current_base; 1.4117 + EVDNS_LOCK(base); 1.4118 + res = evdns_base_load_hosts_impl(base, hosts_fname); 1.4119 + EVDNS_UNLOCK(base); 1.4120 + return res; 1.4121 +} 1.4122 + 1.4123 +/* A single request for a getaddrinfo, either v4 or v6. */ 1.4124 +struct getaddrinfo_subrequest { 1.4125 + struct evdns_request *r; 1.4126 + ev_uint32_t type; 1.4127 +}; 1.4128 + 1.4129 +/* State data used to implement an in-progress getaddrinfo. */ 1.4130 +struct evdns_getaddrinfo_request { 1.4131 + struct evdns_base *evdns_base; 1.4132 + /* Copy of the modified 'hints' data that we'll use to build 1.4133 + * answers. */ 1.4134 + struct evutil_addrinfo hints; 1.4135 + /* The callback to invoke when we're done */ 1.4136 + evdns_getaddrinfo_cb user_cb; 1.4137 + /* User-supplied data to give to the callback. */ 1.4138 + void *user_data; 1.4139 + /* The port to use when building sockaddrs. */ 1.4140 + ev_uint16_t port; 1.4141 + /* The sub_request for an A record (if any) */ 1.4142 + struct getaddrinfo_subrequest ipv4_request; 1.4143 + /* The sub_request for an AAAA record (if any) */ 1.4144 + struct getaddrinfo_subrequest ipv6_request; 1.4145 + 1.4146 + /* The cname result that we were told (if any) */ 1.4147 + char *cname_result; 1.4148 + 1.4149 + /* If we have one request answered and one request still inflight, 1.4150 + * then this field holds the answer from the first request... */ 1.4151 + struct evutil_addrinfo *pending_result; 1.4152 + /* And this event is a timeout that will tell us to cancel the second 1.4153 + * request if it's taking a long time. */ 1.4154 + struct event timeout; 1.4155 + 1.4156 + /* And this field holds the error code from the first request... */ 1.4157 + int pending_error; 1.4158 + /* If this is set, the user canceled this request. */ 1.4159 + unsigned user_canceled : 1; 1.4160 + /* If this is set, the user can no longer cancel this request; we're 1.4161 + * just waiting for the free. */ 1.4162 + unsigned request_done : 1; 1.4163 +}; 1.4164 + 1.4165 +/* Convert an evdns errors to the equivalent getaddrinfo error. */ 1.4166 +static int 1.4167 +evdns_err_to_getaddrinfo_err(int e1) 1.4168 +{ 1.4169 + /* XXX Do this better! */ 1.4170 + if (e1 == DNS_ERR_NONE) 1.4171 + return 0; 1.4172 + else if (e1 == DNS_ERR_NOTEXIST) 1.4173 + return EVUTIL_EAI_NONAME; 1.4174 + else 1.4175 + return EVUTIL_EAI_FAIL; 1.4176 +} 1.4177 + 1.4178 +/* Return the more informative of two getaddrinfo errors. */ 1.4179 +static int 1.4180 +getaddrinfo_merge_err(int e1, int e2) 1.4181 +{ 1.4182 + /* XXXX be cleverer here. */ 1.4183 + if (e1 == 0) 1.4184 + return e2; 1.4185 + else 1.4186 + return e1; 1.4187 +} 1.4188 + 1.4189 +static void 1.4190 +free_getaddrinfo_request(struct evdns_getaddrinfo_request *data) 1.4191 +{ 1.4192 + /* DO NOT CALL this if either of the requests is pending. Only once 1.4193 + * both callbacks have been invoked is it safe to free the request */ 1.4194 + if (data->pending_result) 1.4195 + evutil_freeaddrinfo(data->pending_result); 1.4196 + if (data->cname_result) 1.4197 + mm_free(data->cname_result); 1.4198 + event_del(&data->timeout); 1.4199 + mm_free(data); 1.4200 + return; 1.4201 +} 1.4202 + 1.4203 +static void 1.4204 +add_cname_to_reply(struct evdns_getaddrinfo_request *data, 1.4205 + struct evutil_addrinfo *ai) 1.4206 +{ 1.4207 + if (data->cname_result && ai) { 1.4208 + ai->ai_canonname = data->cname_result; 1.4209 + data->cname_result = NULL; 1.4210 + } 1.4211 +} 1.4212 + 1.4213 +/* Callback: invoked when one request in a mixed-format A/AAAA getaddrinfo 1.4214 + * request has finished, but the other one took too long to answer. Pass 1.4215 + * along the answer we got, and cancel the other request. 1.4216 + */ 1.4217 +static void 1.4218 +evdns_getaddrinfo_timeout_cb(evutil_socket_t fd, short what, void *ptr) 1.4219 +{ 1.4220 + int v4_timedout = 0, v6_timedout = 0; 1.4221 + struct evdns_getaddrinfo_request *data = ptr; 1.4222 + 1.4223 + /* Cancel any pending requests, and note which one */ 1.4224 + if (data->ipv4_request.r) { 1.4225 + /* XXXX This does nothing if the request's callback is already 1.4226 + * running (pending_cb is set). */ 1.4227 + evdns_cancel_request(NULL, data->ipv4_request.r); 1.4228 + v4_timedout = 1; 1.4229 + EVDNS_LOCK(data->evdns_base); 1.4230 + ++data->evdns_base->getaddrinfo_ipv4_timeouts; 1.4231 + EVDNS_UNLOCK(data->evdns_base); 1.4232 + } 1.4233 + if (data->ipv6_request.r) { 1.4234 + /* XXXX This does nothing if the request's callback is already 1.4235 + * running (pending_cb is set). */ 1.4236 + evdns_cancel_request(NULL, data->ipv6_request.r); 1.4237 + v6_timedout = 1; 1.4238 + EVDNS_LOCK(data->evdns_base); 1.4239 + ++data->evdns_base->getaddrinfo_ipv6_timeouts; 1.4240 + EVDNS_UNLOCK(data->evdns_base); 1.4241 + } 1.4242 + 1.4243 + /* We only use this timeout callback when we have an answer for 1.4244 + * one address. */ 1.4245 + EVUTIL_ASSERT(!v4_timedout || !v6_timedout); 1.4246 + 1.4247 + /* Report the outcome of the other request that didn't time out. */ 1.4248 + if (data->pending_result) { 1.4249 + add_cname_to_reply(data, data->pending_result); 1.4250 + data->user_cb(0, data->pending_result, data->user_data); 1.4251 + data->pending_result = NULL; 1.4252 + } else { 1.4253 + int e = data->pending_error; 1.4254 + if (!e) 1.4255 + e = EVUTIL_EAI_AGAIN; 1.4256 + data->user_cb(e, NULL, data->user_data); 1.4257 + } 1.4258 + 1.4259 + data->user_cb = NULL; /* prevent double-call if evdns callbacks are 1.4260 + * in-progress. XXXX It would be better if this 1.4261 + * weren't necessary. */ 1.4262 + 1.4263 + if (!v4_timedout && !v6_timedout) { 1.4264 + /* should be impossible? XXXX */ 1.4265 + free_getaddrinfo_request(data); 1.4266 + } 1.4267 +} 1.4268 + 1.4269 +static int 1.4270 +evdns_getaddrinfo_set_timeout(struct evdns_base *evdns_base, 1.4271 + struct evdns_getaddrinfo_request *data) 1.4272 +{ 1.4273 + return event_add(&data->timeout, &evdns_base->global_getaddrinfo_allow_skew); 1.4274 +} 1.4275 + 1.4276 +static inline int 1.4277 +evdns_result_is_answer(int result) 1.4278 +{ 1.4279 + return (result != DNS_ERR_NOTIMPL && result != DNS_ERR_REFUSED && 1.4280 + result != DNS_ERR_SERVERFAILED && result != DNS_ERR_CANCEL); 1.4281 +} 1.4282 + 1.4283 +static void 1.4284 +evdns_getaddrinfo_gotresolve(int result, char type, int count, 1.4285 + int ttl, void *addresses, void *arg) 1.4286 +{ 1.4287 + int i; 1.4288 + struct getaddrinfo_subrequest *req = arg; 1.4289 + struct getaddrinfo_subrequest *other_req; 1.4290 + struct evdns_getaddrinfo_request *data; 1.4291 + 1.4292 + struct evutil_addrinfo *res; 1.4293 + 1.4294 + struct sockaddr_in sin; 1.4295 + struct sockaddr_in6 sin6; 1.4296 + struct sockaddr *sa; 1.4297 + int socklen, addrlen; 1.4298 + void *addrp; 1.4299 + int err; 1.4300 + int user_canceled; 1.4301 + 1.4302 + EVUTIL_ASSERT(req->type == DNS_IPv4_A || req->type == DNS_IPv6_AAAA); 1.4303 + if (req->type == DNS_IPv4_A) { 1.4304 + data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv4_request); 1.4305 + other_req = &data->ipv6_request; 1.4306 + } else { 1.4307 + data = EVUTIL_UPCAST(req, struct evdns_getaddrinfo_request, ipv6_request); 1.4308 + other_req = &data->ipv4_request; 1.4309 + } 1.4310 + 1.4311 + EVDNS_LOCK(data->evdns_base); 1.4312 + if (evdns_result_is_answer(result)) { 1.4313 + if (req->type == DNS_IPv4_A) 1.4314 + ++data->evdns_base->getaddrinfo_ipv4_answered; 1.4315 + else 1.4316 + ++data->evdns_base->getaddrinfo_ipv6_answered; 1.4317 + } 1.4318 + user_canceled = data->user_canceled; 1.4319 + if (other_req->r == NULL) 1.4320 + data->request_done = 1; 1.4321 + EVDNS_UNLOCK(data->evdns_base); 1.4322 + 1.4323 + req->r = NULL; 1.4324 + 1.4325 + if (result == DNS_ERR_CANCEL && ! user_canceled) { 1.4326 + /* Internal cancel request from timeout or internal error. 1.4327 + * we already answered the user. */ 1.4328 + if (other_req->r == NULL) 1.4329 + free_getaddrinfo_request(data); 1.4330 + return; 1.4331 + } 1.4332 + 1.4333 + if (data->user_cb == NULL) { 1.4334 + /* We already answered. XXXX This shouldn't be needed; see 1.4335 + * comments in evdns_getaddrinfo_timeout_cb */ 1.4336 + free_getaddrinfo_request(data); 1.4337 + return; 1.4338 + } 1.4339 + 1.4340 + if (result == DNS_ERR_NONE) { 1.4341 + if (count == 0) 1.4342 + err = EVUTIL_EAI_NODATA; 1.4343 + else 1.4344 + err = 0; 1.4345 + } else { 1.4346 + err = evdns_err_to_getaddrinfo_err(result); 1.4347 + } 1.4348 + 1.4349 + if (err) { 1.4350 + /* Looks like we got an error. */ 1.4351 + if (other_req->r) { 1.4352 + /* The other request is still working; maybe it will 1.4353 + * succeed. */ 1.4354 + /* XXXX handle failure from set_timeout */ 1.4355 + evdns_getaddrinfo_set_timeout(data->evdns_base, data); 1.4356 + data->pending_error = err; 1.4357 + return; 1.4358 + } 1.4359 + 1.4360 + if (user_canceled) { 1.4361 + data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); 1.4362 + } else if (data->pending_result) { 1.4363 + /* If we have an answer waiting, and we weren't 1.4364 + * canceled, ignore this error. */ 1.4365 + add_cname_to_reply(data, data->pending_result); 1.4366 + data->user_cb(0, data->pending_result, data->user_data); 1.4367 + data->pending_result = NULL; 1.4368 + } else { 1.4369 + if (data->pending_error) 1.4370 + err = getaddrinfo_merge_err(err, 1.4371 + data->pending_error); 1.4372 + data->user_cb(err, NULL, data->user_data); 1.4373 + } 1.4374 + free_getaddrinfo_request(data); 1.4375 + return; 1.4376 + } else if (user_canceled) { 1.4377 + if (other_req->r) { 1.4378 + /* The other request is still working; let it hit this 1.4379 + * callback with EVUTIL_EAI_CANCEL callback and report 1.4380 + * the failure. */ 1.4381 + return; 1.4382 + } 1.4383 + data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); 1.4384 + free_getaddrinfo_request(data); 1.4385 + return; 1.4386 + } 1.4387 + 1.4388 + /* Looks like we got some answers. We should turn them into addrinfos 1.4389 + * and then either queue those or return them all. */ 1.4390 + EVUTIL_ASSERT(type == DNS_IPv4_A || type == DNS_IPv6_AAAA); 1.4391 + 1.4392 + if (type == DNS_IPv4_A) { 1.4393 + memset(&sin, 0, sizeof(sin)); 1.4394 + sin.sin_family = AF_INET; 1.4395 + sin.sin_port = htons(data->port); 1.4396 + 1.4397 + sa = (struct sockaddr *)&sin; 1.4398 + socklen = sizeof(sin); 1.4399 + addrlen = 4; 1.4400 + addrp = &sin.sin_addr.s_addr; 1.4401 + } else { 1.4402 + memset(&sin6, 0, sizeof(sin6)); 1.4403 + sin6.sin6_family = AF_INET6; 1.4404 + sin6.sin6_port = htons(data->port); 1.4405 + 1.4406 + sa = (struct sockaddr *)&sin6; 1.4407 + socklen = sizeof(sin6); 1.4408 + addrlen = 16; 1.4409 + addrp = &sin6.sin6_addr.s6_addr; 1.4410 + } 1.4411 + 1.4412 + res = NULL; 1.4413 + for (i=0; i < count; ++i) { 1.4414 + struct evutil_addrinfo *ai; 1.4415 + memcpy(addrp, ((char*)addresses)+i*addrlen, addrlen); 1.4416 + ai = evutil_new_addrinfo(sa, socklen, &data->hints); 1.4417 + if (!ai) { 1.4418 + if (other_req->r) { 1.4419 + evdns_cancel_request(NULL, other_req->r); 1.4420 + } 1.4421 + data->user_cb(EVUTIL_EAI_MEMORY, NULL, data->user_data); 1.4422 + if (res) 1.4423 + evutil_freeaddrinfo(res); 1.4424 + 1.4425 + if (other_req->r == NULL) 1.4426 + free_getaddrinfo_request(data); 1.4427 + return; 1.4428 + } 1.4429 + res = evutil_addrinfo_append(res, ai); 1.4430 + } 1.4431 + 1.4432 + if (other_req->r) { 1.4433 + /* The other request is still in progress; wait for it */ 1.4434 + /* XXXX handle failure from set_timeout */ 1.4435 + evdns_getaddrinfo_set_timeout(data->evdns_base, data); 1.4436 + data->pending_result = res; 1.4437 + return; 1.4438 + } else { 1.4439 + /* The other request is done or never started; append its 1.4440 + * results (if any) and return them. */ 1.4441 + if (data->pending_result) { 1.4442 + if (req->type == DNS_IPv4_A) 1.4443 + res = evutil_addrinfo_append(res, 1.4444 + data->pending_result); 1.4445 + else 1.4446 + res = evutil_addrinfo_append( 1.4447 + data->pending_result, res); 1.4448 + data->pending_result = NULL; 1.4449 + } 1.4450 + 1.4451 + /* Call the user callback. */ 1.4452 + add_cname_to_reply(data, res); 1.4453 + data->user_cb(0, res, data->user_data); 1.4454 + 1.4455 + /* Free data. */ 1.4456 + free_getaddrinfo_request(data); 1.4457 + } 1.4458 +} 1.4459 + 1.4460 +static struct hosts_entry * 1.4461 +find_hosts_entry(struct evdns_base *base, const char *hostname, 1.4462 + struct hosts_entry *find_after) 1.4463 +{ 1.4464 + struct hosts_entry *e; 1.4465 + 1.4466 + if (find_after) 1.4467 + e = TAILQ_NEXT(find_after, next); 1.4468 + else 1.4469 + e = TAILQ_FIRST(&base->hostsdb); 1.4470 + 1.4471 + for (; e; e = TAILQ_NEXT(e, next)) { 1.4472 + if (!evutil_ascii_strcasecmp(e->hostname, hostname)) 1.4473 + return e; 1.4474 + } 1.4475 + return NULL; 1.4476 +} 1.4477 + 1.4478 +static int 1.4479 +evdns_getaddrinfo_fromhosts(struct evdns_base *base, 1.4480 + const char *nodename, struct evutil_addrinfo *hints, ev_uint16_t port, 1.4481 + struct evutil_addrinfo **res) 1.4482 +{ 1.4483 + int n_found = 0; 1.4484 + struct hosts_entry *e; 1.4485 + struct evutil_addrinfo *ai=NULL; 1.4486 + int f = hints->ai_family; 1.4487 + 1.4488 + EVDNS_LOCK(base); 1.4489 + for (e = find_hosts_entry(base, nodename, NULL); e; 1.4490 + e = find_hosts_entry(base, nodename, e)) { 1.4491 + struct evutil_addrinfo *ai_new; 1.4492 + ++n_found; 1.4493 + if ((e->addr.sa.sa_family == AF_INET && f == PF_INET6) || 1.4494 + (e->addr.sa.sa_family == AF_INET6 && f == PF_INET)) 1.4495 + continue; 1.4496 + ai_new = evutil_new_addrinfo(&e->addr.sa, e->addrlen, hints); 1.4497 + if (!ai_new) { 1.4498 + n_found = 0; 1.4499 + goto out; 1.4500 + } 1.4501 + sockaddr_setport(ai_new->ai_addr, port); 1.4502 + ai = evutil_addrinfo_append(ai, ai_new); 1.4503 + } 1.4504 + EVDNS_UNLOCK(base); 1.4505 +out: 1.4506 + if (n_found) { 1.4507 + /* Note that we return an empty answer if we found entries for 1.4508 + * this hostname but none were of the right address type. */ 1.4509 + *res = ai; 1.4510 + return 0; 1.4511 + } else { 1.4512 + if (ai) 1.4513 + evutil_freeaddrinfo(ai); 1.4514 + return -1; 1.4515 + } 1.4516 +} 1.4517 + 1.4518 +struct evdns_getaddrinfo_request * 1.4519 +evdns_getaddrinfo(struct evdns_base *dns_base, 1.4520 + const char *nodename, const char *servname, 1.4521 + const struct evutil_addrinfo *hints_in, 1.4522 + evdns_getaddrinfo_cb cb, void *arg) 1.4523 +{ 1.4524 + struct evdns_getaddrinfo_request *data; 1.4525 + struct evutil_addrinfo hints; 1.4526 + struct evutil_addrinfo *res = NULL; 1.4527 + int err; 1.4528 + int port = 0; 1.4529 + int want_cname = 0; 1.4530 + 1.4531 + if (!dns_base) { 1.4532 + dns_base = current_base; 1.4533 + if (!dns_base) { 1.4534 + log(EVDNS_LOG_WARN, 1.4535 + "Call to getaddrinfo_async with no " 1.4536 + "evdns_base configured."); 1.4537 + cb(EVUTIL_EAI_FAIL, NULL, arg); /* ??? better error? */ 1.4538 + return NULL; 1.4539 + } 1.4540 + } 1.4541 + 1.4542 + /* If we _must_ answer this immediately, do so. */ 1.4543 + if ((hints_in && (hints_in->ai_flags & EVUTIL_AI_NUMERICHOST))) { 1.4544 + res = NULL; 1.4545 + err = evutil_getaddrinfo(nodename, servname, hints_in, &res); 1.4546 + cb(err, res, arg); 1.4547 + return NULL; 1.4548 + } 1.4549 + 1.4550 + if (hints_in) { 1.4551 + memcpy(&hints, hints_in, sizeof(hints)); 1.4552 + } else { 1.4553 + memset(&hints, 0, sizeof(hints)); 1.4554 + hints.ai_family = PF_UNSPEC; 1.4555 + } 1.4556 + 1.4557 + evutil_adjust_hints_for_addrconfig(&hints); 1.4558 + 1.4559 + /* Now try to see if we _can_ answer immediately. */ 1.4560 + /* (It would be nice to do this by calling getaddrinfo directly, with 1.4561 + * AI_NUMERICHOST, on plaforms that have it, but we can't: there isn't 1.4562 + * a reliable way to distinguish the "that wasn't a numeric host!" case 1.4563 + * from any other EAI_NONAME cases.) */ 1.4564 + err = evutil_getaddrinfo_common(nodename, servname, &hints, &res, &port); 1.4565 + if (err != EVUTIL_EAI_NEED_RESOLVE) { 1.4566 + cb(err, res, arg); 1.4567 + return NULL; 1.4568 + } 1.4569 + 1.4570 + /* If there is an entry in the hosts file, we should give it now. */ 1.4571 + if (!evdns_getaddrinfo_fromhosts(dns_base, nodename, &hints, port, &res)) { 1.4572 + cb(0, res, arg); 1.4573 + return NULL; 1.4574 + } 1.4575 + 1.4576 + /* Okay, things are serious now. We're going to need to actually 1.4577 + * launch a request. 1.4578 + */ 1.4579 + data = mm_calloc(1,sizeof(struct evdns_getaddrinfo_request)); 1.4580 + if (!data) { 1.4581 + cb(EVUTIL_EAI_MEMORY, NULL, arg); 1.4582 + return NULL; 1.4583 + } 1.4584 + 1.4585 + memcpy(&data->hints, &hints, sizeof(data->hints)); 1.4586 + data->port = (ev_uint16_t)port; 1.4587 + data->ipv4_request.type = DNS_IPv4_A; 1.4588 + data->ipv6_request.type = DNS_IPv6_AAAA; 1.4589 + data->user_cb = cb; 1.4590 + data->user_data = arg; 1.4591 + data->evdns_base = dns_base; 1.4592 + 1.4593 + want_cname = (hints.ai_flags & EVUTIL_AI_CANONNAME); 1.4594 + 1.4595 + /* If we are asked for a PF_UNSPEC address, we launch two requests in 1.4596 + * parallel: one for an A address and one for an AAAA address. We 1.4597 + * can't send just one request, since many servers only answer one 1.4598 + * question per DNS request. 1.4599 + * 1.4600 + * Once we have the answer to one request, we allow for a short 1.4601 + * timeout before we report it, to see if the other one arrives. If 1.4602 + * they both show up in time, then we report both the answers. 1.4603 + * 1.4604 + * If too many addresses of one type time out or fail, we should stop 1.4605 + * launching those requests. (XXX we don't do that yet.) 1.4606 + */ 1.4607 + 1.4608 + if (hints.ai_family != PF_INET6) { 1.4609 + log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p", 1.4610 + nodename, &data->ipv4_request); 1.4611 + 1.4612 + data->ipv4_request.r = evdns_base_resolve_ipv4(dns_base, 1.4613 + nodename, 0, evdns_getaddrinfo_gotresolve, 1.4614 + &data->ipv4_request); 1.4615 + if (want_cname) 1.4616 + data->ipv4_request.r->current_req->put_cname_in_ptr = 1.4617 + &data->cname_result; 1.4618 + } 1.4619 + if (hints.ai_family != PF_INET) { 1.4620 + log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv6 as %p", 1.4621 + nodename, &data->ipv6_request); 1.4622 + 1.4623 + data->ipv6_request.r = evdns_base_resolve_ipv6(dns_base, 1.4624 + nodename, 0, evdns_getaddrinfo_gotresolve, 1.4625 + &data->ipv6_request); 1.4626 + if (want_cname) 1.4627 + data->ipv6_request.r->current_req->put_cname_in_ptr = 1.4628 + &data->cname_result; 1.4629 + } 1.4630 + 1.4631 + evtimer_assign(&data->timeout, dns_base->event_base, 1.4632 + evdns_getaddrinfo_timeout_cb, data); 1.4633 + 1.4634 + if (data->ipv4_request.r || data->ipv6_request.r) { 1.4635 + return data; 1.4636 + } else { 1.4637 + mm_free(data); 1.4638 + cb(EVUTIL_EAI_FAIL, NULL, arg); 1.4639 + return NULL; 1.4640 + } 1.4641 +} 1.4642 + 1.4643 +void 1.4644 +evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *data) 1.4645 +{ 1.4646 + EVDNS_LOCK(data->evdns_base); 1.4647 + if (data->request_done) { 1.4648 + EVDNS_UNLOCK(data->evdns_base); 1.4649 + return; 1.4650 + } 1.4651 + event_del(&data->timeout); 1.4652 + data->user_canceled = 1; 1.4653 + if (data->ipv4_request.r) 1.4654 + evdns_cancel_request(data->evdns_base, data->ipv4_request.r); 1.4655 + if (data->ipv6_request.r) 1.4656 + evdns_cancel_request(data->evdns_base, data->ipv6_request.r); 1.4657 + EVDNS_UNLOCK(data->evdns_base); 1.4658 +}