From 4bf67c243a147a478cde3426083f385b033a5d9c Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Tue, 12 Jan 2010 10:35:08 -0500
Subject: [PATCH 1/2] Set asynchronous DNS timeout in sssd.conf

---
 server/confdb/confdb.h              |    1 +
 server/config/SSSDConfig.py         |    1 +
 server/config/SSSDConfigTest.py     |    2 ++
 server/config/etc/sssd.api.conf     |    1 +
 server/providers/data_provider_fo.c |   11 ++++++++++-
 server/resolv/async_resolv.c        |   13 +++++++++++--
 server/resolv/async_resolv.h        |    2 +-
 server/tests/fail_over-tests.c      |    2 +-
 server/tests/resolv-tests.c         |    2 +-
 9 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/server/confdb/confdb.h b/server/confdb/confdb.h
index 7f6c63b..cebdf29 100644
--- a/server/confdb/confdb.h
+++ b/server/confdb/confdb.h
@@ -87,6 +87,7 @@
 #define CONFDB_DOMAIN_MPG "magic_private_groups"
 #define CONFDB_DOMAIN_FQ "use_fully_qualified_names"
 #define CONFDB_DOMAIN_ENTRY_CACHE_TIMEOUT "entry_cache_timeout"
+#define CONFDB_DOMAIN_DNS_TIMEOUT "dns_timeout"
 
 /* Local Provider */
 #define CONFDB_LOCAL_DEFAULT_SHELL   "default_shell"
