static void
evdns_resolv_set_defaults(struct evdns_base *base, int flags) {
+ int add_default = flags & DNS_OPTION_NAMESERVERS;
+ if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT)
+ add_default = 0;
+
/* if the file isn't found then we assume a local resolver */
ASSERT_LOCKED(base);
- if (flags & DNS_OPTION_SEARCH) search_set_from_hostname(base);
- if (flags & DNS_OPTION_NAMESERVERS) evdns_base_nameserver_ip_add(base,"127.0.0.1");
+ if (flags & DNS_OPTION_SEARCH)
+ search_set_from_hostname(base);
+ if (add_default)
+ evdns_base_nameserver_ip_add(base, "127.0.0.1");
}
#ifndef EVENT__HAVE_STRTOK_R
char *resolv;
char *start;
int err = 0;
+ int add_default;
log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
+ add_default = flags & DNS_OPTION_NAMESERVERS;
+ if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT)
+ add_default = 0;
+
if (flags & DNS_OPTION_HOSTSFILE) {
char *fname = evdns_get_default_hosts_filename();
evdns_base_load_hosts(base, fname);
}
}
- if (!base->server_head && (flags & DNS_OPTION_NAMESERVERS)) {
+ if (!base->server_head && add_default) {
/* no nameservers were configured. */
evdns_base_nameserver_ip_add(base, "127.0.0.1");
err = 6;
TAILQ_INIT(&base->hostsdb);
-#define EVDNS_BASE_ALL_FLAGS (0x8001)
+#define EVDNS_BASE_ALL_FLAGS ( \
+ EVDNS_BASE_INITIALIZE_NAMESERVERS | \
+ EVDNS_BASE_DISABLE_WHEN_INACTIVE | \
+ EVDNS_BASE_NAMESERVERS_NO_DEFAULT | \
+ 0)
+
if (flags & ~EVDNS_BASE_ALL_FLAGS) {
flags = EVDNS_BASE_INITIALIZE_NAMESERVERS;
log(EVDNS_LOG_WARN,
if (flags & EVDNS_BASE_INITIALIZE_NAMESERVERS) {
int r;
+ int opts = DNS_OPTIONS_ALL;
+ if (flags & EVDNS_BASE_NAMESERVERS_NO_DEFAULT) {
+ opts |= DNS_OPTION_NAMESERVERS_NO_DEFAULT;
+ }
+
#ifdef _WIN32
r = evdns_base_config_windows_nameservers(base);
#else
- r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");
+ r = evdns_base_resolv_conf_parse(base, opts, "/etc/resolv.conf");
#endif
if (r == -1) {
evdns_base_free_and_unlock(base, 0);
DNS_OPTION_HOSTSFILE | \
0 \
)
+/* Do not "default" nameserver (i.e. "127.0.0.1:53") if there is no nameservers
+ * in resolv.conf, (iff DNS_OPTION_NAMESERVERS is set) */
+#define DNS_OPTION_NAMESERVERS_NO_DEFAULT 16
/* Obsolete name for DNS_QUERY_NO_SEARCH */
#define DNS_NO_SEARCH DNS_QUERY_NO_SEARCH
/** Flag for evdns_base_new: Do not prevent the libevent event loop from
* exiting when we have no active dns requests. */
#define EVDNS_BASE_DISABLE_WHEN_INACTIVE 0x8000
+/** Flag for evdns_base_new: If EVDNS_BASE_INITIALIZE_NAMESERVERS isset, do not
+ * add default nameserver if there are no nameservers in resolv.conf
+ * @see DNS_OPTION_NAMESERVERS_NO_DEFAULT */
+#define EVDNS_BASE_NAMESERVERS_NO_DEFAULT 0x10000
/**
Initialize the asynchronous DNS library.
@param event_base the event base to associate the dns client with
@param flags any of EVDNS_BASE_INITIALIZE_NAMESERVERS|
- EVDNS_BASE_DISABLE_WHEN_INACTIVE
+ EVDNS_BASE_DISABLE_WHEN_INACTIVE|EVDNS_BASE_NAMESERVERS_NO_DEFAULT
@return evdns_base object if successful, or NULL if an error occurred.
@see evdns_base_free()
*/
@param base the evdns_base to which to apply this operation
@param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
- DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL
+ DNS_OPTION_HOSTSFILE|DNS_OPTIONS_ALL|DNS_OPTION_NAMESERVERS_NO_DEFAULT
@param filename the path to the resolv.conf file
@return 0 if successful, or various positive error codes if an error
occurred (see above)
{
struct in_addr in;
struct event_base *base = event_base_new();
- struct evdns_base *dns = evdns_base_new(base, 1/* init name servers */);
+ struct evdns_base *dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS);
struct evdns_request *req = NULL;
tt_assert(base);
event_base_free(inactive_base);
}
+static void
+dns_initialize_nameservers_test(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct event_base *base = data->base;
+ struct evdns_base *dns = NULL;
+
+ dns = evdns_base_new(base, 0);
+ tt_assert(dns);
+ tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
+ evdns_base_free(dns, 0);
+
+ dns = evdns_base_new(base, EVDNS_BASE_INITIALIZE_NAMESERVERS);
+ tt_assert(dns);
+ tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr));
+
+end:
+ if (dns)
+ evdns_base_free(dns, 0);
+}
+#ifndef _WIN32
+#define RESOLV_FILE "empty-resolv.conf"
+static void
+dns_nameservers_no_default_test(void *arg)
+{
+ struct basic_test_data *data = arg;
+ struct event_base *base = data->base;
+ struct evdns_base *dns = NULL;
+ int ok = access(RESOLV_FILE, R_OK);
+
+ tt_assert(ok);
+
+ dns = evdns_base_new(base, 0);
+ tt_assert(dns);
+ tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
+
+ /* We cannot test
+ * EVDNS_BASE_INITIALIZE_NAMESERVERS|EVDNS_BASE_NAMESERVERS_NO_DEFAULT
+ * because we cannot mock "/etc/resolv.conf" (yet). */
+
+ evdns_base_resolv_conf_parse(dns,
+ DNS_OPTIONS_ALL|DNS_OPTION_NAMESERVERS_NO_DEFAULT, RESOLV_FILE);
+ tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, -1);
+
+ evdns_base_resolv_conf_parse(dns, DNS_OPTIONS_ALL, RESOLV_FILE);
+ tt_int_op(evdns_base_get_nameserver_addr(dns, 0, NULL, 0), ==, sizeof(struct sockaddr));
+
+end:
+ if (dns)
+ evdns_base_free(dns, 0);
+}
+#endif
+
/* === Test for bufferevent_socket_connect_hostname */
static int total_connected_or_failed = 0;
{ "disable_when_inactive_no_ns", dns_disable_when_inactive_no_ns_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+ { "initialize_nameservers", dns_initialize_nameservers_test,
+ TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+#ifndef _WIN32
+ { "nameservers_no_default", dns_nameservers_no_default_test,
+ TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
+#endif
+
{ "getaddrinfo_async", test_getaddrinfo_async,
TT_FORK|TT_NEED_BASE, &basic_setup, (char*)"" },
{ "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,