Lines Matching +full:port +full:- +full:base

1 /* Copyright 2006-2007 Niels Provos
2 * Copyright 2007-2012 Nick Mathewson and Niels Provos
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))
160 struct evdns_base *base; member
163 * owned by event base any more. */
195 struct evdns_base *base; member
235 struct evdns_base *base; member
243 /* Represents a local port where we're listening for DNS requests. Right now, */
249 char closing; /* Are we trying to close this port, pending writes? */
270 u16 datalen; /* Length of data; -1 if data is a label */
284 struct evdns_server_port *port; /* Which port received this request on? */ member
301 /* Caller-visible fields: flags, questions. */
302 struct evdns_server_request base; member
307 * Each inflight request req is in req_heads[req->trans_id % n_req_heads].
343 /** Port to bind to for outgoing DNS packets. */
392 (((char*)(base_ptr) - evutil_offsetof(struct server_request, base))))
394 #define REQ_HEAD(base, id) ((base)->req_heads[id % (base)->n_req_heads]) argument
396 static struct nameserver *nameserver_pick(struct evdns_base *base);
400 static int evdns_transmit(struct evdns_base *base);
405 static struct request *search_request_new(struct evdns_base *base, struct evdns_request *handle, in…
406 static void evdns_requests_pump_waiting_queue(struct evdns_base *base);
407 static u16 transaction_id_pick(struct evdns_base *base);
408 static struct request *request_new(struct evdns_base *base, struct evdns_request *handle, int type,…
413 static void server_port_free(struct evdns_server_port *port);
415 static int evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const …
416 static int evdns_base_set_option_impl(struct evdns_base *base,
418 static void evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests);
424 #define EVDNS_LOCK(base) EVUTIL_NIL_STMT_ argument
425 #define EVDNS_UNLOCK(base) EVUTIL_NIL_STMT_ argument
426 #define ASSERT_LOCKED(base) EVUTIL_NIL_STMT_ argument
428 #define EVDNS_LOCK(base) \ argument
429 EVLOCK_LOCK((base)->lock, 0)
430 #define EVDNS_UNLOCK(base) \ argument
431 EVLOCK_UNLOCK((base)->lock, 0)
432 #define ASSERT_LOCKED(base) \ argument
433 EVLOCK_ASSERT_LOCKED((base)->lock)
473 request_find_from_trans_id(struct evdns_base *base, u16 trans_id) { in request_find_from_trans_id() argument
474 struct request *req = REQ_HEAD(base, trans_id); in request_find_from_trans_id()
477 ASSERT_LOCKED(base); in request_find_from_trans_id()
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()
497 EVDNS_LOCK(ns->base); in nameserver_prod_callback()
499 EVDNS_UNLOCK(ns->base); in nameserver_prod_callback()
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()
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()
564 struct evdns_base *base = ns->base; in nameserver_failed() local
568 ASSERT_LOCKED(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()
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()
613 request_swap_ns(req, nameserver_pick(base)); in nameserver_failed()
615 req = req->next; in nameserver_failed()
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() local
655 int was_inflight = (head != &base->req_waiting_head); in request_finished()
656 EVDNS_LOCK(base); 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()
682 mm_free(req->request); 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()
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()
708 evdns_requests_pump_waiting_queue(base); in request_finished()
709 EVDNS_UNLOCK(base); in request_finished()
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()
747 evdns_requests_pump_waiting_queue(struct evdns_base *base) { in evdns_requests_pump_waiting_queue() argument
748 ASSERT_LOCKED(base); in evdns_requests_pump_waiting_queue()
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()
768 request_trans_id_set(req, transaction_id_pick(base)); in evdns_requests_pump_waiting_queue()
770 evdns_request_insert(req, &REQ_HEAD(base, req->trans_id)); in evdns_requests_pump_waiting_queue()
772 evdns_transmit(base); 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()
917 if (req->reissue_count < req->base->global_max_reissues) { in reply_handle()
921 nameserver_failed(req->ns, msg); in reply_handle()
934 (struct sockaddr *)&req->ns->address, 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()
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()
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()
1034 reply_parse(struct evdns_base *base, u8 *packet, int length) { in reply_parse() argument
1048 ASSERT_LOCKED(base); in reply_parse()
1059 req = request_find_from_trans_id(base, trans_id); in reply_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()
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()
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()
1226 return -1; in reply_parse()
1229 /* Parse a raw request (packet,length) sent to a nameserver port (port) from */
1230 /* a DNS client (addr,addrlen), and if it's well-formed, call the corresponding */
1233 request_parse(u8 *packet, int length, struct evdns_server_port *port, struct sockaddr *addr, ev_soc… in request_parse() argument
1243 ASSERT_LOCKED(port); in request_parse()
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()
1333 transaction_id_pick(struct evdns_base *base) { in transaction_id_pick() argument
1334 ASSERT_LOCKED(base); in transaction_id_pick()
1341 if (request_find_from_trans_id(base, trans_id) == NULL) in transaction_id_pick()
1350 nameserver_pick(struct evdns_base *base) { in nameserver_pick() argument
1351 struct nameserver *started_at = base->server_head, *picked; in nameserver_pick()
1352 ASSERT_LOCKED(base); in nameserver_pick()
1353 if (!base->server_head) return NULL; 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()
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()
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()
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()
1406 (struct sockaddr*)&ns->address, 0)) { 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. */
1449 server_port_flush(struct evdns_server_port *port) in server_port_flush() argument
1451 struct server_request *req = port->pending_replies; in server_port_flush()
1452 ASSERT_LOCKED(port); 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()
1460 …log(EVDNS_LOG_WARN, "Error %s (%d) while writing response to port; dropping", evutil_socket_error_… 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()
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()
1475 server_port_ready_callback, port); in server_port_flush()
1477 if (event_add(&port->event, NULL) < 0) { in server_port_flush()
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()
1496 if (event_add(&ns->event, NULL) < 0) { in nameserver_write_waiting()
1500 (struct sockaddr *)&ns->address, in nameserver_write_waiting()
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()
1523 EVDNS_UNLOCK(ns->base); in nameserver_ready_callback()
1530 struct evdns_server_port *port = (struct evdns_server_port *) arg; in server_port_ready_callback() local
1533 EVDNS_LOCK(port); in server_port_ready_callback()
1535 port->choked = 0; in server_port_ready_callback()
1536 server_port_flush(port); in server_port_ready_callback()
1539 server_port_read(port); in server_port_ready_callback()
1541 EVDNS_UNLOCK(port); 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()
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 */
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()
1718 return (-1); in evdns_request_data_build()
1723 evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_r… in evdns_add_server_port_with_base() argument
1725 struct evdns_server_port *port; in evdns_add_server_port_with_base() local
1728 if (!(port = mm_malloc(sizeof(struct evdns_server_port)))) in evdns_add_server_port_with_base()
1730 memset(port, 0, sizeof(struct evdns_server_port)); in evdns_add_server_port_with_base()
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()
1744 server_port_ready_callback, port); in evdns_add_server_port_with_base()
1745 if (event_add(&port->event, NULL) < 0) { in evdns_add_server_port_with_base()
1746 mm_free(port); in evdns_add_server_port_with_base()
1749 EVTHREAD_ALLOC_LOCK(port->lock, EVTHREAD_LOCKTYPE_RECURSIVE); in evdns_add_server_port_with_base()
1750 return port; in evdns_add_server_port_with_base()
1761 evdns_close_server_port(struct evdns_server_port *port) in evdns_close_server_port() argument
1763 EVDNS_LOCK(port); in evdns_close_server_port()
1764 if (--port->refcnt == 0) { in evdns_close_server_port()
1765 EVDNS_UNLOCK(port); in evdns_close_server_port()
1766 server_port_free(port); in evdns_close_server_port()
1768 port->closing = 1; in evdns_close_server_port()
1769 EVDNS_UNLOCK(port); 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() local
2009 int r = -1; in evdns_server_request_respond()
2011 EVDNS_LOCK(port); 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 …ent_assign(&port->event, port->event_base, port->socket, (port->closing?0:EV_READ) | EV_WRITE | EV… 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()
2052 server_port_flush(port); in evdns_server_request_respond()
2056 EVDNS_UNLOCK(port); 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()
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()
2136 server_port_free(struct evdns_server_port *port) in server_port_free() argument
2138 EVUTIL_ASSERT(port); in server_port_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()
2148 mm_free(port); 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() local
2185 EVDNS_LOCK(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()
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()
2199 arg, req->tx_count); in evdns_request_timeout_callback()
2200 (void) evtimer_del(&req->timeout_event); in evdns_request_timeout_callback()
2201 request_swap_ns(req, nameserver_pick(base)); 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()
2211 EVDNS_UNLOCK(base); 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()
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()
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()
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()
2320 EVDNS_LOCK(ns->base); in nameserver_probe_callback()
2321 ns->probe_request = NULL; in nameserver_probe_callback()
2328 EVDNS_UNLOCK(ns->base); in nameserver_probe_callback()
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()
2353 request_trans_id_set(req, transaction_id_pick(ns->base)); in nameserver_send_probe()
2354 req->ns = ns; in nameserver_send_probe()
2362 evdns_transmit(struct evdns_base *base) { in evdns_transmit() argument
2366 ASSERT_LOCKED(base); in evdns_transmit()
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()
2387 evdns_base_count_nameservers(struct evdns_base *base) in evdns_base_count_nameservers() argument
2392 EVDNS_LOCK(base); in evdns_base_count_nameservers()
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()
2401 EVDNS_UNLOCK(base); in evdns_base_count_nameservers()
2413 evdns_base_clear_nameservers_and_suspend(struct evdns_base *base) in evdns_base_clear_nameservers_and_suspend() argument
2418 EVDNS_LOCK(base); in evdns_base_clear_nameservers_and_suspend()
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()
2422 EVDNS_UNLOCK(base); 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()
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()
2473 EVDNS_UNLOCK(base); in evdns_base_clear_nameservers_and_suspend()
2486 evdns_base_resume(struct evdns_base *base) in evdns_base_resume() argument
2488 EVDNS_LOCK(base); in evdns_base_resume()
2489 evdns_requests_pump_waiting_queue(base); in evdns_base_resume()
2490 EVDNS_UNLOCK(base); in evdns_base_resume()
2502 evdns_nameserver_add_impl_(struct evdns_base *base, const struct sockaddr *address, int addrlen) { in evdns_nameserver_add_impl_() argument
2505 const struct nameserver *server = base->server_head, *const started_at = base->server_head; in evdns_nameserver_add_impl_()
2510 ASSERT_LOCKED(base); in evdns_nameserver_add_impl_()
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_()
2523 if (!ns) return -1; 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_()
2567 if (!base->disable_when_inactive && event_add(&ns->event, NULL) < 0) { 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_()
2602 evdns_base_nameserver_add(struct evdns_base *base, unsigned long int address) in evdns_base_nameserver_add() argument
2610 EVDNS_LOCK(base); in evdns_base_nameserver_add()
2611 res = evdns_nameserver_add_impl_(base, (struct sockaddr*)&sin, sizeof(sin)); in evdns_base_nameserver_add()
2612 EVDNS_UNLOCK(base); in evdns_base_nameserver_add()
2624 sockaddr_setport(struct sockaddr *sa, ev_uint16_t port) in sockaddr_setport() argument
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()
2647 evdns_base_nameserver_ip_add(struct evdns_base *base, const char *ip_as_string) { in evdns_base_nameserver_ip_add() argument
2662 EVDNS_LOCK(base); in evdns_base_nameserver_ip_add()
2663 res = evdns_nameserver_add_impl_(base, sa, len); in evdns_base_nameserver_ip_add()
2664 EVDNS_UNLOCK(base); in evdns_base_nameserver_ip_add()
2676 evdns_base_nameserver_sockaddr_add(struct evdns_base *base, in evdns_base_nameserver_sockaddr_add() argument
2680 EVUTIL_ASSERT(base); in evdns_base_nameserver_sockaddr_add()
2681 EVDNS_LOCK(base); in evdns_base_nameserver_sockaddr_add()
2682 res = evdns_nameserver_add_impl_(base, sa, len); in evdns_base_nameserver_sockaddr_add()
2683 EVDNS_UNLOCK(base); in evdns_base_nameserver_sockaddr_add()
2688 evdns_base_get_nameserver_addr(struct evdns_base *base, int idx, in evdns_base_get_nameserver_addr() argument
2691 int result = -1; in evdns_base_get_nameserver_addr()
2694 EVDNS_LOCK(base); 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()
2711 EVDNS_UNLOCK(base); 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()
2781 request_new(struct evdns_base *base, struct evdns_request *handle, int type, in request_new() argument
2786 (base->global_requests_inflight < base->global_max_requests_inflight) ? 1 : 0; in request_new()
2790 const u16 trans_id = issuing_now ? transaction_id_pick(base) : 0xffff; in request_new()
2798 ASSERT_LOCKED(base); 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() local
2860 ASSERT_LOCKED(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()
2879 evdns_cancel_request(struct evdns_base *base, struct evdns_request *handle) in evdns_cancel_request() argument
2883 if (!handle->current_req) in evdns_cancel_request()
2886 if (!base) { in evdns_cancel_request()
2888 base = handle->base; in evdns_cancel_request()
2889 if (!base) in evdns_cancel_request()
2890 base = handle->current_req->base; in evdns_cancel_request()
2893 EVDNS_LOCK(base); in evdns_cancel_request()
2894 if (handle->pending_cb) { in evdns_cancel_request()
2895 EVDNS_UNLOCK(base); 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()
2910 EVDNS_UNLOCK(base); in evdns_cancel_request()
2915 evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, in evdns_base_resolve_ipv4() argument
2923 EVDNS_LOCK(base); in evdns_base_resolve_ipv4()
2926 request_new(base, handle, TYPE_A, name, flags, in evdns_base_resolve_ipv4()
2931 search_request_new(base, handle, TYPE_A, name, flags, in evdns_base_resolve_ipv4()
2934 if (handle->current_req == NULL) { in evdns_base_resolve_ipv4()
2938 EVDNS_UNLOCK(base); in evdns_base_resolve_ipv4()
2946 ? 0 : -1; in evdns_resolve_ipv4()
2952 evdns_base_resolve_ipv6(struct evdns_base *base, in evdns_base_resolve_ipv6() argument
2962 EVDNS_LOCK(base); in evdns_base_resolve_ipv6()
2964 req = request_new(base, handle, TYPE_AAAA, name, flags, in evdns_base_resolve_ipv6()
2969 search_request_new(base, handle, TYPE_AAAA, name, flags, in evdns_base_resolve_ipv6()
2972 if (handle->current_req == NULL) { in evdns_base_resolve_ipv6()
2976 EVDNS_UNLOCK(base); in evdns_base_resolve_ipv6()
2983 ? 0 : -1; in evdns_resolve_ipv6()
2987 evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_call… in evdns_base_resolve_reverse() argument
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()
3003 EVDNS_LOCK(base); in evdns_base_resolve_reverse()
3004 req = request_new(base, handle, TYPE_PTR, buf, flags, callback, ptr); in evdns_base_resolve_reverse()
3007 if (handle->current_req == NULL) { in evdns_base_resolve_reverse()
3011 EVDNS_UNLOCK(base); in evdns_base_resolve_reverse()
3017 ? 0 : -1; in evdns_resolve_reverse()
3021 evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdn… in evdns_base_resolve_reverse_ipv6() argument
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()
3043 EVDNS_LOCK(base); in evdns_base_resolve_reverse_ipv6()
3044 req = request_new(base, handle, TYPE_PTR, buf, flags, callback, ptr); in evdns_base_resolve_reverse_ipv6()
3047 if (handle->current_req == NULL) { in evdns_base_resolve_reverse_ipv6()
3051 EVDNS_UNLOCK(base); 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()
3112 search_postfix_clear(struct evdns_base *base) { in search_postfix_clear() argument
3113 search_state_decref(base->global_search_state); in search_postfix_clear()
3115 base->global_search_state = search_state_new(); in search_postfix_clear()
3120 evdns_base_search_clear(struct evdns_base *base) in evdns_base_search_clear() argument
3122 EVDNS_LOCK(base); in evdns_base_search_clear()
3123 search_postfix_clear(base); in evdns_base_search_clear()
3124 EVDNS_UNLOCK(base); in evdns_base_search_clear()
3133 search_postfix_add(struct evdns_base *base, const char *domain) { in search_postfix_add() argument
3139 ASSERT_LOCKED(base); in search_postfix_add()
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()
3156 search_reverse(struct evdns_base *base) { in search_reverse() argument
3158 ASSERT_LOCKED(base); in search_reverse()
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()
3172 evdns_base_search_add(struct evdns_base *base, const char *domain) { in evdns_base_search_add() argument
3173 EVDNS_LOCK(base); in evdns_base_search_add()
3174 search_postfix_add(base, domain); in evdns_base_search_add()
3175 EVDNS_UNLOCK(base); in evdns_base_search_add()
3184 evdns_base_search_ndots_set(struct evdns_base *base, const int ndots) { in evdns_base_search_ndots_set() argument
3185 EVDNS_LOCK(base); in evdns_base_search_ndots_set()
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()
3189 EVDNS_UNLOCK(base); in evdns_base_search_ndots_set()
3197 search_set_from_hostname(struct evdns_base *base) { in search_set_from_hostname() argument
3200 ASSERT_LOCKED(base); in search_set_from_hostname()
3201 search_postfix_clear(base); in search_set_from_hostname()
3205 search_postfix_add(base, domainname); in search_set_from_hostname()
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()
3223 const int postfix_len = dom->len; in search_make_new()
3240 search_request_new(struct evdns_base *base, struct evdns_request *handle, in search_request_new() argument
3243 ASSERT_LOCKED(base); in search_request_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()
3251 if (string_num_dots(name) >= base->global_search_state->ndots) { in search_request_new()
3252 req = request_new(base, handle, type, name, flags, user_callback, user_arg); 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()
3258 req = request_new(base, handle, type, new_name, flags, user_callback, user_arg); 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()
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()
3277 struct request *const req = request_new(base, handle, type, name, flags, user_callback, user_arg); in search_request_new()
3291 struct request *req = handle->current_req; in search_try_next()
3292 struct evdns_base *base = req->base; in search_try_next() local
3294 ASSERT_LOCKED(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()
3302 if (string_num_dots(handle->search_origname) < handle->search_state->ndots) { in search_try_next()
3304 …newreq = request_new(base, NULL, req->request_type, handle->search_origname, handle->search_flags,… 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()
3349 evdns_resolv_set_defaults(struct evdns_base *base, int flags) { in evdns_resolv_set_defaults() argument
3355 ASSERT_LOCKED(base); in evdns_resolv_set_defaults()
3357 search_set_from_hostname(base); in evdns_resolv_set_defaults()
3359 evdns_base_nameserver_ip_add(base, "127.0.0.1"); 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()
3426 evdns_base_set_max_requests_inflight(struct evdns_base *base, int maxinflight) in evdns_base_set_max_requests_inflight() argument
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()
3432 ASSERT_LOCKED(base); 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()
3458 evdns_base_set_option(struct evdns_base *base, in evdns_base_set_option() argument
3462 EVDNS_LOCK(base); in evdns_base_set_option()
3463 res = evdns_base_set_option_impl(base, option, val, DNS_OPTIONS_ALL); in evdns_base_set_option()
3464 EVDNS_UNLOCK(base); in evdns_base_set_option()
3476 if (slen == optlen || slen == optlen - 1) in str_matches_option()
3485 evdns_base_set_option_impl(struct evdns_base *base, in evdns_base_set_option_impl() argument
3488 ASSERT_LOCKED(base); in evdns_base_set_option_impl()
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()
3524 evdns_base_set_max_requests_inflight(base, maxinflight); 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()
3581 resolv_conf_parse_line(struct evdns_base *base, char *const start, int flags) { in resolv_conf_parse_line() argument
3588 ASSERT_LOCKED(base); in resolv_conf_parse_line()
3595 evdns_base_nameserver_ip_add(base, nameserver); in resolv_conf_parse_line()
3599 search_postfix_clear(base); in resolv_conf_parse_line()
3600 search_postfix_add(base, domain); in resolv_conf_parse_line()
3604 search_postfix_clear(base); in resolv_conf_parse_line()
3607 search_postfix_add(base, domain); in resolv_conf_parse_line()
3609 search_reverse(base); in resolv_conf_parse_line()
3614 evdns_base_set_option_impl(base, option, val ? val+1 : "", flags); in resolv_conf_parse_line()
3629 evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename) { in evdns_base_resolv_conf_parse() argument
3631 EVDNS_LOCK(base); in evdns_base_resolv_conf_parse()
3632 res = evdns_base_resolv_conf_parse_impl(base, flags, filename); in evdns_base_resolv_conf_parse()
3633 EVDNS_UNLOCK(base); in evdns_base_resolv_conf_parse()
3663 evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char *const filename) { in evdns_base_resolv_conf_parse_impl() argument
3678 evdns_base_load_hosts(base, fname); in evdns_base_resolv_conf_parse_impl()
3684 evdns_resolv_set_defaults(base, flags); in evdns_base_resolv_conf_parse_impl()
3689 if (err == -1) { in evdns_base_resolv_conf_parse_impl()
3691 evdns_resolv_set_defaults(base, flags); in evdns_base_resolv_conf_parse_impl()
3702 resolv_conf_parse_line(base, start, flags); in evdns_base_resolv_conf_parse_impl()
3706 resolv_conf_parse_line(base, start, flags); in evdns_base_resolv_conf_parse_impl()
3711 if (!base->server_head && add_default) { in evdns_base_resolv_conf_parse_impl()
3713 evdns_base_nameserver_ip_add(base, "127.0.0.1"); 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()
3717 search_set_from_hostname(base); in evdns_base_resolv_conf_parse_impl()
3733 /* Add multiple nameservers from a space-or-comma-separated list. */
3735 evdns_nameserver_ip_add_line(struct evdns_base *base, const char *ips) { in evdns_nameserver_ip_add_line() argument
3739 ASSERT_LOCKED(base); in evdns_nameserver_ip_add_line()
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()
3751 r = evdns_base_nameserver_ip_add(base, buf); in evdns_nameserver_ip_add_line()
3763 load_nameservers_with_getnetworkparams(struct evdns_base *base) in load_nameservers_with_getnetworkparams() argument
3765 /* Based on MSDN examples and inspection of c-ares code. */ in load_nameservers_with_getnetworkparams()
3774 ASSERT_LOCKED(base); in load_nameservers_with_getnetworkparams()
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()
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()
3842 config_nameserver_from_reg_key(struct evdns_base *base, HKEY key, const TCHAR *subkey) in config_nameserver_from_reg_key() argument
3848 ASSERT_LOCKED(base); in config_nameserver_from_reg_key()
3851 return -1; in config_nameserver_from_reg_key()
3853 return -1; in config_nameserver_from_reg_key()
3857 status = evdns_nameserver_ip_add_line(base,buf); in config_nameserver_from_reg_key()
3869 load_nameservers_from_registry(struct evdns_base *base) in load_nameservers_from_registry() argument
3874 if (!found && config_nameserver_from_reg_key(base,k,TEXT(name)) == 0) { \ in load_nameservers_from_registry()
3882 ASSERT_LOCKED(base); in load_nameservers_from_registry()
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()
3925 evdns_base_config_windows_nameservers(struct evdns_base *base) in evdns_base_config_windows_nameservers() argument
3929 if (base == NULL) in evdns_base_config_windows_nameservers()
3930 base = current_base; in evdns_base_config_windows_nameservers()
3931 if (base == NULL) in evdns_base_config_windows_nameservers()
3932 return -1; in evdns_base_config_windows_nameservers()
3933 EVDNS_LOCK(base); in evdns_base_config_windows_nameservers()
3936 evdns_base_load_hosts(base, fname); in evdns_base_config_windows_nameservers()
3940 if (load_nameservers_with_getnetworkparams(base) == 0) { in evdns_base_config_windows_nameservers()
3941 EVDNS_UNLOCK(base); in evdns_base_config_windows_nameservers()
3944 r = load_nameservers_from_registry(base); in evdns_base_config_windows_nameservers()
3946 EVDNS_UNLOCK(base); in evdns_base_config_windows_nameservers()
3955 return current_base == NULL ? -1 : 0; in evdns_config_windows_nameservers()
3965 struct evdns_base *base; in evdns_base_new() local
3973 /* Give the evutil library a hook into its evdns-enabled in evdns_base_new()
3975 * else libevent-core will depend on libevent-extras. */ in evdns_base_new()
3979 base = mm_malloc(sizeof(struct evdns_base)); in evdns_base_new()
3980 if (base == NULL) in evdns_base_new()
3982 memset(base, 0, sizeof(struct evdns_base)); 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()
3986 EVDNS_LOCK(base); in evdns_base_new()
3989 base->req_heads = NULL; in evdns_base_new()
3991 evdns_base_set_max_requests_inflight(base, 64); 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()
4034 r = evdns_base_config_windows_nameservers(base); in evdns_base_new()
4036 r = evdns_base_resolv_conf_parse(base, opts, "/etc/resolv.conf"); in evdns_base_new()
4039 evdns_base_free_and_unlock(base, 0); in evdns_base_new()
4044 base->disable_when_inactive = 1; in evdns_base_new()
4047 EVDNS_UNLOCK(base); in evdns_base_new()
4048 return base; in evdns_base_new()
4054 struct evdns_base *base = evdns_base_new(NULL, 1); in evdns_init() local
4055 if (base) { in evdns_init()
4056 current_base = base; in evdns_init()
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()
4102 evdns_base_free_and_unlock(struct evdns_base *base, int fail_requests) in evdns_base_free_and_unlock() argument
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()
4156 EVDNS_UNLOCK(base); in evdns_base_free_and_unlock()
4157 EVTHREAD_FREE_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); in evdns_base_free_and_unlock()
4159 mm_free(base); in evdns_base_free_and_unlock()
4163 evdns_base_free(struct evdns_base *base, int fail_requests) in evdns_base_free() argument
4165 EVDNS_LOCK(base); in evdns_base_free()
4166 evdns_base_free_and_unlock(base, fail_requests); in evdns_base_free()
4170 evdns_base_clear_host_addresses(struct evdns_base *base) in evdns_base_clear_host_addresses() argument
4173 EVDNS_LOCK(base); in evdns_base_clear_host_addresses()
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()
4178 EVDNS_UNLOCK(base); in evdns_base_clear_host_addresses()
4193 evdns_base_parse_hosts_line(struct evdns_base *base, char *line) in evdns_base_parse_hosts_line() argument
4201 ASSERT_LOCKED(base); in evdns_base_parse_hosts_line()
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()
4247 evdns_base_load_hosts_impl(struct evdns_base *base, const char *hosts_fname) in evdns_base_load_hosts_impl() argument
4253 ASSERT_LOCKED(base); in evdns_base_load_hosts_impl()
4259 evdns_base_parse_hosts_line(base, tmp); in evdns_base_load_hosts_impl()
4261 evdns_base_parse_hosts_line(base, tmp); in evdns_base_load_hosts_impl()
4262 return err ? -1 : 0; in evdns_base_load_hosts_impl()
4273 evdns_base_parse_hosts_line(base, cp); in evdns_base_load_hosts_impl()
4276 evdns_base_parse_hosts_line(base, cp); in evdns_base_load_hosts_impl()
4286 evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname) in evdns_base_load_hosts() argument
4289 if (!base) in evdns_base_load_hosts()
4290 base = current_base; in evdns_base_load_hosts()
4291 EVDNS_LOCK(base); in evdns_base_load_hosts()
4292 res = evdns_base_load_hosts_impl(base, hosts_fname); in evdns_base_load_hosts()
4293 EVDNS_UNLOCK(base); in evdns_base_load_hosts()
4303 /* State data used to implement an in-progress getaddrinfo. */
4311 /* User-supplied data to give to the callback. */
4313 /* The port to use when building sockaddrs. */
4314 ev_uint16_t port; member
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
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()
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()
4508 if (other_req->r == NULL) in evdns_getaddrinfo_gotresolve()
4513 if (data->user_cb == NULL) { 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()
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()
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()
4643 find_hosts_entry(struct evdns_base *base, const char *hostname, in find_hosts_entry() argument
4651 e = TAILQ_FIRST(&base->hostsdb); in find_hosts_entry()
4654 if (!evutil_ascii_strcasecmp(e->hostname, hostname)) in find_hosts_entry()
4661 evdns_getaddrinfo_fromhosts(struct evdns_base *base, in evdns_getaddrinfo_fromhosts() argument
4662 const char *nodename, struct evutil_addrinfo *hints, ev_uint16_t port, in evdns_getaddrinfo_fromhosts() argument
4668 int f = hints->ai_family; in evdns_getaddrinfo_fromhosts()
4670 EVDNS_LOCK(base); in evdns_getaddrinfo_fromhosts()
4671 for (e = find_hosts_entry(base, nodename, NULL); e; in evdns_getaddrinfo_fromhosts()
4672 e = find_hosts_entry(base, nodename, e)) { 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()
4686 EVDNS_UNLOCK(base); in evdns_getaddrinfo_fromhosts()
4696 return -1; in evdns_getaddrinfo_fromhosts()
4710 int port = 0; in evdns_getaddrinfo() local
4726 if ((hints_in && (hints_in->ai_flags & EVUTIL_AI_NUMERICHOST))) { in evdns_getaddrinfo()
4747 err = evutil_getaddrinfo_common_(nodename, servname, &hints, &res, &port); in evdns_getaddrinfo()
4754 if (!evdns_getaddrinfo_fromhosts(dns_base, nodename, &hints, port, &res)) { 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()
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()
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()