[SSSD] [PATCH] Handle timeout during sss_ldap_init_send

Jakub Hrozek jhrozek at redhat.com
Mon Aug 15 15:53:56 UTC 2011


In some cases, where there would be no response from the LDAP server,
there would be no R/W events on the LDAP fd, so
sdap_async_sys_connect_done would never be called.

This patch adds a tevent timer that cancels the connection after
SDAP_NETWORK_TIMEOUT seconds.

A simple testcase is enabling DROP iptables rules on the LDAP server.
-------------- next part --------------
>From 5a489f05544601a9b08b7b78fdf303dc0210b299 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 15 Aug 2011 17:46:04 +0200
Subject: [PATCH] Handle timeout during sss_ldap_init_send

In some cases, where there would be no response from the LDAP server,
there would be no R/W events on the LDAP fd, so
sdap_async_sys_connect_done would never be called.

This patch adds a tevent timer that cancels the connection after
SDAP_NETWORK_TIMEOUT seconds.
---
 src/providers/ldap/sdap_async_connection.c |    6 ++++-
 src/util/sss_ldap.c                        |   36 +++++++++++++++++++++++++++-
 src/util/sss_ldap.h                        |    2 +-
 3 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index db39be1..6f67700 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -89,6 +89,7 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
     struct tevent_req *subreq;
     struct sdap_connect_state *state;
     int ret;
+    int timeout;
 
     req = tevent_req_create(memctx, &state, struct sdap_connect_state);
     if (!req) return NULL;
@@ -112,8 +113,11 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
     state->sh->page_size = dp_opt_get_int(state->opts->basic,
                                           SDAP_PAGE_SIZE);
 
+    timeout = dp_opt_get_int(state->opts->basic, SDAP_NETWORK_TIMEOUT);
+
     subreq = sss_ldap_init_send(state, ev, uri, sockaddr,
-                                sizeof(struct sockaddr_storage));
+                                sizeof(struct sockaddr_storage),
+                                timeout);
     if (subreq == NULL) {
         ret = ENOMEM;
         DEBUG(1, ("sss_ldap_init_send failed.\n"));
diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c
index bff7c8d..de4bebf 100644
--- a/src/util/sss_ldap.c
+++ b/src/util/sss_ldap.c
@@ -285,12 +285,19 @@ static errno_t set_fd_flags_and_opts(int fd)
 extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld);
 
 static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq);
+static void sdap_async_sys_connect_timeout(struct tevent_context *ev,
+                                           struct tevent_timer *te,
+                                           struct timeval tv, void *pvt);
 #endif
 
 struct sss_ldap_init_state {
     LDAP *ldap;
     int sd;
     const char *uri;
+
+#ifdef HAVE_LDAP_INIT_FD
+    struct tevent_timer *connect_timeout;
+#endif
 };
 
 
@@ -298,7 +305,7 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
                                       struct tevent_context *ev,
                                       const char *uri,
                                       struct sockaddr_storage *addr,
-                                      int addr_len)
+                                      int addr_len, int timeout)
 {
     int ret = EOK;
     struct tevent_req *req;
@@ -315,6 +322,7 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
 
 #ifdef HAVE_LDAP_INIT_FD
     struct tevent_req *subreq;
+    struct timeval tv;
 
     state->sd = socket(addr->ss_family, SOCK_STREAM, 0);
     if (state->sd == -1) {
@@ -339,6 +347,18 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
         goto fail;
     }
 
+    DEBUG(6, ("Setting %d seconds timeout for connecting\n", timeout));
+    tv = tevent_timeval_current_ofs(timeout, 0);
+
+    state->connect_timeout = tevent_add_timer(ev, subreq, tv,
+                                              sdap_async_sys_connect_timeout,
+                                              subreq);
+    if (state->connect_timeout == NULL) {
+        DEBUG(1, ("tevent_add_timer failed.\n"));
+        ret = ENOMEM;
+        goto fail;
+    }
+
     tevent_req_set_callback(subreq, sss_ldap_init_sys_connect_done, req);
     return req;
 
@@ -369,6 +389,18 @@ fail:
 }
 
 #ifdef HAVE_LDAP_INIT_FD
+static void sdap_async_sys_connect_timeout(struct tevent_context *ev,
+                                           struct tevent_timer *te,
+                                           struct timeval tv, void *pvt)
+{
+    struct tevent_req *connection_request;
+
+    DEBUG(4, ("The LDAP connection timed out\n"));
+
+    connection_request = talloc_get_type(pvt, struct tevent_req);
+    tevent_req_error(connection_request, ETIMEDOUT);
+}
+
 static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq)
 {
     struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -378,6 +410,8 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq)
     int ret;
     int lret;
 
+    talloc_zfree(state->connect_timeout);
+
     ret = sdap_async_sys_connect_recv(subreq);
     talloc_zfree(subreq);
     if (ret != EOK) {
diff --git a/src/util/sss_ldap.h b/src/util/sss_ldap.h
index ab89029..4b4d9c1 100644
--- a/src/util/sss_ldap.h
+++ b/src/util/sss_ldap.h
@@ -53,7 +53,7 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
                                       struct tevent_context *ev,
                                       const char *uri,
                                       struct sockaddr_storage *addr,
-                                      int addr_len);
+                                      int addr_len, int timeout);
 
 int sss_ldap_init_recv(struct tevent_req *req, LDAP **ldap, int *sd);
 #endif /* __SSS_LDAP_H__ */
-- 
1.7.6



More information about the sssd-devel mailing list