diff --git a/server/config/SSSDConfig.py b/server/config/SSSDConfig.py
index d31fbe2..7ab0d4f 100644
--- a/server/config/SSSDConfig.py
+++ b/server/config/SSSDConfig.py
@@ -77,6 +77,7 @@ option_strings = {
     'store_legacy_passwords' : _('Store password hashes'),
     'use_fully_qualified_names' : _('Display users/groups in fully-qualified form'),
     'entry_cache_timeout' : _('Entry cache timeout length (seconds)'),
+    'dns_timeout' : _("Length of time to wait for DNS requests"),
 
     # [provider/ipa]
     'ipa_domain' : _('IPA domain'),
diff --git a/server/config/SSSDConfigTest.py b/server/config/SSSDConfigTest.py
index 060bc67..a55b36c 100755
--- a/server/config/SSSDConfigTest.py
+++ b/server/config/SSSDConfigTest.py
@@ -382,6 +382,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'store_legacy_passwords',
             'use_fully_qualified_names',
             'entry_cache_timeout',
+            'dns_timeout',
             'id_provider',
             'auth_provider',
             'access_provider',
@@ -597,6 +598,7 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'store_legacy_passwords',
             'use_fully_qualified_names',
             'entry_cache_timeout',
+            'dns_timeout',
             'id_provider',
             'auth_provider',
             'access_provider',
diff --git a/server/config/etc/sssd.api.conf b/server/config/etc/sssd.api.conf
index bdb6aab..25b82e0 100644
--- a/server/config/etc/sssd.api.conf
+++ b/server/config/etc/sssd.api.conf
@@ -52,6 +52,7 @@ cache_credentials = bool, None, false
 store_legacy_passwords = bool, None, false
 use_fully_qualified_names = bool, None, false
 entry_cache_timeout = int, None
+dns_timeout = int, None
 
 # Special providers
 [provider/permit]
diff --git a/server/providers/data_provider_fo.c b/server/providers/data_provider_fo.c
index 23c857a..7fefdc6 100644
--- a/server/providers/data_provider_fo.c
+++ b/server/providers/data_provider_fo.c
@@ -56,6 +56,7 @@ struct be_failover_ctx {
 int be_init_failover(struct be_ctx *ctx)
 {
     int ret;
+    int ns_timeout; /* Timeout for async resolver */
 
     if (ctx->be_fo != NULL) {
         return EOK;
@@ -66,7 +67,15 @@ int be_init_failover(struct be_ctx *ctx)
         return ENOMEM;
     }
 
-    ret = resolv_init(ctx, ctx->ev, &ctx->be_fo->resolv);
+    /* Set the timeout for asynchronous DNS requests */
+    ret = confdb_get_int(ctx->cdb, ctx->be_fo, ctx->conf_path,
+                         CONFDB_DOMAIN_DNS_TIMEOUT, 10, &ns_timeout);
+    if (ret != EOK) {
+        talloc_zfree(ctx->be_fo);
+        return ret;
+    }
+
+    ret = resolv_init(ctx, ctx->ev, ns_timeout, &ctx->be_fo->resolv);
     if (ret != EOK) {
         talloc_zfree(ctx->be_fo);
         return ret;
diff --git a/server/resolv/async_resolv.c b/server/resolv/async_resolv.c
index c350d6c..8455b57 100644
--- a/server/resolv/async_resolv.c
+++ b/server/resolv/async_resolv.c
@@ -72,6 +72,9 @@ struct resolv_ctx {
     ares_channel channel;
     /* List of file descriptors that are watched by tevent. */
     struct fd_watch *fds;
+
+    /* Time in milliseconds before canceling a DNS request */
+    int timeout;
 };
 
 struct resolv_ctx *context_list;
@@ -242,7 +245,12 @@ recreate_ares_channel(struct resolv_ctx *ctx)
      */
     options.sock_state_cb = fd_event;
     options.sock_state_cb_data = ctx;
-    ret = ares_init_options(&new_channel, &options, ARES_OPT_SOCK_STATE_CB);
+    options.timeout = ctx->timeout * 1000;
+    options.tries = 1;
+    ret = ares_init_options(&new_channel, &options,
+                            ARES_OPT_SOCK_STATE_CB |
+                            ARES_OPT_TIMEOUTMS |
+                            ARES_OPT_TRIES);
     if (ret != ARES_SUCCESS) {
         DEBUG(1, ("Failed to initialize ares channel: %s\n",
                   resolv_strerror(ret)));
@@ -261,7 +269,7 @@ recreate_ares_channel(struct resolv_ctx *ctx)
 
 int
 resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
-            struct resolv_ctx **ctxp)
+            int timeout, struct resolv_ctx **ctxp)
 {
     int ret;
     struct resolv_ctx *ctx;
@@ -271,6 +279,7 @@ resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
         return ENOMEM;
 
     ctx->ev_ctx = ev_ctx;
+    ctx->timeout = timeout;
 
     ret = recreate_ares_channel(ctx);
     if (ret != EOK) {
diff --git a/server/resolv/async_resolv.h b/server/resolv/async_resolv.h
index e051538..5558e15 100644
--- a/server/resolv/async_resolv.h
+++ b/server/resolv/async_resolv.h
@@ -47,7 +47,7 @@
 struct resolv_ctx;
 
 int resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
-                struct resolv_ctx **ctxp);
+                int timeout, struct resolv_ctx **ctxp);
 
 void resolv_reread_configuration(void);
 
diff --git a/server/tests/fail_over-tests.c b/server/tests/fail_over-tests.c
index 16cc60e..21610ec 100644
--- a/server/tests/fail_over-tests.c
+++ b/server/tests/fail_over-tests.c
@@ -71,7 +71,7 @@ setup_test(void)
         fail("Could not init tevent context");
     }
 
-    ret = resolv_init(ctx, ctx->ev, &ctx->resolv);
+    ret = resolv_init(ctx, ctx->ev, 10, &ctx->resolv);
     if (ret != EOK) {
         talloc_free(ctx);
         fail("Could not init resolv context");
diff --git a/server/tests/resolv-tests.c b/server/tests/resolv-tests.c
index d6b8c4f..3cd8dbe 100644
--- a/server/tests/resolv-tests.c
+++ b/server/tests/resolv-tests.c
@@ -73,7 +73,7 @@ static int setup_resolv_test(struct resolv_test_ctx **ctx)
         return EFAULT;
     }
 
-    ret = resolv_init(test_ctx, test_ctx->ev, &test_ctx->resolv);
+    ret = resolv_init(test_ctx, test_ctx->ev, 10, &test_ctx->resolv);
     if (ret != EOK) {
         fail("Could not init resolv context");
         talloc_free(test_ctx);
-- 
1.6.5.2

