]> granicus.if.org Git - libevent/commitdiff
evdns: add DNS_OPTION_NAMESERVERS_NO_DEFAULT/EVDNS_BASE_NAMESERVERS_NO_DEFAULT
authorAzat Khuzhin <azat@libevent.org>
Sun, 31 Mar 2019 22:47:00 +0000 (01:47 +0300)
committerAzat Khuzhin <azat@libevent.org>
Sun, 31 Mar 2019 23:18:59 +0000 (02:18 +0300)
- DNS_OPTION_NAMESERVERS_NO_DEFAULT
  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)

- EVDNS_BASE_NAMESERVERS_NO_DEFAULT
  If EVDNS_BASE_INITIALIZE_NAMESERVERS isset, do not add default
  nameserver if there are no nameservers in resolv.conf (just set
  DNS_OPTION_NAMESERVERS_NO_DEFAULT internally)

Fixes: #569
evdns.c
include/event2/dns.h
test/regress_dns.c

diff --git a/evdns.c b/evdns.c
index b686355692cf003ff189107e3f55b52a6fe9debd..3cf6ef0955a87fbfa26de7434b35cd8e933f3201 100644 (file)
--- a/evdns.c
+++ b/evdns.c
@@ -3327,10 +3327,16 @@ search_request_finished(struct evdns_request *const handle) {
 
 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
@@ -3626,9 +3632,14 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
        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);
@@ -3664,7 +3675,7 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
                }
        }
 
-       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;
@@ -3965,7 +3976,12 @@ evdns_base_new(struct event_base *event_base, int flags)
 
        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,
@@ -3976,10 +3992,15 @@ evdns_base_new(struct event_base *event_base, int flags)
 
        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);
index 358b30fde93f13d29d576500e20050a48f90a2aa..3c548a1ec9fd5f75fb5d96441c0a2da254158a1e 100644 (file)
@@ -209,6 +209,9 @@ extern "C" {
     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
@@ -233,6 +236,10 @@ struct event_base;
 /** 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.
@@ -243,7 +250,7 @@ struct event_base;
 
   @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()
  */
@@ -478,7 +485,7 @@ int evdns_base_set_option(struct evdns_base *base, const char *option, const cha
 
   @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)
index 9f1d6283c293a17dba7e045f07804ea3560c41cd..25a5f5ac6974b392478b00b131df58f70bfaf989 100644 (file)
@@ -204,7 +204,7 @@ dns_resolve_reverse(void *ptr)
 {
        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);
@@ -1004,6 +1004,59 @@ end:
                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;
@@ -2332,6 +2385,13 @@ struct testcase_t dns_testcases[] = {
        { "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,