summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-04-15 18:26:18 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-04-26 09:55:00 -0400
commit5b680ac8ef46fc1714f2ab59a07f68ac386ad89b (patch)
tree5bbf5788a17b5e6e5091430793b4adaef59b0df3
parent74ff3d42d38feab9aaf1db86f228c41418b8b592 (diff)
downloadsssd-5b680ac8ef46fc1714f2ab59a07f68ac386ad89b.tar.gz
sssd-5b680ac8ef46fc1714f2ab59a07f68ac386ad89b.tar.bz2
sssd-5b680ac8ef46fc1714f2ab59a07f68ac386ad89b.zip
Make the handling of fd events opaque
Depending on the version of the OpenLDAP libraries we use two different schemes to find the file descriptor of the connection to the LDAP server. This patch removes the related ifdefs from the main code and introduces helper functions which can handle the specific cases.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/providers/ldap/sdap.h6
-rw-r--r--src/providers/ldap/sdap_async.c127
-rw-r--r--src/providers/ldap/sdap_async_connection.c54
-rw-r--r--src/providers/ldap/sdap_async_private.h16
-rw-r--r--src/providers/ldap/sdap_fd_events.c259
6 files changed, 280 insertions, 184 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e56d7b16..92244f4a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -722,6 +722,7 @@ libsss_ldap_la_SOURCES = \
providers/ldap/sdap_async_accounts.c \
providers/ldap/sdap_async_connection.c \
providers/ldap/sdap_child_helpers.c \
+ providers/ldap/sdap_fd_events.c \
providers/ldap/sdap.c \
util/user_info_msg.c \
util/sss_ldap.c \
@@ -793,6 +794,7 @@ libsss_ipa_la_SOURCES = \
providers/ldap/sdap_async_accounts.c \
providers/ldap/sdap_async_connection.c \
providers/ldap/sdap_child_helpers.c \
+ providers/ldap/sdap_fd_events.c \
providers/ldap/sdap.c \
util/user_info_msg.c \
util/sss_ldap.c \
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index f0e345ec..aca98457 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -71,11 +71,7 @@ struct sdap_handle {
LDAP *ldap;
bool connected;
-#ifdef HAVE_LDAP_CONNCB
- struct ldap_conncb *conncb;
-#else
- struct tevent_fd *fde;
-#endif
+ struct sdap_fd_events *sdap_fd_events;
struct sdap_op *ops;
};
diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c
index 15f3048b..a25c50bb 100644
--- a/src/providers/ldap/sdap_async.c
+++ b/src/providers/ldap/sdap_async.c
@@ -97,12 +97,7 @@ static void sdap_handle_release(struct sdap_handle *sh)
if (sh->connected) {
struct sdap_op *op;
-#ifdef HAVE_LDAP_CONNCB
- /* remove all related fd events from the event loop */
- talloc_zfree(sh->conncb->lc_arg);
-#else
- talloc_zfree(sh->fde);
-#endif
+ talloc_zfree(sh->sdap_fd_events);
while (sh->ops) {
op = sh->ops;
@@ -115,9 +110,6 @@ static void sdap_handle_release(struct sdap_handle *sh)
if (sh->ldap) {
ldap_unbind_ext(sh->ldap, NULL, NULL);
}
-#ifdef HAVE_LDAP_CONNCB
- talloc_zfree(sh->conncb);
-#endif
sh->connected = false;
sh->ldap = NULL;
sh->ops = NULL;
@@ -132,9 +124,8 @@ static void sdap_process_next_reply(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv, void *pvt);
-static void sdap_ldap_result(struct tevent_context *ev,
- struct tevent_fd *fde,
- uint16_t flags, void *pvt)
+void sdap_ldap_result(struct tevent_context *ev, struct tevent_fd *fde,
+ uint16_t flags, void *pvt)
{
sdap_process_result(ev, pvt);
}
@@ -336,118 +327,6 @@ static void sdap_process_next_reply(struct tevent_context *ev,
op->callback(op, op->list, EOK, op->data);
}
-#ifdef HAVE_LDAP_CONNCB
-int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
- struct sockaddr *addr, struct ldap_conncb *ctx)
-{
- int ret;
- ber_socket_t ber_fd;
- struct fd_event_item *fd_event_item;
- struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
- struct ldap_cb_data);
-
- ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
- if (ret == -1) {
- DEBUG(1, ("ber_sockbuf_ctrl failed.\n"));
- return EINVAL;
- }
- DEBUG(9, ("New LDAP connection to [%s] with fd [%d].\n",
- ldap_url_desc2str(srv), ber_fd));
-
- fd_event_item = talloc_zero(cb_data, struct fd_event_item);
- if (fd_event_item == NULL) {
- DEBUG(1, ("talloc failed.\n"));
- return ENOMEM;
- }
-
- fd_event_item->fde = tevent_add_fd(cb_data->ev, fd_event_item, ber_fd,
- TEVENT_FD_READ, sdap_ldap_result,
- cb_data->sh);
- if (fd_event_item->fde == NULL) {
- DEBUG(1, ("tevent_add_fd failed.\n"));
- talloc_free(fd_event_item);
- return ENOMEM;
- }
- fd_event_item->fd = ber_fd;
-
- DLIST_ADD(cb_data->fd_list, fd_event_item);
-
- return LDAP_SUCCESS;
-}
-
-void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb,
- struct ldap_conncb *ctx)
-{
- int ret;
- ber_socket_t ber_fd;
- struct fd_event_item *fd_event_item;
- struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
- struct ldap_cb_data);
-
- if (sb == NULL || cb_data == NULL) {
- return;
- }
-
- ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
- if (ret == -1) {
- DEBUG(1, ("ber_sockbuf_ctrl failed.\n"));
- return;
- }
- DEBUG(9, ("Closing LDAP connection with fd [%d].\n", ber_fd));
-
- DLIST_FOR_EACH(fd_event_item, cb_data->fd_list) {
- if (fd_event_item->fd == ber_fd) {
- break;
- }
- }
- if (fd_event_item == NULL) {
- DEBUG(1, ("No event for fd [%d] found.\n", ber_fd));
- return;
- }
-
- DLIST_REMOVE(cb_data->fd_list, fd_event_item);
- talloc_zfree(fd_event_item);
-
- return;
-}
-
-#else
-
-static int get_fd_from_ldap(LDAP *ldap, int *fd)
-{
- int ret;
-
- ret = ldap_get_option(ldap, LDAP_OPT_DESC, fd);
- if (ret != LDAP_OPT_SUCCESS) {
- DEBUG(1, ("Failed to get fd from ldap!!\n"));
- *fd = -1;
- return EIO;
- }
-
- return EOK;
-}
-
-int sdap_install_ldap_callbacks(struct sdap_handle *sh,
- struct tevent_context *ev)
-{
- int fd;
- int ret;
-
- ret = get_fd_from_ldap(sh->ldap, &fd);
- if (ret) return ret;
-
- sh->fde = tevent_add_fd(ev, sh, fd, TEVENT_FD_READ, sdap_ldap_result, sh);
- if (!sh->fde) return ENOMEM;
-
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->fde, sh->ldap));
-
- return EOK;
-}
-
-#endif
-
-
/* ==LDAP-Operations-Helpers============================================== */
static int sdap_op_destructor(void *mem)
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 083bc0cc..9871dc21 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -127,37 +127,11 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
goto fail;
}
-#ifdef HAVE_LDAP_CONNCB
- struct ldap_cb_data *cb_data;
-
- /* add connection callback */
- state->sh->conncb = talloc_zero(state->sh, struct ldap_conncb);
- if (state->sh->conncb == NULL) {
- DEBUG(1, ("talloc_zero failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
-
- cb_data = talloc_zero(state->sh->conncb, struct ldap_cb_data);
- if (cb_data == NULL) {
- DEBUG(1, ("talloc_zero failed.\n"));
- ret = ENOMEM;
- goto fail;
- }
- cb_data->sh = state->sh;
- cb_data->ev = state->ev;
-
- state->sh->conncb->lc_add = sdap_ldap_connect_callback_add;
- state->sh->conncb->lc_del = sdap_ldap_connect_callback_del;
- state->sh->conncb->lc_arg = cb_data;
-
- lret = ldap_set_option(state->sh->ldap, LDAP_OPT_CONNECT_CB,
- state->sh->conncb);
- if (lret != LDAP_OPT_SUCCESS) {
- DEBUG(1, ("Failed to set connection callback\n"));
+ ret = setup_ldap_connection_callbacks(state->sh, state->ev);
+ if (ret != EOK) {
+ DEBUG(1, ("setup_ldap_connection_callbacks failed.\n"));
goto fail;
}
-#endif
/* if we do not use start_tls the connection is not really connected yet
* just fake an async procedure and leave connection to the bind call */
@@ -174,11 +148,8 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
goto fail;
}
- state->sh->connected = true;
-#ifndef HAVE_LDAP_CONNCB
- ret = sdap_install_ldap_callbacks(state->sh, state->ev);
+ ret = sdap_set_connected(state->sh, state->ev);
if (ret) goto fail;
-#endif
/* FIXME: get timeouts from configuration, for now 5 secs. */
ret = sdap_op_add(state, ev, state->sh, msgid,
@@ -350,11 +321,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
DEBUG(8, ("ldap simple bind sent, msgid = %d\n", msgid));
if (!sh->connected) {
- sh->connected = true;
-#ifndef HAVE_LDAP_CONNCB
- ret = sdap_install_ldap_callbacks(sh, ev);
+ ret = sdap_set_connected(sh, ev);
if (ret) goto fail;
-#endif
}
/* FIXME: get timeouts from configuration, for now 5 secs. */
@@ -544,11 +512,8 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx,
}
if (!sh->connected) {
- sh->connected = true;
-#ifndef HAVE_LDAP_CONNCB
- ret = sdap_install_ldap_callbacks(sh, ev);
+ ret = sdap_set_connected(sh, ev);
if (ret) goto fail;
-#endif
}
tevent_req_post(req, ev);
@@ -980,6 +945,7 @@ static void sdap_cli_rootdse_step(struct tevent_req *req)
struct sdap_cli_connect_state *state = tevent_req_data(req,
struct sdap_cli_connect_state);
struct tevent_req *subreq;
+ int ret;
subreq = sdap_get_rootdse_send(state, state->ev, state->opts, state->sh);
if (!subreq) {
@@ -992,15 +958,11 @@ static void sdap_cli_rootdse_step(struct tevent_req *req)
/* this rootdse search is performed before we actually do a bind,
* so we need to set up the callbacks or we will never get notified
* of a reply */
- state->sh->connected = true;
-#ifndef HAVE_LDAP_CONNCB
- int ret;
- ret = sdap_install_ldap_callbacks(state->sh, state->ev);
+ ret = sdap_set_connected(state->sh, state->ev);
if (ret) {
tevent_req_error(req, ret);
}
-#endif
}
}
diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h
index 55f76ed7..75597c6d 100644
--- a/src/providers/ldap/sdap_async_private.h
+++ b/src/providers/ldap/sdap_async_private.h
@@ -28,15 +28,13 @@
void make_realm_upper_case(const char *upn);
struct sdap_handle *sdap_handle_create(TALLOC_CTX *memctx);
-#ifdef HAVE_LDAP_CONNCB
-int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
- struct sockaddr *addr, struct ldap_conncb *ctx);
-void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb,
- struct ldap_conncb *ctx);
-#else
-int sdap_install_ldap_callbacks(struct sdap_handle *sh,
- struct tevent_context *ev);
-#endif
+void sdap_ldap_result(struct tevent_context *ev, struct tevent_fd *fde,
+ uint16_t flags, void *pvt);
+
+int setup_ldap_connection_callbacks(struct sdap_handle *sh,
+ struct tevent_context *ev);
+
+errno_t sdap_set_connected(struct sdap_handle *sh, struct tevent_context *ev);
int sdap_op_add(TALLOC_CTX *memctx, struct tevent_context *ev,
struct sdap_handle *sh, int msgid,
diff --git a/src/providers/ldap/sdap_fd_events.c b/src/providers/ldap/sdap_fd_events.c
new file mode 100644
index 00000000..11527789
--- /dev/null
+++ b/src/providers/ldap/sdap_fd_events.c
@@ -0,0 +1,259 @@
+/*
+ SSSD
+
+ Helper routines for file descriptor events
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2010 Red Hat
+
+ 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 "util/util.h"
+#include "providers/ldap/sdap_async_private.h"
+
+struct sdap_fd_events {
+#ifdef HAVE_LDAP_CONNCB
+ struct ldap_conncb *conncb;
+#else
+ struct tevent_fd *fde;
+#endif
+};
+
+#ifdef HAVE_LDAP_CONNCB
+static int remove_connection_callback(TALLOC_CTX *mem_ctx)
+{
+ int lret;
+ struct ldap_conncb *conncb = talloc_get_type(mem_ctx, struct ldap_conncb);
+
+ struct ldap_cb_data *cb_data = talloc_get_type(conncb->lc_arg,
+ struct ldap_cb_data);
+
+ lret = ldap_get_option(cb_data->sh->ldap, LDAP_OPT_CONNECT_CB, conncb);
+ if (lret != LDAP_OPT_SUCCESS) {
+ DEBUG(1, ("Failed to remove connection callback.\n"));
+ } else {
+ DEBUG(9, ("Successfully removed connection callback.\n"));
+ }
+ return lret;
+}
+
+static int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb,
+ LDAPURLDesc *srv,
+ struct sockaddr *addr,
+ struct ldap_conncb *ctx)
+{
+ int ret;
+ ber_socket_t ber_fd;
+ struct fd_event_item *fd_event_item;
+ struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
+ struct ldap_cb_data);
+
+ if (cb_data == NULL) {
+ DEBUG(1, ("sdap_ldap_connect_callback_add called without "
+ "callback data.\n"));
+ return EINVAL;
+ }
+
+ ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
+ if (ret == -1) {
+ DEBUG(1, ("ber_sockbuf_ctrl failed.\n"));
+ return EINVAL;
+ }
+ DEBUG(9, ("New LDAP connection to [%s] with fd [%d].\n",
+ ldap_url_desc2str(srv), ber_fd));
+
+ fd_event_item = talloc_zero(cb_data, struct fd_event_item);
+ if (fd_event_item == NULL) {
+ DEBUG(1, ("talloc failed.\n"));
+ return ENOMEM;
+ }
+
+ fd_event_item->fde = tevent_add_fd(cb_data->ev, fd_event_item, ber_fd,
+ TEVENT_FD_READ, sdap_ldap_result,
+ cb_data->sh);
+ if (fd_event_item->fde == NULL) {
+ DEBUG(1, ("tevent_add_fd failed.\n"));
+ talloc_free(fd_event_item);
+ return ENOMEM;
+ }
+ fd_event_item->fd = ber_fd;
+
+ DLIST_ADD(cb_data->fd_list, fd_event_item);
+
+ return LDAP_SUCCESS;
+}
+
+static void sdap_ldap_connect_callback_del(LDAP *ld, Sockbuf *sb,
+ struct ldap_conncb *ctx)
+{
+ int ret;
+ ber_socket_t ber_fd;
+ struct fd_event_item *fd_event_item;
+ struct ldap_cb_data *cb_data = talloc_get_type(ctx->lc_arg,
+ struct ldap_cb_data);
+
+ if (sb == NULL || cb_data == NULL) {
+ return;
+ }
+
+ ret = ber_sockbuf_ctrl(sb, LBER_SB_OPT_GET_FD, &ber_fd);
+ if (ret == -1) {
+ DEBUG(1, ("ber_sockbuf_ctrl failed.\n"));
+ return;
+ }
+ DEBUG(9, ("Closing LDAP connection with fd [%d].\n", ber_fd));
+
+ DLIST_FOR_EACH(fd_event_item, cb_data->fd_list) {
+ if (fd_event_item->fd == ber_fd) {
+ break;
+ }
+ }
+ if (fd_event_item == NULL) {
+ DEBUG(1, ("No event for fd [%d] found.\n", ber_fd));
+ return;
+ }
+
+ DLIST_REMOVE(cb_data->fd_list, fd_event_item);
+ talloc_zfree(fd_event_item);
+
+ return;
+}
+
+#else
+
+static int get_fd_from_ldap(LDAP *ldap, int *fd)
+{
+ int ret;
+
+ ret = ldap_get_option(ldap, LDAP_OPT_DESC, fd);
+ if (ret != LDAP_OPT_SUCCESS) {
+ DEBUG(1, ("Failed to get fd from ldap!!\n"));
+ *fd = -1;
+ return EIO;
+ }
+
+ return EOK;
+}
+
+static int sdap_install_ldap_callbacks(struct sdap_handle *sh,
+ struct tevent_context *ev)
+{
+ int fd;
+ int ret;
+
+ if (sh->sdap_fd_events) {
+ DEBUG(1, ("sdap_install_ldap_callbacks is called with already "
+ "initialized sdap_fd_events.\n"));
+ return EINVAL;
+ }
+
+ sh->sdap_fd_events = talloc_zero(sh, struct sdap_fd_events);
+ if (!sh->sdap_fd_events) {
+ DEBUG(1, ("talloc_zero failed.\n"));
+ return ENOMEM;
+ }
+
+ ret = get_fd_from_ldap(sh->ldap, &fd);
+ if (ret) return ret;
+
+ sh->sdap_fd_events->fde = tevent_add_fd(ev, sh->sdap_fd_events, fd,
+ TEVENT_FD_READ, sdap_ldap_result,
+ sh);
+ if (!sh->sdap_fd_events->fde) {
+ talloc_zfree(sh->sdap_fd_events);
+ return ENOMEM;
+ }
+
+ DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
+ sh, (int)sh->connected, sh->ops, sh->sdap_fd_events->fde,
+ sh->ldap));
+
+ return EOK;
+}
+
+#endif
+
+
+errno_t setup_ldap_connection_callbacks(struct sdap_handle *sh,
+ struct tevent_context *ev)
+{
+#ifdef HAVE_LDAP_CONNCB
+ int ret;
+ struct ldap_cb_data *cb_data;
+
+ sh->sdap_fd_events = talloc_zero(sh, struct sdap_fd_events);
+ if (sh->sdap_fd_events == NULL) {
+ DEBUG(1, ("talloc_zero failed.\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ sh->sdap_fd_events->conncb = talloc_zero(sh->sdap_fd_events,
+ struct ldap_conncb);
+ if (sh->sdap_fd_events->conncb == NULL) {
+ DEBUG(1, ("talloc_zero failed.\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+
+ cb_data = talloc_zero(sh->sdap_fd_events->conncb, struct ldap_cb_data);
+ if (cb_data == NULL) {
+ DEBUG(1, ("talloc_zero failed.\n"));
+ ret = ENOMEM;
+ goto fail;
+ }
+ cb_data->sh = sh;
+ cb_data->ev = ev;
+
+ sh->sdap_fd_events->conncb->lc_add = sdap_ldap_connect_callback_add;
+ sh->sdap_fd_events->conncb->lc_del = sdap_ldap_connect_callback_del;
+ sh->sdap_fd_events->conncb->lc_arg = cb_data;
+
+ ret = ldap_set_option(sh->ldap, LDAP_OPT_CONNECT_CB,
+ sh->sdap_fd_events->conncb);
+ if (ret != LDAP_OPT_SUCCESS) {
+ DEBUG(1, ("Failed to set connection callback\n"));
+ ret = EFAULT;
+ goto fail;
+ }
+
+ talloc_set_destructor((TALLOC_CTX *) sh->sdap_fd_events->conncb,
+ remove_connection_callback);
+
+ return EOK;
+
+fail:
+ talloc_zfree(sh->sdap_fd_events);
+ return ret;
+#else
+ DEBUG(9, ("LDAP connection callbacks are not supported.\n"));
+ return EOK;
+#endif
+}
+
+errno_t sdap_set_connected(struct sdap_handle *sh, struct tevent_context *ev)
+{
+ int ret = EOK;
+
+ sh->connected = true;
+
+#ifndef HAVE_LDAP_CONNCB
+ ret = sdap_install_ldap_callbacks(sh, ev);
+#endif
+
+ return ret;
+}