Lines Matching +full:we +full:- +full:on +full:- +full:ns
1 /* Copyright 2006-2007 Niels Provos
2 * Copyright 2007-2012 Nick Mathewson and Niels Provos
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 /* Based on software by Adam Langly. Adam's original message:
42 * You may wish to replace the word "Parts" with something else depending on
51 #include "event2/event-config.h"
52 #include "evconfig-private.h"
96 #include "defer-internal.h"
97 #include "log-internal.h"
98 #include "mm-internal.h"
99 #include "strlcpy-internal.h"
100 #include "ipv6-internal.h"
101 #include "util-internal.h"
102 #include "evthread-internal.h"
133 EVUTIL_ASSERT((req)->handle && (req)->handle->current_req == (req))
141 /* that we bother recording */
154 /* Persistent handle. We keep this separate from 'struct request' since we
180 struct nameserver *ns; /* the server which we last sent it */ member
183 /* XXX We could turn this into a CIRCLEQ. */
193 char **put_cname_in_ptr; /* store the cname here if we get one. */
222 int failed_times; /* number of times which we have given this server a chance */
228 /* when we next probe this server. */
232 char state; /* zero if we think that this server is down */
233 char choked; /* true if we have an EAGAIN from this server's socket */
234 char write_waiting; /* true if we are waiting for EV_WRITE events */
238 * to track when we should add/del the event. */
243 /* Represents a local port where we're listening for DNS requests. Right now, */
246 evutil_socket_t socket; /* socket we use to read queries and write replies. */
248 char choked; /* Are we currently blocked from writing? */
249 char closing; /* Are we trying to close this port, pending writes? */
253 /* circular list of replies that we want to write. */
270 u16 datalen; /* Length of data; -1 if data is a label */
274 /* Represents a request that we've received as a DNS server, and holds */
275 /* the components of the reply as we're constructing it. */
277 /* Pointers to the next and previous entries on the list of replies */
278 /* that we're waiting to write. Only set if we have tried to respond */
284 struct evdns_server_port *port; /* Which port received this request on? */
296 /* Constructed response. Only set once we're ready to send a reply. */
301 /* Caller-visible fields: flags, questions. */
307 * Each inflight request req is in req_heads[req->trans_id % n_req_heads].
310 /* A circular list of requests that we're waiting to send, but haven't
319 /* The number of good nameservers that we have */
332 int global_max_reissues; /* a reissue occurs when we get some errors from the server */
333 int global_max_retransmits; /* number of times we'll retransmit a request which timed out */
334 /* number of timeouts in a row before we consider this server to be down */
336 /* true iff we will use the 0x20 hack to prevent poisoning attacks. */
339 /* The first time that a nameserver fails, how long do we wait before
392 (((char*)(base_ptr) - evutil_offsetof(struct server_request, base))))
394 #define REQ_HEAD(base, id) ((base)->req_heads[id % (base)->n_req_heads])
402 static void nameserver_send_probe(struct nameserver *const ns);
429 EVLOCK_LOCK((base)->lock, 0)
431 EVLOCK_UNLOCK((base)->lock, 0)
433 EVLOCK_ASSERT_LOCKED((base)->lock)
470 /* one with a matching transaction id. Returns NULL on */
481 if (req->trans_id == trans_id) return req; in request_find_from_trans_id()
482 req = req->next; in request_find_from_trans_id()
490 /* has gone down and we want to test if it has came back to life yet */
493 struct nameserver *const ns = (struct nameserver *) arg; in nameserver_prod_callback() local
497 EVDNS_LOCK(ns->base); in nameserver_prod_callback()
498 nameserver_send_probe(ns); in nameserver_prod_callback()
499 EVDNS_UNLOCK(ns->base); in nameserver_prod_callback()
503 /* it has come back to life) times out. We increment the count of failed_times */
506 nameserver_probe_failed(struct nameserver *const ns) { in nameserver_probe_failed() argument
510 ASSERT_LOCKED(ns->base); in nameserver_probe_failed()
511 (void) evtimer_del(&ns->timeout_event); in nameserver_probe_failed()
512 if (ns->state == 1) { in nameserver_probe_failed()
521 memcpy(&timeout, &ns->base->global_nameserver_probe_initial_timeout, in nameserver_probe_failed()
523 for (i=ns->failed_times; i > 0 && timeout.tv_sec < MAX_PROBE_TIMEOUT; --i) { in nameserver_probe_failed()
536 ns->failed_times++; in nameserver_probe_failed()
538 if (evtimer_add(&ns->timeout_event, &timeout) < 0) { in nameserver_probe_failed()
543 (struct sockaddr *)&ns->address, in nameserver_probe_failed()
549 request_swap_ns(struct request *req, struct nameserver *ns) { in request_swap_ns() argument
550 if (ns && req->ns != ns) { in request_swap_ns()
551 EVUTIL_ASSERT(req->ns->requests_inflight > 0); in request_swap_ns()
552 req->ns->requests_inflight--; in request_swap_ns()
553 ns->requests_inflight++; in request_swap_ns()
555 req->ns = ns; in request_swap_ns()
562 nameserver_failed(struct nameserver *const ns, const char *msg) { in nameserver_failed() argument
564 struct evdns_base *base = ns->base; in nameserver_failed()
571 if (!ns->state) return; in nameserver_failed()
575 (struct sockaddr *)&ns->address, in nameserver_failed()
579 base->global_good_nameservers--; in nameserver_failed()
580 EVUTIL_ASSERT(base->global_good_nameservers >= 0); in nameserver_failed()
581 if (base->global_good_nameservers == 0) { in nameserver_failed()
585 ns->state = 0; in nameserver_failed()
586 ns->failed_times = 1; in nameserver_failed()
588 if (evtimer_add(&ns->timeout_event, in nameserver_failed()
589 &base->global_nameserver_probe_initial_timeout) < 0) { in nameserver_failed()
593 (struct sockaddr *)&ns->address, in nameserver_failed()
602 /* if we don't have *any* good nameservers then there's no point */ in nameserver_failed()
604 if (!base->global_good_nameservers) return; in nameserver_failed()
606 for (i = 0; i < base->n_req_heads; ++i) { in nameserver_failed()
607 req = started_at = base->req_heads[i]; in nameserver_failed()
610 if (req->tx_count == 0 && req->ns == ns) { in nameserver_failed()
615 req = req->next; in nameserver_failed()
622 nameserver_up(struct nameserver *const ns) in nameserver_up() argument
625 ASSERT_LOCKED(ns->base); in nameserver_up()
626 if (ns->state) return; in nameserver_up()
629 (struct sockaddr *)&ns->address, in nameserver_up()
631 evtimer_del(&ns->timeout_event); in nameserver_up()
632 if (ns->probe_request) { in nameserver_up()
633 evdns_cancel_request(ns->base, ns->probe_request); in nameserver_up()
634 ns->probe_request = NULL; in nameserver_up()
636 ns->state = 1; in nameserver_up()
637 ns->failed_times = 0; in nameserver_up()
638 ns->timedout = 0; in nameserver_up()
639 ns->base->global_good_nameservers++; in nameserver_up()
644 req->trans_id = trans_id; in request_trans_id_set()
645 *((u16 *) req->request) = htons(trans_id); in request_trans_id_set()
654 struct evdns_base *base = req->base; in request_finished()
655 int was_inflight = (head != &base->req_waiting_head); in request_finished()
664 evtimer_del(&req->timeout_event); in request_finished()
665 base->global_requests_inflight--; in request_finished()
666 req->ns->requests_inflight--; in request_finished()
668 base->global_requests_waiting--; in request_finished()
671 event_debug_unassign(&req->timeout_event); in request_finished()
673 if (req->ns && in request_finished()
674 req->ns->requests_inflight == 0 && in request_finished()
675 req->base->disable_when_inactive) { in request_finished()
676 event_del(&req->ns->event); in request_finished()
677 evtimer_del(&req->ns->timeout_event); in request_finished()
680 if (!req->request_appended) { in request_finished()
681 /* need to free the request data on it's own */ in request_finished()
682 mm_free(req->request); in request_finished()
685 /* so everything gets free()ed when we: */ in request_finished()
688 if (req->handle) { in request_finished()
689 EVUTIL_ASSERT(req->handle->current_req == req); in request_finished()
692 search_request_finished(req->handle); in request_finished()
693 req->handle->current_req = NULL; in request_finished()
694 if (! req->handle->pending_cb) { in request_finished()
695 /* If we're planning to run the callback, in request_finished()
697 mm_free(req->handle); in request_finished()
699 req->handle = NULL; /* If we have a bug, let's crash in request_finished()
702 req->handle->current_req = NULL; in request_finished()
713 /* We try the request again with another server. */
720 const struct nameserver *const last_ns = req->ns; in request_reissue()
721 ASSERT_LOCKED(req->base); in request_reissue()
726 request_swap_ns(req, nameserver_pick(req->base)); in request_reissue()
727 if (req->ns == last_ns) { in request_reissue()
734 req->reissue_count++; in request_reissue()
735 req->tx_count = 0; in request_reissue()
736 req->transmit_me = 1; in request_reissue()
741 /* this function looks for space on the inflight queue and promotes */
749 while (base->global_requests_inflight < base->global_max_requests_inflight && in evdns_requests_pump_waiting_queue()
750 base->global_requests_waiting) { in evdns_requests_pump_waiting_queue()
753 EVUTIL_ASSERT(base->req_waiting_head); in evdns_requests_pump_waiting_queue()
754 req = base->req_waiting_head; in evdns_requests_pump_waiting_queue()
756 req->ns = nameserver_pick(base); in evdns_requests_pump_waiting_queue()
757 if (!req->ns) in evdns_requests_pump_waiting_queue()
761 req->ns->requests_inflight++; in evdns_requests_pump_waiting_queue()
763 evdns_request_remove(req, &base->req_waiting_head); in evdns_requests_pump_waiting_queue()
765 base->global_requests_waiting--; in evdns_requests_pump_waiting_queue()
766 base->global_requests_inflight++; in evdns_requests_pump_waiting_queue()
770 evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); in evdns_requests_pump_waiting_queue()
794 switch (cb->request_type) { in reply_run_callback()
796 if (cb->have_reply) in reply_run_callback()
797 cb->user_callback(DNS_ERR_NONE, DNS_IPv4_A, in reply_run_callback()
798 cb->reply.data.a.addrcount, cb->ttl, in reply_run_callback()
799 cb->reply.data.a.addresses, in reply_run_callback()
802 cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); in reply_run_callback()
805 if (cb->have_reply) { in reply_run_callback()
806 char *name = cb->reply.data.ptr.name; in reply_run_callback()
807 cb->user_callback(DNS_ERR_NONE, DNS_PTR, 1, cb->ttl, in reply_run_callback()
810 cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); in reply_run_callback()
814 if (cb->have_reply) in reply_run_callback()
815 cb->user_callback(DNS_ERR_NONE, DNS_IPv6_AAAA, in reply_run_callback()
816 cb->reply.data.aaaa.addrcount, cb->ttl, in reply_run_callback()
817 cb->reply.data.aaaa.addresses, in reply_run_callback()
820 cb->user_callback(cb->err, 0, 0, cb->ttl, NULL, user_pointer); in reply_run_callback()
826 if (cb->handle && cb->handle->pending_cb) { in reply_run_callback()
827 mm_free(cb->handle); in reply_run_callback()
844 ASSERT_LOCKED(req->base); in reply_schedule_callback()
846 d->request_type = req->request_type; in reply_schedule_callback()
847 d->user_callback = req->user_callback; in reply_schedule_callback()
848 d->ttl = ttl; in reply_schedule_callback()
849 d->err = err; in reply_schedule_callback()
851 d->have_reply = 1; in reply_schedule_callback()
852 memcpy(&d->reply, reply, sizeof(struct reply)); in reply_schedule_callback()
855 if (req->handle) { in reply_schedule_callback()
856 req->handle->pending_cb = 1; in reply_schedule_callback()
857 d->handle = req->handle; in reply_schedule_callback()
861 &d->deferred, in reply_schedule_callback()
862 event_get_priority(&req->timeout_event), in reply_schedule_callback()
864 req->user_pointer); in reply_schedule_callback()
866 req->base->event_base, in reply_schedule_callback()
867 &d->deferred); in reply_schedule_callback()
893 ASSERT_LOCKED(req->base); in reply_handle()
896 if (flags & (_RCODE_MASK | _TC_MASK) || !reply || !reply->have_answer) { in reply_handle()
901 u16 error_code = (flags & _RCODE_MASK) - 1; in reply_handle()
907 } else if (reply && !reply->have_answer) { in reply_handle()
916 /* we regard these errors as marking a bad nameserver */ in reply_handle()
917 if (req->reissue_count < req->base->global_max_reissues) { in reply_handle()
921 nameserver_failed(req->ns, msg); in reply_handle()
926 /* rcode 2 (servfailed) sometimes means "we in reply_handle()
934 (struct sockaddr *)&req->ns->address, in reply_handle()
940 /* we got a good reply from the nameserver: it is up. */ in reply_handle()
941 if (req->handle == req->ns->probe_request) { in reply_handle()
942 /* Avoid double-free */ in reply_handle()
943 req->ns->probe_request = NULL; in reply_handle()
946 nameserver_up(req->ns); in reply_handle()
949 if (req->handle->search_state && in reply_handle()
950 req->request_type != TYPE_PTR) { in reply_handle()
951 /* if we have a list of domains to search in, in reply_handle()
953 if (!search_try_next(req->handle)) { in reply_handle()
965 request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); in reply_handle()
969 if (req->handle == req->ns->probe_request) in reply_handle()
970 req->ns->probe_request = NULL; /* Avoid double-free */ in reply_handle()
971 nameserver_up(req->ns); in reply_handle()
972 request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); in reply_handle()
978 int name_end = -1; in name_parse()
1003 /* Make sure that the target offset is in-bounds. */ in name_parse()
1004 if (j < 0 || j >= length) return -1; in name_parse()
1005 /* If we've jumped more times than there are characters in the in name_parse()
1006 * message, we must have a loop. */ in name_parse()
1007 if (++ptr_count > length) return -1; in name_parse()
1010 if (label_len > 63) return -1; in name_parse()
1012 if (cp + 1 >= end) return -1; in name_parse()
1015 if (cp + label_len >= end) return -1; in name_parse()
1016 if (j + label_len > length) return -1; in name_parse()
1021 if (cp >= end) return -1; in name_parse()
1029 return -1; in name_parse()
1060 if (!req) return -1; in reply_parse()
1061 EVUTIL_ASSERT(req->base == base); in reply_parse()
1066 if (!(flags & _QR_MASK)) return -1; /* must be an answer */ in reply_parse()
1081 reply.type = req->request_type; in reply_parse()
1093 if (name_parse(req->request, req->request_len, &k, in reply_parse()
1096 if (!base->global_randomize_case) { in reply_parse()
1112 /* now we have the answer section which looks like in reply_parse()
1127 if (req->request_type != TYPE_A) { in reply_parse()
1133 addrtocopy = MIN(MAX_V4_ADDRS - reply.data.a.addrcount, (unsigned)addrcount); in reply_parse()
1136 /* we only bother with the first four addresses. */ in reply_parse()
1145 if (req->request_type != TYPE_PTR) { in reply_parse()
1156 if (!req->put_cname_in_ptr || *req->put_cname_in_ptr) { in reply_parse()
1162 *req->put_cname_in_ptr = mm_strdup(cname); in reply_parse()
1165 if (req->request_type != TYPE_AAAA) { in reply_parse()
1171 addrtocopy = MIN(MAX_V6_ADDRS - reply.data.aaaa.addrcount, (unsigned)addrcount); in reply_parse()
1174 /* we only bother with the first four addresses. */ in reply_parse()
1226 return -1; in reply_parse()
1230 /* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */
1256 if (flags & _QR_MASK) return -1; /* Must not be an answer. */ in request_parse()
1260 if (server_req == NULL) return -1; in request_parse()
1263 server_req->trans_id = trans_id; in request_parse()
1264 memcpy(&server_req->addr, addr, addrlen); in request_parse()
1265 server_req->addrlen = addrlen; in request_parse()
1267 server_req->base.flags = flags; in request_parse()
1268 server_req->base.nquestions = 0; in request_parse()
1269 server_req->base.questions = mm_calloc(sizeof(struct evdns_server_question *), questions); in request_parse()
1270 if (server_req->base.questions == NULL) in request_parse()
1285 q->type = type; in request_parse()
1286 q->dns_question_class = class; in request_parse()
1287 memcpy(q->name, tmp_name, namelen+1); in request_parse()
1288 server_req->base.questions[server_req->base.nquestions++] = q; in request_parse()
1293 server_req->port = port; in request_parse()
1294 port->refcnt++; in request_parse()
1298 evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL); in request_parse()
1299 return -1; in request_parse()
1302 port->user_callback(&(server_req->base), port->user_data); in request_parse()
1306 if (server_req->base.questions) { in request_parse()
1307 for (i = 0; i < server_req->base.nquestions; ++i) in request_parse()
1308 mm_free(server_req->base.questions[i]); in request_parse()
1309 mm_free(server_req->base.questions); in request_parse()
1312 return -1; in request_parse()
1347 /* nameservers which we think are down and load balance across the rest */
1351 struct nameserver *started_at = base->server_head, *picked; in nameserver_pick()
1353 if (!base->server_head) return NULL; in nameserver_pick()
1355 /* if we don't have any good nameservers then there's no */ in nameserver_pick()
1357 if (!base->global_good_nameservers) { in nameserver_pick()
1358 base->server_head = base->server_head->next; in nameserver_pick()
1359 return base->server_head; in nameserver_pick()
1364 if (base->server_head->state) { in nameserver_pick()
1365 /* we think this server is currently good */ in nameserver_pick()
1366 picked = base->server_head; in nameserver_pick()
1367 base->server_head = base->server_head->next; in nameserver_pick()
1371 base->server_head = base->server_head->next; in nameserver_pick()
1372 if (base->server_head == started_at) { in nameserver_pick()
1374 /* so we just return this one and hope for the */ in nameserver_pick()
1376 EVUTIL_ASSERT(base->global_good_nameservers == 0); in nameserver_pick()
1377 picked = base->server_head; in nameserver_pick()
1378 base->server_head = base->server_head->next; in nameserver_pick()
1386 nameserver_read(struct nameserver *ns) { in nameserver_read() argument
1391 ASSERT_LOCKED(ns->base); in nameserver_read()
1394 const int r = recvfrom(ns->socket, (void*)packet, in nameserver_read()
1398 int err = evutil_socket_geterror(ns->socket); in nameserver_read()
1401 nameserver_failed(ns, in nameserver_read()
1406 (struct sockaddr*)&ns->address, 0)) { in nameserver_read()
1407 log(EVDNS_LOG_WARN, "Address mismatch on received " in nameserver_read()
1415 ns->timedout = 0; in nameserver_read()
1416 reply_parse(ns->base, packet, r); in nameserver_read()
1420 /* Read a packet from a DNS client on a server port s, parse it, and */
1432 r = recvfrom(s->socket, (void*)packet, sizeof(packet), 0, in server_port_read()
1435 int err = evutil_socket_geterror(s->socket); in server_port_read()
1447 /* Try to write all pending replies on a given DNS server port. */
1451 struct server_request *req = port->pending_replies; in server_port_flush()
1454 int r = sendto(port->socket, req->response, (int)req->response_len, 0, in server_port_flush()
1455 (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); in server_port_flush()
1457 int err = evutil_socket_geterror(port->socket); in server_port_flush()
1463 /* we released the last reference to req->port. */ in server_port_flush()
1466 EVUTIL_ASSERT(req != port->pending_replies); in server_port_flush()
1467 req = port->pending_replies; in server_port_flush()
1471 /* We have no more pending requests; stop listening for 'writeable' events. */ in server_port_flush()
1472 (void) event_del(&port->event); in server_port_flush()
1473 event_assign(&port->event, port->event_base, in server_port_flush()
1474 port->socket, EV_READ | EV_PERSIST, in server_port_flush()
1477 if (event_add(&port->event, NULL) < 0) { in server_port_flush()
1483 /* set if we are waiting for the ability to write to this server. */
1484 /* if waiting is true then we ask libevent for EV_WRITE events, otherwise */
1485 /* we stop these events. */
1487 nameserver_write_waiting(struct nameserver *ns, char waiting) { in nameserver_write_waiting() argument
1488 ASSERT_LOCKED(ns->base); in nameserver_write_waiting()
1489 if (ns->write_waiting == waiting) return; in nameserver_write_waiting()
1491 ns->write_waiting = waiting; in nameserver_write_waiting()
1492 (void) event_del(&ns->event); in nameserver_write_waiting()
1493 event_assign(&ns->event, ns->base->event_base, in nameserver_write_waiting()
1494 ns->socket, EV_READ | (waiting ? EV_WRITE : 0) | EV_PERSIST, in nameserver_write_waiting()
1495 nameserver_ready_callback, ns); in nameserver_write_waiting()
1496 if (event_add(&ns->event, NULL) < 0) { in nameserver_write_waiting()
1500 (struct sockaddr *)&ns->address, in nameserver_write_waiting()
1510 struct nameserver *ns = (struct nameserver *) arg; in nameserver_ready_callback() local
1513 EVDNS_LOCK(ns->base); in nameserver_ready_callback()
1515 ns->choked = 0; in nameserver_ready_callback()
1516 if (!evdns_transmit(ns->base)) { in nameserver_ready_callback()
1517 nameserver_write_waiting(ns, 0); in nameserver_ready_callback()
1521 nameserver_read(ns); in nameserver_ready_callback()
1523 EVDNS_UNLOCK(ns->base); in nameserver_ready_callback()
1535 port->choked = 0; in server_port_ready_callback()
1559 table->n_labels = 0; in dnslabel_table_init()
1567 for (i = 0; i < table->n_labels; ++i) in dnslabel_clear()
1568 mm_free(table->labels[i].v); in dnslabel_clear()
1569 table->n_labels = 0; in dnslabel_clear()
1572 /* return the position of the label in the current message, or -1 if the label */
1578 for (i = 0; i < table->n_labels; ++i) { in dnslabel_table_get_pos()
1579 if (!strcmp(label, table->labels[i].v)) in dnslabel_table_get_pos()
1580 return table->labels[i].pos; in dnslabel_table_get_pos()
1582 return -1; in dnslabel_table_get_pos()
1585 /* remember that we've used the label at position pos */
1591 if (table->n_labels == MAX_LABELS) in dnslabel_table_add()
1592 return (-1); in dnslabel_table_add()
1595 return (-1); in dnslabel_table_add()
1596 p = table->n_labels++; in dnslabel_table_add()
1597 table->labels[p].v = v; in dnslabel_table_add()
1598 table->labels[p].pos = pos; in dnslabel_table_add()
1603 /* Converts a string to a length-prefixed set of DNS labels, starting */
1610 /* Returns the first index after the encoded name, or negative on error. */
1611 /* -1 label was > 63 bytes */
1612 /* -2 name too long to fit in buffer. */
1637 if (name_len > 255) return -2; in dnsname_to_labels()
1647 const size_t label_len = end - start; in dnsname_to_labels()
1648 if (label_len > 63) return -1; in dnsname_to_labels()
1649 if ((size_t)(j+label_len+1) > buf_len) return -2; in dnsname_to_labels()
1658 const size_t label_len = name - start; in dnsname_to_labels()
1659 if (label_len > 63) return -1; in dnsname_to_labels()
1660 if ((size_t)(j+label_len+1) > buf_len) return -2; in dnsname_to_labels()
1674 if (!j || buf[j-1]) buf[j++] = 0; in dnsname_to_labels()
1677 return (-2); in dnsname_to_labels()
1693 /* Returns the amount of space used. Negative on error. */
1718 return (-1); in evdns_request_data_build()
1733 port->socket = socket; in evdns_add_server_port_with_base()
1734 port->refcnt = 1; in evdns_add_server_port_with_base()
1735 port->choked = 0; in evdns_add_server_port_with_base()
1736 port->closing = 0; in evdns_add_server_port_with_base()
1737 port->user_callback = cb; in evdns_add_server_port_with_base()
1738 port->user_data = user_data; in evdns_add_server_port_with_base()
1739 port->pending_replies = NULL; in evdns_add_server_port_with_base()
1740 port->event_base = base; in evdns_add_server_port_with_base()
1742 event_assign(&port->event, port->event_base, in evdns_add_server_port_with_base()
1743 port->socket, EV_READ | EV_PERSIST, in evdns_add_server_port_with_base()
1745 if (event_add(&port->event, NULL) < 0) { in evdns_add_server_port_with_base()
1749 EVTHREAD_ALLOC_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); in evdns_add_server_port_with_base()
1764 if (--port->refcnt == 0) { in evdns_close_server_port()
1768 port->closing = 1; in evdns_close_server_port()
1780 int result = -1; in evdns_server_request_add_reply()
1782 EVDNS_LOCK(req->port); in evdns_server_request_add_reply()
1783 if (req->response) /* have we already answered? */ in evdns_server_request_add_reply()
1788 itemp = &req->answer; in evdns_server_request_add_reply()
1789 countp = &req->n_answer; in evdns_server_request_add_reply()
1792 itemp = &req->authority; in evdns_server_request_add_reply()
1793 countp = &req->n_authority; in evdns_server_request_add_reply()
1796 itemp = &req->additional; in evdns_server_request_add_reply()
1797 countp = &req->n_additional; in evdns_server_request_add_reply()
1803 itemp = &((*itemp)->next); in evdns_server_request_add_reply()
1808 item->next = NULL; in evdns_server_request_add_reply()
1809 if (!(item->name = mm_strdup(name))) { in evdns_server_request_add_reply()
1813 item->type = type; in evdns_server_request_add_reply()
1814 item->dns_question_class = class; in evdns_server_request_add_reply()
1815 item->ttl = ttl; in evdns_server_request_add_reply()
1816 item->is_name = is_name != 0; in evdns_server_request_add_reply()
1817 item->datalen = 0; in evdns_server_request_add_reply()
1818 item->data = NULL; in evdns_server_request_add_reply()
1820 if (item->is_name) { in evdns_server_request_add_reply()
1821 if (!(item->data = mm_strdup(data))) { in evdns_server_request_add_reply()
1822 mm_free(item->name); in evdns_server_request_add_reply()
1826 item->datalen = (u16)-1; in evdns_server_request_add_reply()
1828 if (!(item->data = mm_malloc(datalen))) { in evdns_server_request_add_reply()
1829 mm_free(item->name); in evdns_server_request_add_reply()
1833 item->datalen = datalen; in evdns_server_request_add_reply()
1834 memcpy(item->data, data, datalen); in evdns_server_request_add_reply()
1842 EVDNS_UNLOCK(req->port); in evdns_server_request_add_reply()
1871 return -1; in evdns_server_request_add_ptr_reply()
1873 return -1; in evdns_server_request_add_ptr_reply()
1875 a = ntohl(in->s_addr); in evdns_server_request_add_ptr_reply()
1876 evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", in evdns_server_request_add_ptr_reply()
1885 ttl, -1, 1, hostname); in evdns_server_request_add_ptr_reply()
1894 ttl, -1, 1, cname); in evdns_server_request_add_cname_reply()
1902 req->base.flags &= ~(EVDNS_FLAGS_AA|EVDNS_FLAGS_RD); in evdns_server_request_set_flags()
1903 req->base.flags |= flags; in evdns_server_request_set_flags()
1918 if (err < 0 || err > 15) return -1; in evdns_server_request_format_response()
1922 flags = req->base.flags; in evdns_server_request_format_response()
1926 APPEND16(req->trans_id); in evdns_server_request_format_response()
1928 APPEND16(req->base.nquestions); in evdns_server_request_format_response()
1929 APPEND16(req->n_answer); in evdns_server_request_format_response()
1930 APPEND16(req->n_authority); in evdns_server_request_format_response()
1931 APPEND16(req->n_additional); in evdns_server_request_format_response()
1934 for (i=0; i < req->base.nquestions; ++i) { in evdns_server_request_format_response()
1935 const char *s = req->base.questions[i]->name; in evdns_server_request_format_response()
1941 APPEND16(req->base.questions[i]->type); in evdns_server_request_format_response()
1942 APPEND16(req->base.questions[i]->dns_question_class); in evdns_server_request_format_response()
1949 item = req->answer; in evdns_server_request_format_response()
1951 item = req->authority; in evdns_server_request_format_response()
1953 item = req->additional; in evdns_server_request_format_response()
1955 r = dnsname_to_labels(buf, buf_len, j, item->name, strlen(item->name), &table); in evdns_server_request_format_response()
1960 APPEND16(item->type); in evdns_server_request_format_response()
1961 APPEND16(item->dns_question_class); in evdns_server_request_format_response()
1962 APPEND32(item->ttl); in evdns_server_request_format_response()
1963 if (item->is_name) { in evdns_server_request_format_response()
1967 r = dnsname_to_labels(buf, buf_len, j, item->data, strlen(item->data), &table); in evdns_server_request_format_response()
1971 t_ = htons( (short) (j-name_start) ); in evdns_server_request_format_response()
1974 APPEND16(item->datalen); in evdns_server_request_format_response()
1975 if (j+item->datalen > (off_t)buf_len) in evdns_server_request_format_response()
1977 memcpy(buf+j, item->data, item->datalen); in evdns_server_request_format_response()
1978 j += item->datalen; in evdns_server_request_format_response()
1980 item = item->next; in evdns_server_request_format_response()
1990 req->response_len = j; in evdns_server_request_format_response()
1992 if (!(req->response = mm_malloc(req->response_len))) { in evdns_server_request_format_response()
1995 return (-1); in evdns_server_request_format_response()
1997 memcpy(req->response, buf, req->response_len); in evdns_server_request_format_response()
2008 struct evdns_server_port *port = req->port; in evdns_server_request_respond()
2009 int r = -1; in evdns_server_request_respond()
2012 if (!req->response) { in evdns_server_request_respond()
2017 r = sendto(port->socket, req->response, (int)req->response_len, 0, in evdns_server_request_respond()
2018 (struct sockaddr*) &req->addr, (ev_socklen_t)req->addrlen); in evdns_server_request_respond()
2020 int sock_err = evutil_socket_geterror(port->socket); in evdns_server_request_respond()
2024 if (port->pending_replies) { in evdns_server_request_respond()
2025 req->prev_pending = port->pending_replies->prev_pending; in evdns_server_request_respond()
2026 req->next_pending = port->pending_replies; in evdns_server_request_respond()
2027 req->prev_pending->next_pending = in evdns_server_request_respond()
2028 req->next_pending->prev_pending = req; in evdns_server_request_respond()
2030 req->prev_pending = req->next_pending = req; in evdns_server_request_respond()
2031 port->pending_replies = req; in evdns_server_request_respond()
2032 port->choked = 1; in evdns_server_request_respond()
2034 (void) event_del(&port->event); in evdns_server_request_respond()
2035 …event_assign(&port->event, port->event_base, port->socket, (port->closing?0:EV_READ) | EV_WRITE | … in evdns_server_request_respond()
2037 if (event_add(&port->event, NULL) < 0) { in evdns_server_request_respond()
2051 if (port->pending_replies) in evdns_server_request_respond()
2068 list = &req->answer; in server_request_free_answers()
2070 list = &req->authority; in server_request_free_answers()
2072 list = &req->additional; in server_request_free_answers()
2076 next = victim->next; in server_request_free_answers()
2077 mm_free(victim->name); in server_request_free_answers()
2078 if (victim->data) in server_request_free_answers()
2079 mm_free(victim->data); in server_request_free_answers()
2088 /* return true iff we just wound up freeing the server_port. */
2093 if (req->base.questions) { in server_request_free()
2094 for (i = 0; i < req->base.nquestions; ++i) in server_request_free()
2095 mm_free(req->base.questions[i]); in server_request_free()
2096 mm_free(req->base.questions); in server_request_free()
2099 if (req->port) { in server_request_free()
2100 EVDNS_LOCK(req->port); in server_request_free()
2102 if (req->port->pending_replies == req) { in server_request_free()
2103 if (req->next_pending && req->next_pending != req) in server_request_free()
2104 req->port->pending_replies = req->next_pending; in server_request_free()
2106 req->port->pending_replies = NULL; in server_request_free()
2108 rc = --req->port->refcnt; in server_request_free()
2111 if (req->response) { in server_request_free()
2112 mm_free(req->response); in server_request_free()
2117 if (req->next_pending && req->next_pending != req) { in server_request_free()
2118 req->next_pending->prev_pending = req->prev_pending; in server_request_free()
2119 req->prev_pending->next_pending = req->next_pending; in server_request_free()
2123 EVDNS_UNLOCK(req->port); /* ????? nickm */ in server_request_free()
2124 server_port_free(req->port); in server_request_free()
2129 EVDNS_UNLOCK(req->port); in server_request_free()
2139 EVUTIL_ASSERT(!port->refcnt); in server_port_free()
2140 EVUTIL_ASSERT(!port->pending_replies); in server_port_free()
2141 if (port->socket > 0) { in server_port_free()
2142 evutil_closesocket(port->socket); in server_port_free()
2143 port->socket = -1; in server_port_free()
2145 (void) event_del(&port->event); in server_port_free()
2146 event_debug_unassign(&port->event); in server_port_free()
2147 EVTHREAD_FREE_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); in server_port_free()
2165 if (addr_len < (int)req->addrlen) in evdns_server_request_get_requesting_addr()
2166 return -1; in evdns_server_request_get_requesting_addr()
2167 memcpy(sa, &(req->addr), req->addrlen); in evdns_server_request_get_requesting_addr()
2168 return req->addrlen; in evdns_server_request_get_requesting_addr()
2179 struct evdns_base *base = req->base; in evdns_request_timeout_callback()
2187 if (req->tx_count >= req->base->global_max_retransmits) { in evdns_request_timeout_callback()
2188 struct nameserver *ns = req->ns; in evdns_request_timeout_callback() local
2190 log(EVDNS_LOG_DEBUG, "Giving up on request %p; tx_count==%d", in evdns_request_timeout_callback()
2191 arg, req->tx_count); in evdns_request_timeout_callback()
2194 request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); in evdns_request_timeout_callback()
2195 nameserver_failed(ns, "request timed out."); in evdns_request_timeout_callback()
2199 arg, req->tx_count); in evdns_request_timeout_callback()
2200 (void) evtimer_del(&req->timeout_event); in evdns_request_timeout_callback()
2204 req->ns->timedout++; in evdns_request_timeout_callback()
2205 if (req->ns->timedout > req->base->global_max_nameserver_timeout) { in evdns_request_timeout_callback()
2206 req->ns->timedout = 0; in evdns_request_timeout_callback()
2207 nameserver_failed(req->ns, "request timed out."); in evdns_request_timeout_callback()
2223 ASSERT_LOCKED(req->base); in evdns_request_transmit_to()
2226 if (server->requests_inflight == 1 && in evdns_request_transmit_to()
2227 req->base->disable_when_inactive && in evdns_request_transmit_to()
2228 event_add(&server->event, NULL) < 0) { in evdns_request_transmit_to()
2232 r = sendto(server->socket, (void*)req->request, req->request_len, 0, in evdns_request_transmit_to()
2233 (struct sockaddr *)&server->address, server->addrlen); in evdns_request_transmit_to()
2235 int err = evutil_socket_geterror(server->socket); in evdns_request_transmit_to()
2238 nameserver_failed(req->ns, evutil_socket_error_to_string(err)); in evdns_request_transmit_to()
2240 } else if (r != (int)req->request_len) { in evdns_request_transmit_to()
2257 ASSERT_LOCKED(req->base); in evdns_request_transmit()
2259 /* if we fail to send this packet then this flag marks it */ in evdns_request_transmit()
2261 req->transmit_me = 1; in evdns_request_transmit()
2262 EVUTIL_ASSERT(req->trans_id != 0xffff); in evdns_request_transmit()
2264 if (!req->ns) in evdns_request_transmit()
2270 if (req->ns->choked) { in evdns_request_transmit()
2272 /* which we have had EAGAIN from */ in evdns_request_transmit()
2276 r = evdns_request_transmit_to(req, req->ns); in evdns_request_transmit()
2280 req->ns->choked = 1; in evdns_request_transmit()
2281 nameserver_write_waiting(req->ns, 1); in evdns_request_transmit()
2284 /* failed to transmit the request entirely. we can fallthrough since in evdns_request_transmit()
2285 * we'll set a timeout, which will time out, and make us retransmit the in evdns_request_transmit()
2292 "Setting timeout for request %p, sent to nameserver %p", req, req->ns); in evdns_request_transmit()
2293 if (evtimer_add(&req->timeout_event, &req->base->global_timeout) < 0) { in evdns_request_transmit()
2299 req->tx_count++; in evdns_request_transmit()
2300 req->transmit_me = 0; in evdns_request_transmit()
2307 struct nameserver *const ns = (struct nameserver *) arg; in nameserver_probe_callback() local
2314 /* We canceled this request because the nameserver came up in nameserver_probe_callback()
2320 EVDNS_LOCK(ns->base); in nameserver_probe_callback()
2321 ns->probe_request = NULL; in nameserver_probe_callback()
2324 nameserver_up(ns); in nameserver_probe_callback()
2326 nameserver_probe_failed(ns); in nameserver_probe_callback()
2328 EVDNS_UNLOCK(ns->base); in nameserver_probe_callback()
2332 nameserver_send_probe(struct nameserver *const ns) { in nameserver_send_probe() argument
2336 /* here we need to send a probe to a given nameserver */ in nameserver_send_probe()
2339 ASSERT_LOCKED(ns->base); in nameserver_send_probe()
2342 (struct sockaddr *)&ns->address, in nameserver_send_probe()
2346 …req = request_new(ns->base, handle, TYPE_A, "google.com", DNS_QUERY_NO_SEARCH, nameserver_probe_ca… in nameserver_send_probe()
2351 ns->probe_request = handle; in nameserver_send_probe()
2352 /* we force this into the inflight queue no matter what */ in nameserver_send_probe()
2353 request_trans_id_set(req, transaction_id_pick(ns->base)); in nameserver_send_probe()
2354 req->ns = ns; in nameserver_send_probe()
2367 for (i = 0; i < base->n_req_heads; ++i) { in evdns_transmit()
2368 if (base->req_heads[i]) { in evdns_transmit()
2369 struct request *const started_at = base->req_heads[i], *req = started_at; in evdns_transmit()
2372 if (req->transmit_me) { in evdns_transmit()
2377 req = req->next; in evdns_transmit()
2393 server = base->server_head; in evdns_base_count_nameservers()
2398 server = server->next; in evdns_base_count_nameservers()
2399 } while (server != base->server_head); in evdns_base_count_nameservers()
2419 server = base->server_head; in evdns_base_clear_nameservers_and_suspend()
2420 started_at = base->server_head; in evdns_base_clear_nameservers_and_suspend()
2426 struct nameserver *next = server->next; in evdns_base_clear_nameservers_and_suspend()
2427 (void) event_del(&server->event); in evdns_base_clear_nameservers_and_suspend()
2428 if (evtimer_initialized(&server->timeout_event)) in evdns_base_clear_nameservers_and_suspend()
2429 (void) evtimer_del(&server->timeout_event); in evdns_base_clear_nameservers_and_suspend()
2430 if (server->probe_request) { in evdns_base_clear_nameservers_and_suspend()
2431 evdns_cancel_request(server->base, server->probe_request); in evdns_base_clear_nameservers_and_suspend()
2432 server->probe_request = NULL; in evdns_base_clear_nameservers_and_suspend()
2434 if (server->socket >= 0) in evdns_base_clear_nameservers_and_suspend()
2435 evutil_closesocket(server->socket); in evdns_base_clear_nameservers_and_suspend()
2441 base->server_head = NULL; in evdns_base_clear_nameservers_and_suspend()
2442 base->global_good_nameservers = 0; in evdns_base_clear_nameservers_and_suspend()
2444 for (i = 0; i < base->n_req_heads; ++i) { in evdns_base_clear_nameservers_and_suspend()
2446 req = req_started_at = base->req_heads[i]; in evdns_base_clear_nameservers_and_suspend()
2448 struct request *next = req->next; in evdns_base_clear_nameservers_and_suspend()
2449 req->tx_count = req->reissue_count = 0; in evdns_base_clear_nameservers_and_suspend()
2450 req->ns = NULL; in evdns_base_clear_nameservers_and_suspend()
2452 (void) evtimer_del(&req->timeout_event); in evdns_base_clear_nameservers_and_suspend()
2453 req->trans_id = 0; in evdns_base_clear_nameservers_and_suspend()
2454 req->transmit_me = 0; in evdns_base_clear_nameservers_and_suspend()
2456 base->global_requests_waiting++; in evdns_base_clear_nameservers_and_suspend()
2457 evdns_request_insert(req, &base->req_waiting_head); in evdns_base_clear_nameservers_and_suspend()
2458 /* We want to insert these suspended elements at the front of in evdns_base_clear_nameservers_and_suspend()
2461 * so we can just shift the start back by one.*/ in evdns_base_clear_nameservers_and_suspend()
2462 base->req_waiting_head = base->req_waiting_head->prev; in evdns_base_clear_nameservers_and_suspend()
2468 base->req_heads[i] = NULL; in evdns_base_clear_nameservers_and_suspend()
2471 base->global_requests_inflight = 0; in evdns_base_clear_nameservers_and_suspend()
2503 /* first check to see if we already have this nameserver */ in evdns_nameserver_add_impl_()
2505 const struct nameserver *server = base->server_head, *const started_at = base->server_head; in evdns_nameserver_add_impl_()
2506 struct nameserver *ns; in evdns_nameserver_add_impl_() local
2513 if (!evutil_sockaddr_cmp((struct sockaddr*)&server->address, address, 1)) return 3; in evdns_nameserver_add_impl_()
2514 server = server->next; in evdns_nameserver_add_impl_()
2517 if (addrlen > (int)sizeof(ns->address)) { in evdns_nameserver_add_impl_()
2522 ns = (struct nameserver *) mm_malloc(sizeof(struct nameserver)); in evdns_nameserver_add_impl_()
2523 if (!ns) return -1; in evdns_nameserver_add_impl_()
2525 memset(ns, 0, sizeof(struct nameserver)); in evdns_nameserver_add_impl_()
2526 ns->base = base; in evdns_nameserver_add_impl_()
2528 evtimer_assign(&ns->timeout_event, ns->base->event_base, nameserver_prod_callback, ns); in evdns_nameserver_add_impl_()
2530 ns->socket = evutil_socket_(address->sa_family, in evdns_nameserver_add_impl_()
2532 if (ns->socket < 0) { err = 1; goto out1; } in evdns_nameserver_add_impl_()
2534 if (base->global_outgoing_addrlen && in evdns_nameserver_add_impl_()
2536 if (bind(ns->socket, in evdns_nameserver_add_impl_()
2537 (struct sockaddr*)&base->global_outgoing_address, in evdns_nameserver_add_impl_()
2538 base->global_outgoing_addrlen) < 0) { in evdns_nameserver_add_impl_()
2545 if (base->so_rcvbuf) { in evdns_nameserver_add_impl_()
2546 if (setsockopt(ns->socket, SOL_SOCKET, SO_RCVBUF, in evdns_nameserver_add_impl_()
2547 (void *)&base->so_rcvbuf, sizeof(base->so_rcvbuf))) { in evdns_nameserver_add_impl_()
2548 log(EVDNS_LOG_WARN, "Couldn't set SO_RCVBUF to %i", base->so_rcvbuf); in evdns_nameserver_add_impl_()
2549 err = -SO_RCVBUF; in evdns_nameserver_add_impl_()
2553 if (base->so_sndbuf) { in evdns_nameserver_add_impl_()
2554 if (setsockopt(ns->socket, SOL_SOCKET, SO_SNDBUF, in evdns_nameserver_add_impl_()
2555 (void *)&base->so_sndbuf, sizeof(base->so_sndbuf))) { in evdns_nameserver_add_impl_()
2556 log(EVDNS_LOG_WARN, "Couldn't set SO_SNDBUF to %i", base->so_sndbuf); in evdns_nameserver_add_impl_()
2557 err = -SO_SNDBUF; in evdns_nameserver_add_impl_()
2562 memcpy(&ns->address, address, addrlen); in evdns_nameserver_add_impl_()
2563 ns->addrlen = addrlen; in evdns_nameserver_add_impl_()
2564 ns->state = 1; in evdns_nameserver_add_impl_()
2565 event_assign(&ns->event, ns->base->event_base, ns->socket, in evdns_nameserver_add_impl_()
2566 EV_READ | EV_PERSIST, nameserver_ready_callback, ns); in evdns_nameserver_add_impl_()
2567 if (!base->disable_when_inactive && event_add(&ns->event, NULL) < 0) { in evdns_nameserver_add_impl_()
2573 evutil_format_sockaddr_port_(address, addrbuf, sizeof(addrbuf)), ns); in evdns_nameserver_add_impl_()
2576 if (!base->server_head) { in evdns_nameserver_add_impl_()
2577 ns->next = ns->prev = ns; in evdns_nameserver_add_impl_()
2578 base->server_head = ns; in evdns_nameserver_add_impl_()
2580 ns->next = base->server_head->next; in evdns_nameserver_add_impl_()
2581 ns->prev = base->server_head; in evdns_nameserver_add_impl_()
2582 base->server_head->next = ns; in evdns_nameserver_add_impl_()
2583 ns->next->prev = ns; in evdns_nameserver_add_impl_()
2586 base->global_good_nameservers++; in evdns_nameserver_add_impl_()
2591 evutil_closesocket(ns->socket); in evdns_nameserver_add_impl_()
2593 event_debug_unassign(&ns->event); in evdns_nameserver_add_impl_()
2594 mm_free(ns); in evdns_nameserver_add_impl_()
2626 if (sa->sa_family == AF_INET) { in sockaddr_setport()
2627 ((struct sockaddr_in *)sa)->sin_port = htons(port); in sockaddr_setport()
2628 } else if (sa->sa_family == AF_INET6) { in sockaddr_setport()
2629 ((struct sockaddr_in6 *)sa)->sin6_port = htons(port); in sockaddr_setport()
2636 if (sa->sa_family == AF_INET) { in sockaddr_getport()
2637 return ntohs(((struct sockaddr_in *)sa)->sin_port); in sockaddr_getport()
2638 } else if (sa->sa_family == AF_INET6) { in sockaddr_getport()
2639 return ntohs(((struct sockaddr_in6 *)sa)->sin6_port); in sockaddr_getport()
2691 int result = -1; in evdns_base_get_nameserver_addr()
2695 server = base->server_head; in evdns_base_get_nameserver_addr()
2696 for (i = 0; i < idx && server; ++i, server = server->next) { in evdns_base_get_nameserver_addr()
2697 if (server->next == base->server_head) in evdns_base_get_nameserver_addr()
2703 if (server->addrlen > len) { in evdns_base_get_nameserver_addr()
2704 result = (int) server->addrlen; in evdns_base_get_nameserver_addr()
2708 memcpy(sa, &server->address, server->addrlen); in evdns_base_get_nameserver_addr()
2709 result = (int) server->addrlen; in evdns_base_get_nameserver_addr()
2719 ASSERT_LOCKED(req->base); in evdns_request_remove()
2734 ptr = ptr->next; in evdns_request_remove()
2738 EVUTIL_ASSERT(req->next); in evdns_request_remove()
2742 if (req->next == req) { in evdns_request_remove()
2746 req->next->prev = req->prev; in evdns_request_remove()
2747 req->prev->next = req->next; in evdns_request_remove()
2748 if (*head == req) *head = req->next; in evdns_request_remove()
2750 req->next = req->prev = NULL; in evdns_request_remove()
2756 ASSERT_LOCKED(req->base); in evdns_request_insert()
2760 req->next = req->prev = req; in evdns_request_insert()
2764 req->prev = (*head)->prev; in evdns_request_insert()
2765 req->prev->next = req; in evdns_request_insert()
2766 req->next = *head; in evdns_request_insert()
2767 (*head)->prev = req; in evdns_request_insert()
2786 (base->global_requests_inflight < base->global_max_requests_inflight) ? 1 : 0; in request_new()
2808 req->base = base; in request_new()
2810 evtimer_assign(&req->timeout_event, req->base->event_base, evdns_request_timeout_callback, req); in request_new()
2812 if (base->global_randomize_case) { in request_new()
2829 req->request = ((u8 *) req) + sizeof(struct request); in request_new()
2831 req->request_appended = 1; in request_new()
2833 type, CLASS_INET, req->request, request_max_len); in request_new()
2837 req->request_len = rlen; in request_new()
2838 req->trans_id = trans_id; in request_new()
2839 req->tx_count = 0; in request_new()
2840 req->request_type = type; in request_new()
2841 req->user_pointer = user_ptr; in request_new()
2842 req->user_callback = callback; in request_new()
2843 req->ns = issuing_now ? nameserver_pick(base) : NULL; in request_new()
2844 req->next = req->prev = NULL; in request_new()
2845 req->handle = handle; in request_new()
2847 handle->current_req = req; in request_new()
2848 handle->base = base; in request_new()
2859 struct evdns_base *base = req->base; in request_submit()
2862 if (req->ns) { in request_submit()
2865 evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); in request_submit()
2867 base->global_requests_inflight++; in request_submit()
2868 req->ns->requests_inflight++; in request_submit()
2872 evdns_request_insert(req, &base->req_waiting_head); in request_submit()
2873 base->global_requests_waiting++; in request_submit()
2883 if (!handle->current_req) in evdns_cancel_request()
2887 /* This redundancy is silly; can we fix it? (Not for 2.0) XXXX */ in evdns_cancel_request()
2888 base = handle->base; in evdns_cancel_request()
2890 base = handle->current_req->base; in evdns_cancel_request()
2894 if (handle->pending_cb) { in evdns_cancel_request()
2899 req = handle->current_req; in evdns_cancel_request()
2903 if (req->ns) { in evdns_cancel_request()
2905 request_finished(req, &REQ_HEAD(base, req->trans_id), 1); in evdns_cancel_request()
2908 request_finished(req, &base->req_waiting_head, 1); in evdns_cancel_request()
2934 if (handle->current_req == NULL) { in evdns_base_resolve_ipv4()
2946 ? 0 : -1; in evdns_resolve_ipv4()
2972 if (handle->current_req == NULL) { in evdns_base_resolve_ipv6()
2983 ? 0 : -1; in evdns_resolve_ipv6()
2993 a = ntohl(in->s_addr); in evdns_base_resolve_reverse()
2994 evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d.in-addr.arpa", in evdns_base_resolve_reverse()
3007 if (handle->current_req == NULL) { in evdns_base_resolve_reverse()
3017 ? 0 : -1; in evdns_resolve_reverse()
3030 for (i=15; i >= 0; --i) { in evdns_base_resolve_reverse_ipv6()
3031 u8 byte = in->s6_addr[i]; in evdns_base_resolve_reverse_ipv6()
3047 if (handle->current_req == NULL) { in evdns_base_resolve_reverse_ipv6()
3057 ? 0 : -1; in evdns_resolve_reverse_ipv6()
3071 /* to decide that a name is non-local and so try a raw lookup first. */
3089 state->refcount--; in search_state_decref()
3090 if (!state->refcount) { in search_state_decref()
3092 for (dom = state->head; dom; dom = next) { in search_state_decref()
3093 next = dom->next; in search_state_decref()
3105 state->refcount = 1; in search_state_new()
3106 state->ndots = 1; in search_state_new()
3113 search_state_decref(base->global_search_state); in search_postfix_clear()
3115 base->global_search_state = search_state_new(); in search_postfix_clear()
3140 if (!base->global_search_state) base->global_search_state = search_state_new(); in search_postfix_add()
3141 if (!base->global_search_state) return; in search_postfix_add()
3142 base->global_search_state->num_domains++; in search_postfix_add()
3147 sdomain->next = base->global_search_state->head; in search_postfix_add()
3148 sdomain->len = (int) domain_len; in search_postfix_add()
3150 base->global_search_state->head = sdomain; in search_postfix_add()
3154 /* when parsing resolv.conf we push elements in the wrong order */
3159 cur = base->global_search_state->head; in search_reverse()
3161 next = cur->next; in search_reverse()
3162 cur->next = prev; in search_reverse()
3167 base->global_search_state->head = prev; in search_reverse()
3186 if (!base->global_search_state) base->global_search_state = search_state_new(); in evdns_base_search_ndots_set()
3187 if (base->global_search_state) in evdns_base_search_ndots_set()
3188 base->global_search_state->ndots = ndots; in evdns_base_search_ndots_set()
3216 need_to_append_dot = base_name[base_len - 1] == '.' ? 0 : 1; in search_make_new()
3218 for (dom = state->head; dom; dom = dom->next) { in search_make_new()
3219 if (!n--) { in search_make_new()
3220 /* this is the postfix we want */ in search_make_new()
3223 const int postfix_len = dom->len; in search_make_new()
3234 /* we ran off the end of the list and still didn't find the requested string */ in search_make_new()
3245 EVUTIL_ASSERT(handle->current_req == NULL); in search_request_new()
3247 base->global_search_state && in search_request_new()
3248 base->global_search_state->num_domains) { in search_request_new()
3249 /* we have some domains to search */ in search_request_new()
3251 if (string_num_dots(name) >= base->global_search_state->ndots) { in search_request_new()
3254 handle->search_index = -1; in search_request_new()
3256 char *const new_name = search_make_new(base->global_search_state, 0, name); in search_request_new()
3261 handle->search_index = 0; in search_request_new()
3263 EVUTIL_ASSERT(handle->search_origname == NULL); in search_request_new()
3264 handle->search_origname = mm_strdup(name); in search_request_new()
3265 if (handle->search_origname == NULL) { in search_request_new()
3266 /* XXX Should we dealloc req? If yes, how? */ in search_request_new()
3271 handle->search_state = base->global_search_state; in search_request_new()
3272 handle->search_flags = flags; in search_request_new()
3273 base->global_search_state->refcount++; in search_request_new()
3284 /* this is called when a request has failed to find a name. We need to check */
3291 struct request *req = handle->current_req; in search_try_next()
3292 struct evdns_base *base = req->base; in search_try_next()
3295 if (handle->search_state) { in search_try_next()
3298 handle->search_index++; in search_try_next()
3299 if (handle->search_index >= handle->search_state->num_domains) { in search_try_next()
3300 /* no more postfixes to try, however we may need to try */ in search_try_next()
3302 if (string_num_dots(handle->search_origname) < handle->search_state->ndots) { in search_try_next()
3303 /* yep, we need to try it raw */ in search_try_next()
3304 …req = request_new(base, NULL, req->request_type, handle->search_origname, handle->search_flags, re… in search_try_next()
3305 log(EVDNS_LOG_DEBUG, "Search: trying raw query %s", handle->search_origname); in search_try_next()
3314 new_name = search_make_new(handle->search_state, handle->search_index, handle->search_origname); in search_try_next()
3316 log(EVDNS_LOG_DEBUG, "Search: now trying %s (%d)", new_name, handle->search_index); in search_try_next()
3317 …newreq = request_new(base, NULL, req->request_type, new_name, handle->search_flags, req->user_call… in search_try_next()
3325 request_finished(req, &REQ_HEAD(req->base, req->trans_id), 0); in search_try_next()
3326 handle->current_req = newreq; in search_try_next()
3327 newreq->handle = handle; in search_try_next()
3334 ASSERT_LOCKED(handle->current_req->base); in search_request_finished()
3335 if (handle->search_state) { in search_request_finished()
3336 search_state_decref(handle->search_state); in search_request_finished()
3337 handle->search_state = NULL; in search_request_finished()
3339 if (handle->search_origname) { in search_request_finished()
3340 mm_free(handle->search_origname); in search_request_finished()
3341 handle->search_origname = NULL; in search_request_finished()
3354 /* if the file isn't found then we assume a local resolver */ in evdns_resolv_set_defaults()
3384 /* helper version of atoi which returns -1 on error */
3390 if (*endptr) return -1; in strtoint()
3394 /* Parse a number of seconds into a timeval; return -1 on error. */
3401 if (*endptr) return -1; in evdns_strtotimeval()
3402 if (d < 0) return -1; in evdns_strtotimeval()
3403 out->tv_sec = (int) d; in evdns_strtotimeval()
3404 out->tv_usec = (int) ((d - (int) d)*1000000); in evdns_strtotimeval()
3405 if (out->tv_sec == 0 && out->tv_usec < 1000) /* less than 1 msec */ in evdns_strtotimeval()
3406 return -1; in evdns_strtotimeval()
3410 /* helper version of atoi that returns -1 on error and clips to bounds. */
3415 if (r == -1) in strtoint_clipped()
3428 int old_n_heads = base->n_req_heads, n_heads; in evdns_base_set_max_requests_inflight()
3429 struct request **old_heads = base->req_heads, **new_heads, *req; in evdns_base_set_max_requests_inflight()
3439 return (-1); in evdns_base_set_max_requests_inflight()
3445 evdns_request_insert(req, &new_heads[req->trans_id % n_heads]); in evdns_base_set_max_requests_inflight()
3450 base->req_heads = new_heads; in evdns_base_set_max_requests_inflight()
3451 base->n_req_heads = n_heads; in evdns_base_set_max_requests_inflight()
3452 base->global_max_requests_inflight = maxinflight; in evdns_base_set_max_requests_inflight()
3471 /* Option names are given as "option:" We accept either 'option' in in str_matches_option()
3476 if (slen == optlen || slen == optlen - 1) in str_matches_option()
3491 if (ndots == -1) return -1; in evdns_base_set_option_impl()
3494 if (!base->global_search_state) base->global_search_state = search_state_new(); in evdns_base_set_option_impl()
3495 if (!base->global_search_state) return -1; in evdns_base_set_option_impl()
3496 base->global_search_state->ndots = ndots; in evdns_base_set_option_impl()
3499 if (evdns_strtotimeval(val, &tv) == -1) return -1; in evdns_base_set_option_impl()
3502 memcpy(&base->global_timeout, &tv, sizeof(struct timeval)); in evdns_base_set_option_impl()
3503 } else if (str_matches_option(option, "getaddrinfo-allow-skew:")) { in evdns_base_set_option_impl()
3505 if (evdns_strtotimeval(val, &tv) == -1) return -1; in evdns_base_set_option_impl()
3507 log(EVDNS_LOG_DEBUG, "Setting getaddrinfo-allow-skew to %s", in evdns_base_set_option_impl()
3509 memcpy(&base->global_getaddrinfo_allow_skew, &tv, in evdns_base_set_option_impl()
3511 } else if (str_matches_option(option, "max-timeouts:")) { in evdns_base_set_option_impl()
3513 if (maxtimeout == -1) return -1; in evdns_base_set_option_impl()
3517 base->global_max_nameserver_timeout = maxtimeout; in evdns_base_set_option_impl()
3518 } else if (str_matches_option(option, "max-inflight:")) { in evdns_base_set_option_impl()
3520 if (maxinflight == -1) return -1; in evdns_base_set_option_impl()
3527 if (retries == -1) return -1; in evdns_base_set_option_impl()
3531 base->global_max_retransmits = retries; in evdns_base_set_option_impl()
3532 } else if (str_matches_option(option, "randomize-case:")) { in evdns_base_set_option_impl()
3534 if (randcase == -1) return -1; in evdns_base_set_option_impl()
3536 base->global_randomize_case = randcase; in evdns_base_set_option_impl()
3537 } else if (str_matches_option(option, "bind-to:")) { in evdns_base_set_option_impl()
3539 * to already-configured ones. We might want to fix that. */ in evdns_base_set_option_impl()
3540 int len = sizeof(base->global_outgoing_address); in evdns_base_set_option_impl()
3543 (struct sockaddr*)&base->global_outgoing_address, &len)) in evdns_base_set_option_impl()
3544 return -1; in evdns_base_set_option_impl()
3545 base->global_outgoing_addrlen = len; in evdns_base_set_option_impl()
3546 } else if (str_matches_option(option, "initial-probe-timeout:")) { in evdns_base_set_option_impl()
3548 if (evdns_strtotimeval(val, &tv) == -1) return -1; in evdns_base_set_option_impl()
3554 memcpy(&base->global_nameserver_probe_initial_timeout, &tv, in evdns_base_set_option_impl()
3556 } else if (str_matches_option(option, "so-rcvbuf:")) { in evdns_base_set_option_impl()
3558 if (buf == -1) return -1; in evdns_base_set_option_impl()
3561 base->so_rcvbuf = buf; in evdns_base_set_option_impl()
3562 } else if (str_matches_option(option, "so-sndbuf:")) { in evdns_base_set_option_impl()
3564 if (buf == -1) return -1; in evdns_base_set_option_impl()
3567 base->so_sndbuf = buf; in evdns_base_set_option_impl()
3689 if (err == -1) { in evdns_base_resolv_conf_parse_impl()
3711 if (!base->server_head && add_default) { in evdns_base_resolv_conf_parse_impl()
3716 …if (flags & DNS_OPTION_SEARCH && (!base->global_search_state || base->global_search_state->num_dom… in evdns_base_resolv_conf_parse_impl()
3733 /* Add multiple nameservers from a space-or-comma-separated list. */
3747 buf = mm_malloc(ips-addr+1); in evdns_nameserver_ip_add_line()
3749 memcpy(buf, addr, ips-addr); in evdns_nameserver_ip_add_line()
3750 buf[ips-addr] = '\0'; in evdns_nameserver_ip_add_line()
3765 /* Based on MSDN examples and inspection of c-ares code. */ in load_nameservers_with_getnetworkparams()
3771 IP_ADDR_STRING *ns; in load_nameservers_with_getnetworkparams() local
3778 status = -1; in load_nameservers_with_getnetworkparams()
3783 status = -1; in load_nameservers_with_getnetworkparams()
3792 status = -1; in load_nameservers_with_getnetworkparams()
3803 status = -1; in load_nameservers_with_getnetworkparams()
3810 ns = &(fixed->DnsServerList); in load_nameservers_with_getnetworkparams()
3811 while (ns) { in load_nameservers_with_getnetworkparams()
3812 r = evdns_nameserver_ip_add_line(base, ns->IpAddress.String); in load_nameservers_with_getnetworkparams()
3815 (ns->IpAddress.String),(int)GetLastError()); in load_nameservers_with_getnetworkparams()
3819 log(EVDNS_LOG_DEBUG,"Successfully added %s as nameserver",ns->IpAddress.String); in load_nameservers_with_getnetworkparams()
3822 ns = ns->Next; in load_nameservers_with_getnetworkparams()
3828 status = -1; in load_nameservers_with_getnetworkparams()
3851 return -1; in config_nameserver_from_reg_key()
3853 return -1; in config_nameserver_from_reg_key()
3890 return -1; in load_nameservers_from_registry()
3897 return -1; in load_nameservers_from_registry()
3910 return -1; in load_nameservers_from_registry()
3920 return found ? 0 : -1; in load_nameservers_from_registry()
3932 return -1; in evdns_base_config_windows_nameservers()
3955 return current_base == NULL ? -1 : 0; in evdns_config_windows_nameservers()
3973 /* Give the evutil library a hook into its evdns-enabled in evdns_base_new()
3974 * functionality. We can't just call evdns_getaddrinfo directly or in evdns_base_new()
3975 * else libevent-core will depend on libevent-extras. */ in evdns_base_new()
3983 base->req_waiting_head = NULL; in evdns_base_new()
3985 EVTHREAD_ALLOC_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); in evdns_base_new()
3989 base->req_heads = NULL; in evdns_base_new()
3993 base->server_head = NULL; in evdns_base_new()
3994 base->event_base = event_base; in evdns_base_new()
3995 base->global_good_nameservers = base->global_requests_inflight = in evdns_base_new()
3996 base->global_requests_waiting = 0; in evdns_base_new()
3998 base->global_timeout.tv_sec = 5; in evdns_base_new()
3999 base->global_timeout.tv_usec = 0; in evdns_base_new()
4000 base->global_max_reissues = 1; in evdns_base_new()
4001 base->global_max_retransmits = 3; in evdns_base_new()
4002 base->global_max_nameserver_timeout = 3; in evdns_base_new()
4003 base->global_search_state = NULL; in evdns_base_new()
4004 base->global_randomize_case = 1; in evdns_base_new()
4005 base->global_getaddrinfo_allow_skew.tv_sec = 3; in evdns_base_new()
4006 base->global_getaddrinfo_allow_skew.tv_usec = 0; in evdns_base_new()
4007 base->global_nameserver_probe_initial_timeout.tv_sec = 10; in evdns_base_new()
4008 base->global_nameserver_probe_initial_timeout.tv_usec = 0; in evdns_base_new()
4010 TAILQ_INIT(&base->hostsdb); in evdns_base_new()
4044 base->disable_when_inactive = 1; in evdns_base_new()
4059 return -1; in evdns_init()
4074 case DNS_ERR_TRUNCATED: return "reply truncated or ill-formed"; in evdns_err_to_string()
4087 if (server->socket >= 0) in evdns_nameserver_free()
4088 evutil_closesocket(server->socket); in evdns_nameserver_free()
4089 (void) event_del(&server->event); in evdns_nameserver_free()
4090 event_debug_unassign(&server->event); in evdns_nameserver_free()
4091 if (server->state == 0) in evdns_nameserver_free()
4092 (void) event_del(&server->timeout_event); in evdns_nameserver_free()
4093 if (server->probe_request) { in evdns_nameserver_free()
4094 evdns_cancel_request(server->base, server->probe_request); in evdns_nameserver_free()
4095 server->probe_request = NULL; in evdns_nameserver_free()
4097 event_debug_unassign(&server->timeout_event); in evdns_nameserver_free()
4108 /* Requires that we hold the lock. */ in evdns_base_free_and_unlock()
4110 /* TODO(nickm) we might need to refcount here. */ in evdns_base_free_and_unlock()
4112 while (base->req_waiting_head) { in evdns_base_free_and_unlock()
4114 reply_schedule_callback(base->req_waiting_head, 0, DNS_ERR_SHUTDOWN, NULL); in evdns_base_free_and_unlock()
4115 request_finished(base->req_waiting_head, &base->req_waiting_head, 1); in evdns_base_free_and_unlock()
4117 for (i = 0; i < base->n_req_heads; ++i) { in evdns_base_free_and_unlock()
4118 while (base->req_heads[i]) { in evdns_base_free_and_unlock()
4120 reply_schedule_callback(base->req_heads[i], 0, DNS_ERR_SHUTDOWN, NULL); in evdns_base_free_and_unlock()
4121 request_finished(base->req_heads[i], &REQ_HEAD(base, base->req_heads[i]->trans_id), 1); in evdns_base_free_and_unlock()
4124 base->global_requests_inflight = base->global_requests_waiting = 0; in evdns_base_free_and_unlock()
4126 for (server = base->server_head; server; server = server_next) { in evdns_base_free_and_unlock()
4127 server_next = server->next; in evdns_base_free_and_unlock()
4129 server->probe_request = NULL; in evdns_base_free_and_unlock()
4131 if (server_next == base->server_head) in evdns_base_free_and_unlock()
4134 base->server_head = NULL; in evdns_base_free_and_unlock()
4135 base->global_good_nameservers = 0; in evdns_base_free_and_unlock()
4137 if (base->global_search_state) { in evdns_base_free_and_unlock()
4138 for (dom = base->global_search_state->head; dom; dom = dom_next) { in evdns_base_free_and_unlock()
4139 dom_next = dom->next; in evdns_base_free_and_unlock()
4142 mm_free(base->global_search_state); in evdns_base_free_and_unlock()
4143 base->global_search_state = NULL; in evdns_base_free_and_unlock()
4148 while ((victim = TAILQ_FIRST(&base->hostsdb))) { in evdns_base_free_and_unlock()
4149 TAILQ_REMOVE(&base->hostsdb, victim, next); in evdns_base_free_and_unlock()
4154 mm_free(base->req_heads); in evdns_base_free_and_unlock()
4157 EVTHREAD_FREE_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); in evdns_base_free_and_unlock()
4174 while ((victim = TAILQ_FIRST(&base->hostsdb))) { in evdns_base_clear_host_addresses()
4175 TAILQ_REMOVE(&base->hostsdb, victim, next); in evdns_base_clear_host_addresses()
4210 return -1; in evdns_base_parse_hosts_line()
4212 return -1; in evdns_base_parse_hosts_line()
4215 return -1; in evdns_base_parse_hosts_line()
4230 return -1; in evdns_base_parse_hosts_line()
4231 EVUTIL_ASSERT(socklen <= (int)sizeof(he->addr)); in evdns_base_parse_hosts_line()
4232 memcpy(&he->addr, &ss, socklen); in evdns_base_parse_hosts_line()
4233 memcpy(he->hostname, hostname, namelen+1); in evdns_base_parse_hosts_line()
4234 he->addrlen = socklen; in evdns_base_parse_hosts_line()
4236 TAILQ_INSERT_TAIL(&base->hostsdb, he, next); in evdns_base_parse_hosts_line()
4262 return err ? -1 : 0; in evdns_base_load_hosts_impl()
4303 /* State data used to implement an in-progress getaddrinfo. */
4306 /* Copy of the modified 'hints' data that we'll use to build
4309 /* The callback to invoke when we're done */
4311 /* User-supplied data to give to the callback. */
4320 /* The cname result that we were told (if any) */
4323 /* If we have one request answered and one request still inflight,
4334 /* If this is set, the user can no longer cancel this request; we're
4368 if (data->pending_result) in free_getaddrinfo_request()
4369 evutil_freeaddrinfo(data->pending_result); in free_getaddrinfo_request()
4370 if (data->cname_result) in free_getaddrinfo_request()
4371 mm_free(data->cname_result); in free_getaddrinfo_request()
4372 event_del(&data->timeout); in free_getaddrinfo_request()
4381 if (data->cname_result && ai) { in add_cname_to_reply()
4382 ai->ai_canonname = data->cname_result; in add_cname_to_reply()
4383 data->cname_result = NULL; in add_cname_to_reply()
4387 /* Callback: invoked when one request in a mixed-format A/AAAA getaddrinfo
4389 * along the answer we got, and cancel the other request.
4398 if (data->ipv4_request.r) { in evdns_getaddrinfo_timeout_cb()
4401 evdns_cancel_request(NULL, data->ipv4_request.r); in evdns_getaddrinfo_timeout_cb()
4403 EVDNS_LOCK(data->evdns_base); in evdns_getaddrinfo_timeout_cb()
4404 ++data->evdns_base->getaddrinfo_ipv4_timeouts; in evdns_getaddrinfo_timeout_cb()
4405 EVDNS_UNLOCK(data->evdns_base); in evdns_getaddrinfo_timeout_cb()
4407 if (data->ipv6_request.r) { in evdns_getaddrinfo_timeout_cb()
4410 evdns_cancel_request(NULL, data->ipv6_request.r); in evdns_getaddrinfo_timeout_cb()
4412 EVDNS_LOCK(data->evdns_base); in evdns_getaddrinfo_timeout_cb()
4413 ++data->evdns_base->getaddrinfo_ipv6_timeouts; in evdns_getaddrinfo_timeout_cb()
4414 EVDNS_UNLOCK(data->evdns_base); in evdns_getaddrinfo_timeout_cb()
4417 /* We only use this timeout callback when we have an answer for in evdns_getaddrinfo_timeout_cb()
4422 if (data->pending_result) { in evdns_getaddrinfo_timeout_cb()
4423 add_cname_to_reply(data, data->pending_result); in evdns_getaddrinfo_timeout_cb()
4424 data->user_cb(0, data->pending_result, data->user_data); in evdns_getaddrinfo_timeout_cb()
4425 data->pending_result = NULL; in evdns_getaddrinfo_timeout_cb()
4427 int e = data->pending_error; in evdns_getaddrinfo_timeout_cb()
4430 data->user_cb(e, NULL, data->user_data); in evdns_getaddrinfo_timeout_cb()
4433 data->user_cb = NULL; /* prevent double-call if evdns callbacks are in evdns_getaddrinfo_timeout_cb()
4434 * in-progress. XXXX It would be better if this in evdns_getaddrinfo_timeout_cb()
4447 return event_add(&data->timeout, &evdns_base->global_getaddrinfo_allow_skew); in evdns_getaddrinfo_set_timeout()
4476 EVUTIL_ASSERT(req->type == DNS_IPv4_A || req->type == DNS_IPv6_AAAA); in evdns_getaddrinfo_gotresolve()
4477 if (req->type == DNS_IPv4_A) { in evdns_getaddrinfo_gotresolve()
4479 other_req = &data->ipv6_request; in evdns_getaddrinfo_gotresolve()
4482 other_req = &data->ipv4_request; in evdns_getaddrinfo_gotresolve()
4487 EVDNS_LOCK(data->evdns_base); in evdns_getaddrinfo_gotresolve()
4489 if (req->type == DNS_IPv4_A) in evdns_getaddrinfo_gotresolve()
4490 ++data->evdns_base->getaddrinfo_ipv4_answered; in evdns_getaddrinfo_gotresolve()
4492 ++data->evdns_base->getaddrinfo_ipv6_answered; in evdns_getaddrinfo_gotresolve()
4494 user_canceled = data->user_canceled; in evdns_getaddrinfo_gotresolve()
4495 if (other_req->r == NULL) in evdns_getaddrinfo_gotresolve()
4496 data->request_done = 1; in evdns_getaddrinfo_gotresolve()
4497 EVDNS_UNLOCK(data->evdns_base); in evdns_getaddrinfo_gotresolve()
4499 data->evdns_base = NULL; in evdns_getaddrinfo_gotresolve()
4500 user_canceled = data->user_canceled; in evdns_getaddrinfo_gotresolve()
4503 req->r = NULL; in evdns_getaddrinfo_gotresolve()
4507 * we already answered the user. */ in evdns_getaddrinfo_gotresolve()
4508 if (other_req->r == NULL) in evdns_getaddrinfo_gotresolve()
4513 if (data->user_cb == NULL) { in evdns_getaddrinfo_gotresolve()
4514 /* We already answered. XXXX This shouldn't be needed; see in evdns_getaddrinfo_gotresolve()
4530 /* Looks like we got an error. */ in evdns_getaddrinfo_gotresolve()
4531 if (other_req->r) { in evdns_getaddrinfo_gotresolve()
4536 evdns_getaddrinfo_set_timeout(data->evdns_base, data); in evdns_getaddrinfo_gotresolve()
4538 data->pending_error = err; in evdns_getaddrinfo_gotresolve()
4543 data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); in evdns_getaddrinfo_gotresolve()
4544 } else if (data->pending_result) { in evdns_getaddrinfo_gotresolve()
4545 /* If we have an answer waiting, and we weren't in evdns_getaddrinfo_gotresolve()
4547 add_cname_to_reply(data, data->pending_result); in evdns_getaddrinfo_gotresolve()
4548 data->user_cb(0, data->pending_result, data->user_data); in evdns_getaddrinfo_gotresolve()
4549 data->pending_result = NULL; in evdns_getaddrinfo_gotresolve()
4551 if (data->pending_error) in evdns_getaddrinfo_gotresolve()
4553 data->pending_error); in evdns_getaddrinfo_gotresolve()
4554 data->user_cb(err, NULL, data->user_data); in evdns_getaddrinfo_gotresolve()
4559 if (other_req->r) { in evdns_getaddrinfo_gotresolve()
4565 data->user_cb(EVUTIL_EAI_CANCEL, NULL, data->user_data); in evdns_getaddrinfo_gotresolve()
4570 /* Looks like we got some answers. We should turn them into addrinfos in evdns_getaddrinfo_gotresolve()
4577 sin.sin_port = htons(data->port); in evdns_getaddrinfo_gotresolve()
4586 sin6.sin6_port = htons(data->port); in evdns_getaddrinfo_gotresolve()
4598 ai = evutil_new_addrinfo_(sa, socklen, &data->hints); in evdns_getaddrinfo_gotresolve()
4600 if (other_req->r) { in evdns_getaddrinfo_gotresolve()
4601 evdns_cancel_request(NULL, other_req->r); in evdns_getaddrinfo_gotresolve()
4603 data->user_cb(EVUTIL_EAI_MEMORY, NULL, data->user_data); in evdns_getaddrinfo_gotresolve()
4607 if (other_req->r == NULL) in evdns_getaddrinfo_gotresolve()
4614 if (other_req->r) { in evdns_getaddrinfo_gotresolve()
4617 evdns_getaddrinfo_set_timeout(data->evdns_base, data); in evdns_getaddrinfo_gotresolve()
4618 data->pending_result = res; in evdns_getaddrinfo_gotresolve()
4623 if (data->pending_result) { in evdns_getaddrinfo_gotresolve()
4624 if (req->type == DNS_IPv4_A) in evdns_getaddrinfo_gotresolve()
4626 data->pending_result); in evdns_getaddrinfo_gotresolve()
4629 data->pending_result, res); in evdns_getaddrinfo_gotresolve()
4630 data->pending_result = NULL; in evdns_getaddrinfo_gotresolve()
4635 data->user_cb(0, res, data->user_data); in evdns_getaddrinfo_gotresolve()
4651 e = TAILQ_FIRST(&base->hostsdb); in find_hosts_entry()
4654 if (!evutil_ascii_strcasecmp(e->hostname, hostname)) in find_hosts_entry()
4668 int f = hints->ai_family; in evdns_getaddrinfo_fromhosts()
4675 if ((e->addr.sa.sa_family == AF_INET && f == PF_INET6) || in evdns_getaddrinfo_fromhosts()
4676 (e->addr.sa.sa_family == AF_INET6 && f == PF_INET)) in evdns_getaddrinfo_fromhosts()
4678 ai_new = evutil_new_addrinfo_(&e->addr.sa, e->addrlen, hints); in evdns_getaddrinfo_fromhosts()
4683 sockaddr_setport(ai_new->ai_addr, port); in evdns_getaddrinfo_fromhosts()
4689 /* Note that we return an empty answer if we found entries for in evdns_getaddrinfo_fromhosts()
4696 return -1; in evdns_getaddrinfo_fromhosts()
4725 /* If we _must_ answer this immediately, do so. */ in evdns_getaddrinfo()
4726 if ((hints_in && (hints_in->ai_flags & EVUTIL_AI_NUMERICHOST))) { in evdns_getaddrinfo()
4742 /* Now try to see if we _can_ answer immediately. */ in evdns_getaddrinfo()
4744 * AI_NUMERICHOST, on plaforms that have it, but we can't: there isn't in evdns_getaddrinfo()
4753 /* If there is an entry in the hosts file, we should give it now. */ in evdns_getaddrinfo()
4759 /* Okay, things are serious now. We're going to need to actually in evdns_getaddrinfo()
4768 memcpy(&data->hints, &hints, sizeof(data->hints)); in evdns_getaddrinfo()
4769 data->port = (ev_uint16_t)port; in evdns_getaddrinfo()
4770 data->ipv4_request.type = DNS_IPv4_A; in evdns_getaddrinfo()
4771 data->ipv6_request.type = DNS_IPv6_AAAA; in evdns_getaddrinfo()
4772 data->user_cb = cb; in evdns_getaddrinfo()
4773 data->user_data = arg; in evdns_getaddrinfo()
4774 data->evdns_base = dns_base; in evdns_getaddrinfo()
4778 /* If we are asked for a PF_UNSPEC address, we launch two requests in in evdns_getaddrinfo()
4779 * parallel: one for an A address and one for an AAAA address. We in evdns_getaddrinfo()
4783 * Once we have the answer to one request, we allow for a short in evdns_getaddrinfo()
4784 * timeout before we report it, to see if the other one arrives. If in evdns_getaddrinfo()
4785 * they both show up in time, then we report both the answers. in evdns_getaddrinfo()
4787 * If too many addresses of one type time out or fail, we should stop in evdns_getaddrinfo()
4788 * launching those requests. (XXX we don't do that yet.) in evdns_getaddrinfo()
4794 log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p", in evdns_getaddrinfo()
4795 nodename, &data->ipv4_request); in evdns_getaddrinfo()
4797 data->ipv4_request.r = evdns_base_resolve_ipv4(dns_base, in evdns_getaddrinfo()
4799 &data->ipv4_request); in evdns_getaddrinfo()
4800 if (want_cname && data->ipv4_request.r) in evdns_getaddrinfo()
4801 data->ipv4_request.r->current_req->put_cname_in_ptr = in evdns_getaddrinfo()
4802 &data->cname_result; in evdns_getaddrinfo()
4805 log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv6 as %p", in evdns_getaddrinfo()
4806 nodename, &data->ipv6_request); in evdns_getaddrinfo()
4808 data->ipv6_request.r = evdns_base_resolve_ipv6(dns_base, in evdns_getaddrinfo()
4810 &data->ipv6_request); in evdns_getaddrinfo()
4811 if (want_cname && data->ipv6_request.r) in evdns_getaddrinfo()
4812 data->ipv6_request.r->current_req->put_cname_in_ptr = in evdns_getaddrinfo()
4813 &data->cname_result; in evdns_getaddrinfo()
4816 evtimer_assign(&data->timeout, dns_base->event_base, in evdns_getaddrinfo()
4819 started = (data->ipv4_request.r || data->ipv6_request.r); in evdns_getaddrinfo()
4835 EVDNS_LOCK(data->evdns_base); in evdns_getaddrinfo_cancel()
4836 if (data->request_done) { in evdns_getaddrinfo_cancel()
4837 EVDNS_UNLOCK(data->evdns_base); in evdns_getaddrinfo_cancel()
4840 event_del(&data->timeout); in evdns_getaddrinfo_cancel()
4841 data->user_canceled = 1; in evdns_getaddrinfo_cancel()
4842 if (data->ipv4_request.r) in evdns_getaddrinfo_cancel()
4843 evdns_cancel_request(data->evdns_base, data->ipv4_request.r); in evdns_getaddrinfo_cancel()
4844 if (data->ipv6_request.r) in evdns_getaddrinfo_cancel()
4845 evdns_cancel_request(data->evdns_base, data->ipv6_request.r); in evdns_getaddrinfo_cancel()
4846 EVDNS_UNLOCK(data->evdns_base); in evdns_getaddrinfo_cancel()