summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-03-02 14:33:38 -0500
committerJakub Hrozek <jhrozek@redhat.com>2016-03-09 18:34:39 +0100
commit5dbf360f2d6b0281c32f1bba6ebf5cc834c1716e (patch)
tree76b6fa8bcd9d2f6ffaa055a0367432e6a7daa6eb
parent991c9f47fcb24704b880f60ab8ee77cfda056e2c (diff)
downloadsssd-5dbf360f2d6b0281c32f1bba6ebf5cc834c1716e.tar.gz
sssd-5dbf360f2d6b0281c32f1bba6ebf5cc834c1716e.tar.xz
sssd-5dbf360f2d6b0281c32f1bba6ebf5cc834c1716e.zip
Util: Move socket setup in a common utility file
Other components may need to connect sockets, the code here is generic enough that with minimal modifications can be used for non-ldap connections too. So create a sss_sockets.c/h utility file with all the non-ldap specific socket setup functions and make them available for other uses. Resolves: https://fedorahosted.org/sssd/ticket/2968 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
-rw-r--r--Makefile.am5
-rw-r--r--src/util/sss_ldap.c256
-rw-r--r--src/util/sss_sockets.c356
-rw-r--r--src/util/sss_sockets.h39
4 files changed, 412 insertions, 244 deletions
diff --git a/Makefile.am b/Makefile.am
index 4e4f38a5e..d6eb0fc73 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -541,6 +541,7 @@ dist_noinst_HEADERS = \
src/util/sss_python.h \
src/util/sss_krb5.h \
src/util/sss_selinux.h \
+ src/util/sss_sockets.h \
src/util/sss_utf8.h \
src/util/sss_ssh.h \
src/util/sss_ini.h \
@@ -1663,6 +1664,7 @@ ipa_ldap_opt_tests_SOURCES = \
src/providers/ad/ad_opts.c \
src/providers/ipa/ipa_opts.c \
src/providers/krb5/krb5_opts.c \
+ src/util/sss_sockets.c \
src/util/sss_ldap.c \
src/tests/ipa_ldap_opt-tests.c
ipa_ldap_opt_tests_CFLAGS = \
@@ -1877,6 +1879,7 @@ TEST_MOCK_RESP_OBJ = \
src/responder/common/responder_cache_req.c
TEST_MOCK_PROVIDER_OBJ = \
+ src/util/sss_sockets.c \
src/util/sss_ldap.c \
src/providers/data_provider_opts.c \
src/providers/ldap/ldap_opts.c \
@@ -2264,6 +2267,7 @@ sdap_tests_SOURCES = \
src/providers/ldap/sdap_range.c \
src/providers/ldap/ldap_opts.c \
src/providers/ipa/ipa_opts.c \
+ src/util/sss_sockets.c \
src/util/sss_ldap.c \
src/tests/cmocka/test_sdap.c \
$(NULL)
@@ -2879,6 +2883,7 @@ libsss_ldap_common_la_SOURCES = \
src/providers/ldap/sdap.c \
src/providers/ipa/ipa_dn.c \
src/util/user_info_msg.c \
+ src/util/sss_sockets.c \
src/util/sss_ldap.c \
$(NULL)
libsss_ldap_common_la_CFLAGS = \
diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c
index c440d5445..7fdaadb5c 100644
--- a/src/util/sss_ldap.c
+++ b/src/util/sss_ldap.c
@@ -17,18 +17,13 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
#include "config.h"
+#include "util/util.h"
+#include "util/sss_sockets.h"
+#include "util/sss_ldap.h"
#include "providers/ldap/sdap.h"
-#include "util/sss_ldap.h"
-#include "util/util.h"
const char* sss_ldap_err2string(int err)
{
@@ -103,183 +98,6 @@ int sss_ldap_control_create(const char *oid, int iscritical,
}
#ifdef HAVE_LDAP_INIT_FD
-struct sdap_async_sys_connect_state {
- long old_flags;
- struct tevent_fd *fde;
- int fd;
- socklen_t addr_len;
- struct sockaddr_storage addr;
-};
-
-static void sdap_async_sys_connect_done(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv);
-
-static struct tevent_req *sdap_async_sys_connect_send(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- int fd,
- const struct sockaddr *addr,
- socklen_t addr_len)
-{
- struct tevent_req *req;
- struct sdap_async_sys_connect_state *state;
- long flags;
- int ret;
- int fret;
-
- flags = fcntl(fd, F_GETFL, 0);
- if (flags == -1) {
- DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_GETFL failed.\n");
- return NULL;
- }
-
- req = tevent_req_create(mem_ctx, &state,
- struct sdap_async_sys_connect_state);
- if (req == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
- return NULL;
- }
-
- state->old_flags = flags;
- state->fd = fd;
- state->addr_len = addr_len;
- memcpy(&state->addr, addr, addr_len);
-
- ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
- goto done;
- }
-
- ret = connect(fd, addr, addr_len);
- if (ret == EOK) {
- goto done;
- }
-
- ret = errno;
- switch(ret) {
- case EINPROGRESS:
- case EINTR:
- state->fde = tevent_add_fd(ev, state, fd,
- TEVENT_FD_READ | TEVENT_FD_WRITE,
- sdap_async_sys_connect_done, req);
- if (state->fde == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
- ret = ENOMEM;
- goto done;
- }
-
- return req;
-
- break;
- default:
- DEBUG(SSSDBG_CRIT_FAILURE,
- "connect failed [%d][%s].\n", ret, strerror(ret));
- }
-
-done:
- fret = fcntl(fd, F_SETFL, flags);
- if (fret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
- }
-
- if (ret == EOK) {
- tevent_req_done(req);
- } else {
- tevent_req_error(req, ret);
- }
-
- tevent_req_post(req, ev);
- return req;
-}
-
-static void sdap_async_sys_connect_done(struct tevent_context *ev,
- struct tevent_fd *fde, uint16_t flags,
- void *priv)
-{
- struct tevent_req *req = talloc_get_type(priv, struct tevent_req);
- struct sdap_async_sys_connect_state *state = tevent_req_data(req,
- struct sdap_async_sys_connect_state);
- int ret;
- int fret;
-
- errno = 0;
- ret = connect(state->fd, (struct sockaddr *) &state->addr,
- state->addr_len);
- if (ret != EOK) {
- ret = errno;
- if (ret == EINPROGRESS || ret == EINTR) {
- return; /* Try again later */
- }
- DEBUG(SSSDBG_CRIT_FAILURE,
- "connect failed [%d][%s].\n", ret, strerror(ret));
- }
-
- talloc_zfree(fde);
-
- fret = fcntl(state->fd, F_SETFL, state->old_flags);
- if (fret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
- }
-
- if (ret == EOK) {
- tevent_req_done(req);
- } else {
- tevent_req_error(req, ret);
- }
-
- return;
-}
-
-static int sdap_async_sys_connect_recv(struct tevent_req *req)
-{
- TEVENT_REQ_RETURN_ON_ERROR(req);
-
- return EOK;
-}
-
-static errno_t set_fd_flags_and_opts(int fd)
-{
- int ret;
- long flags;
- int dummy = 1;
-
- flags = fcntl(fd, F_GETFD, 0);
- if (flags == -1) {
- ret = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- "fcntl F_GETFD failed [%d][%s].\n", ret, strerror(ret));
- return ret;
- }
-
- flags = fcntl(fd, F_SETFD, flags| FD_CLOEXEC);
- if (flags == -1) {
- ret = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- "fcntl F_SETFD failed [%d][%s].\n", ret, strerror(ret));
- return ret;
- }
-
- /* SO_KEEPALIVE and TCP_NODELAY are set by OpenLDAP client libraries but
- * failures are ignored.*/
- ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &dummy, sizeof(dummy));
- if (ret != 0) {
- ret = errno;
- DEBUG(SSSDBG_FUNC_DATA,
- "setsockopt SO_KEEPALIVE failed.[%d][%s].\n", ret,
- strerror(ret));
- }
-
- ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy));
- if (ret != 0) {
- ret = errno;
- DEBUG(SSSDBG_FUNC_DATA,
- "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret,
- strerror(ret));
- }
-
- return EOK;
-}
#define LDAP_PROTO_TCP 1 /* ldap:// */
#define LDAP_PROTO_UDP 2 /* reserved */
@@ -289,19 +107,12 @@ 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
};
static int sss_ldap_init_state_destructor(void *data)
@@ -313,14 +124,17 @@ static int sss_ldap_init_state_destructor(void *data)
"calling ldap_unbind_ext for ldap:[%p] sd:[%d]\n",
state->ldap, state->sd);
ldap_unbind_ext(state->ldap, NULL, NULL);
- } else if (state->sd != -1) {
+ }
+ if (state->sd != -1) {
DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd);
close(state->sd);
+ state->sd = -1;
}
return 0;
}
+
struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
const char *uri,
@@ -340,47 +154,16 @@ struct tevent_req *sss_ldap_init_send(TALLOC_CTX *mem_ctx,
talloc_set_destructor((TALLOC_CTX *)state, sss_ldap_init_state_destructor);
state->ldap = NULL;
+ state->sd = -1;
state->uri = uri;
#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) {
- ret = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- "socket failed [%d][%s].\n", ret, strerror(ret));
- goto fail;
- }
-
- ret = set_fd_flags_and_opts(state->sd);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_flags_and_opts failed.\n");
- goto fail;
- }
-
- DEBUG(SSSDBG_TRACE_ALL,
- "Using file descriptor [%d] for LDAP connection.\n", state->sd);
- subreq = sdap_async_sys_connect_send(state, ev, state->sd,
- (struct sockaddr *) addr, addr_len);
+ subreq = sssd_async_socket_init_send(state, ev, addr, addr_len, timeout);
if (subreq == NULL) {
ret = ENOMEM;
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_async_sys_connect_send failed.\n");
- goto fail;
- }
-
- DEBUG(SSSDBG_TRACE_FUNC,
- "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(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
- ret = ENOMEM;
+ DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_socket_init_send failed.\n");
goto fail;
}
@@ -392,7 +175,6 @@ fail:
#else
DEBUG(SSSDBG_MINOR_FAILURE, "ldap_init_fd not available, "
"will use ldap_initialize with uri [%s].\n", uri);
- state->sd = -1;
ret = ldap_initialize(&state->ldap, uri);
if (ret == LDAP_SUCCESS) {
tevent_req_done(req);
@@ -412,18 +194,6 @@ 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(SSSDBG_CONF_SETTINGS, "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,
@@ -433,13 +203,11 @@ 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);
+ ret = sssd_async_socket_init_recv(subreq, &state->sd);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_async_sys_connect request failed: [%d]: %s.\n",
+ "sssd_async_socket_init request failed: [%d]: %s.\n",
ret, sss_strerror(ret));
goto fail;
}
diff --git a/src/util/sss_sockets.c b/src/util/sss_sockets.c
new file mode 100644
index 000000000..d0283af2d
--- /dev/null
+++ b/src/util/sss_sockets.c
@@ -0,0 +1,356 @@
+/*
+ SSSD
+
+ Socket utils
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include "util/util.h"
+
+
+static errno_t set_fd_flags_and_opts(int fd)
+{
+ int ret;
+ long flags;
+ int dummy = 1;
+
+ flags = fcntl(fd, F_GETFD, 0);
+ if (flags == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "fcntl F_GETFD failed [%d][%s].\n", ret, strerror(ret));
+ return ret;
+ }
+
+ flags = fcntl(fd, F_SETFD, flags| FD_CLOEXEC);
+ if (flags == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "fcntl F_SETFD failed [%d][%s].\n", ret, strerror(ret));
+ return ret;
+ }
+
+ /* SO_KEEPALIVE and TCP_NODELAY are set by OpenLDAP client libraries but
+ * failures are ignored.*/
+ ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &dummy, sizeof(dummy));
+ if (ret != 0) {
+ ret = errno;
+ DEBUG(SSSDBG_FUNC_DATA,
+ "setsockopt SO_KEEPALIVE failed.[%d][%s].\n", ret,
+ strerror(ret));
+ }
+
+ ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy));
+ if (ret != 0) {
+ ret = errno;
+ DEBUG(SSSDBG_FUNC_DATA,
+ "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret,
+ strerror(ret));
+ }
+
+ return EOK;
+}
+
+
+struct sssd_async_connect_state {
+ long old_flags;
+ struct tevent_fd *fde;
+ int fd;
+ socklen_t addr_len;
+ struct sockaddr_storage addr;
+};
+
+static void sssd_async_connect_done(struct tevent_context *ev,
+ struct tevent_fd *fde, uint16_t flags,
+ void *priv);
+
+struct tevent_req *sssd_async_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd,
+ const struct sockaddr *addr,
+ socklen_t addr_len)
+{
+ struct tevent_req *req;
+ struct sssd_async_connect_state *state;
+ long flags;
+ int ret;
+ int fret;
+
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags == -1) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_GETFL failed.\n");
+ return NULL;
+ }
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sssd_async_connect_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
+ return NULL;
+ }
+
+ state->old_flags = flags;
+ state->fd = fd;
+ state->addr_len = addr_len;
+ memcpy(&state->addr, addr, addr_len);
+
+ ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
+ goto done;
+ }
+
+ ret = connect(fd, addr, addr_len);
+ if (ret == EOK) {
+ goto done;
+ }
+
+ ret = errno;
+ switch (ret) {
+ case EINPROGRESS:
+ case EINTR:
+ state->fde = tevent_add_fd(ev, state, fd,
+ TEVENT_FD_READ | TEVENT_FD_WRITE,
+ sssd_async_connect_done, req);
+ if (state->fde == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ return req;
+
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "connect failed [%d][%s].\n", ret, strerror(ret));
+ }
+
+done:
+ fret = fcntl(fd, F_SETFL, flags);
+ if (fret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
+ }
+
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sssd_async_connect_done(struct tevent_context *ev,
+ struct tevent_fd *fde, uint16_t flags,
+ void *priv)
+{
+ struct tevent_req *req = talloc_get_type(priv, struct tevent_req);
+ struct sssd_async_connect_state *state =
+ tevent_req_data(req, struct sssd_async_connect_state);
+ int ret;
+ int fret;
+
+ errno = 0;
+ ret = connect(state->fd, (struct sockaddr *) &state->addr,
+ state->addr_len);
+ if (ret != EOK) {
+ ret = errno;
+ if (ret == EINPROGRESS || ret == EINTR) {
+ return; /* Try again later */
+ }
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "connect failed [%d][%s].\n", ret, strerror(ret));
+ }
+
+ talloc_zfree(fde);
+
+ fret = fcntl(state->fd, F_SETFL, state->old_flags);
+ if (fret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
+ }
+
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+
+ return;
+}
+
+int sssd_async_connect_recv(struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
+
+static void sssd_async_connect_timeout(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv, void *pvt)
+{
+ struct tevent_req *connection_request;
+
+ DEBUG(SSSDBG_CONF_SETTINGS, "The connection timed out\n");
+
+ connection_request = talloc_get_type(pvt, struct tevent_req);
+ tevent_req_error(connection_request, ETIMEDOUT);
+}
+
+
+struct sssd_async_socket_state {
+ struct tevent_timer *connect_timeout;
+ int sd;
+};
+
+static int sssd_async_socket_state_destructor(void *data);
+static void sssd_async_socket_init_done(struct tevent_req *subreq);
+
+struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sockaddr_storage *addr,
+ socklen_t addr_len, int timeout)
+{
+ struct sssd_async_socket_state *state;
+ struct tevent_req *req, *subreq;
+ struct timeval tv;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct sssd_async_socket_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
+ return NULL;
+ }
+ state->sd = -1;
+
+ talloc_set_destructor((TALLOC_CTX *)state,
+ sssd_async_socket_state_destructor);
+
+ state->sd = socket(addr->ss_family, SOCK_STREAM, 0);
+ if (state->sd == -1) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "socket failed [%d][%s].\n", ret, strerror(ret));
+ goto fail;
+ }
+
+ ret = set_fd_flags_and_opts(state->sd);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_flags_and_opts failed.\n");
+ goto fail;
+ }
+
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Using file descriptor [%d] for LDAP connection.\n", state->sd);
+
+ subreq = sssd_async_connect_send(state, ev, state->sd,
+ (struct sockaddr *) addr, addr_len);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_connect_send failed.\n");
+ goto fail;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Setting %d seconds timeout for connecting\n", timeout);
+ tv = tevent_timeval_current_ofs(timeout, 0);
+
+ state->connect_timeout = tevent_add_timer(ev, subreq, tv,
+ sssd_async_connect_timeout,
+ subreq);
+ if (state->connect_timeout == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ tevent_req_set_callback(subreq, sssd_async_socket_init_done, req);
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sssd_async_socket_init_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct sssd_async_socket_state *state =
+ tevent_req_data(req, struct sssd_async_socket_state);
+ int ret;
+
+ /* kill the timeout handler now that we got a reply */
+ talloc_zfree(state->connect_timeout);
+
+ ret = sssd_async_connect_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "sdap_async_sys_connect request failed: [%d]: %s.\n",
+ ret, sss_strerror(ret));
+ goto fail;
+ }
+
+ tevent_req_done(req);
+ return;
+
+fail:
+ tevent_req_error(req, ret);
+}
+
+int sssd_async_socket_init_recv(struct tevent_req *req, int *sd)
+{
+ struct sssd_async_socket_state *state =
+ tevent_req_data(req, struct sssd_async_socket_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ /* steal the sd and neutralize destructor actions */
+ *sd = state->sd;
+ state->sd = -1;
+
+ return EOK;
+}
+
+static int sssd_async_socket_state_destructor(void *data)
+{
+ struct sssd_async_socket_state *state =
+ talloc_get_type(data, struct sssd_async_socket_state);
+
+ if (state->sd != -1) {
+ DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd);
+ close(state->sd);
+ state->sd = -1;
+ }
+
+ return 0;
+}
diff --git a/src/util/sss_sockets.h b/src/util/sss_sockets.h
new file mode 100644
index 000000000..ccb05cb84
--- /dev/null
+++ b/src/util/sss_sockets.h
@@ -0,0 +1,39 @@
+/*
+ SSSD
+
+ Socket utils
+
+ Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __SSS_SOCKETS_H__
+#define __SSS_SOCKETS_H__
+
+struct tevent_req *sssd_async_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd,
+ const struct sockaddr *addr,
+ socklen_t addr_len);
+int sssd_async_connect_recv(struct tevent_req *req);
+
+
+struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sockaddr_storage *addr,
+ socklen_t addr_len, int timeout);
+int sssd_async_socket_init_recv(struct tevent_req *req, int *sd);
+
+#endif /* __SSS_SOCKETS_H__ */