summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-01-19 12:32:02 +0100
committerStephen Gallagher <sgallagh@redhat.com>2010-02-02 14:41:40 -0500
commit7c8f422495347e6ff829246ebf5d7faad9f6d160 (patch)
treebd22991dd01b9b5a347402b1808eddb89e96e3b8 /server
parentad35c1852e4fe3920acc63eb9ada409af0fb7d60 (diff)
downloadsssd-7c8f422495347e6ff829246ebf5d7faad9f6d160.tar.gz
sssd-7c8f422495347e6ff829246ebf5d7faad9f6d160.tar.xz
sssd-7c8f422495347e6ff829246ebf5d7faad9f6d160.zip
Use ldap connection callbacks to get file descriptors
Diffstat (limited to 'server')
-rw-r--r--server/providers/ldap/sdap.h16
-rw-r--r--server/providers/ldap/sdap_async.c101
-rw-r--r--server/providers/ldap/sdap_async_connection.c40
-rw-r--r--server/providers/ldap/sdap_async_private.h7
4 files changed, 121 insertions, 43 deletions
diff --git a/server/providers/ldap/sdap.h b/server/providers/ldap/sdap.h
index 2909f4172..a5b9e832c 100644
--- a/server/providers/ldap/sdap.h
+++ b/server/providers/ldap/sdap.h
@@ -53,11 +53,25 @@ struct sdap_op {
struct sdap_msg *last;
};
+struct fd_event_item {
+ struct fd_event_item *prev;
+ struct fd_event_item *next;
+
+ int fd;
+ struct tevent_fd *fde;
+};
+
+struct ldap_cb_data {
+ struct sdap_handle *sh;
+ struct tevent_context *ev;
+ struct fd_event_item *fd_list;
+};
+
struct sdap_handle {
LDAP *ldap;
bool connected;
- struct tevent_fd *fde;
+ struct ldap_conncb *conncb;
struct sdap_op *ops;
};
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index 706101bf0..fd8c11e05 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -91,13 +91,14 @@ static int sdap_handle_destructor(void *mem)
static void sdap_handle_release(struct sdap_handle *sh)
{
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->fde, sh->ldap));
+ DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], ldap[%p]\n",
+ sh, (int)sh->connected, sh->ops, sh->ldap));
if (sh->connected) {
struct sdap_op *op;
- talloc_zfree(sh->fde);
+ /* remove all related fd events from the event loop */
+ talloc_zfree(sh->conncb->lc_arg);
while (sh->ops) {
op = sh->ops;
@@ -110,26 +111,13 @@ static void sdap_handle_release(struct sdap_handle *sh)
if (sh->ldap) {
ldap_unbind_ext(sh->ldap, NULL, NULL);
}
+ talloc_zfree(sh->conncb);
sh->connected = false;
sh->ldap = NULL;
sh->ops = NULL;
}
}
-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;
-}
-
/* ==Parse-Results-And-Handle-Disconnections============================== */
static void sdap_process_message(struct tevent_context *ev,
struct sdap_handle *sh, LDAPMessage *msg);
@@ -160,8 +148,8 @@ static void sdap_process_result(struct tevent_context *ev, void *pvt)
LDAPMessage *msg;
int ret;
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->fde, sh->ldap));
+ DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], ldap[%p]\n",
+ sh, (int)sh->connected, sh->ops, sh->ldap));
if (!sh->connected || !sh->ldap) {
DEBUG(2, ("ERROR: LDAP connection is not connected!\n"));
@@ -342,24 +330,79 @@ static void sdap_process_next_reply(struct tevent_context *ev,
op->callback(op, op->list, EOK, op->data);
}
-int sdap_install_ldap_callbacks(struct sdap_handle *sh,
- struct tevent_context *ev)
+int sdap_ldap_connect_callback_add(LDAP *ld, Sockbuf *sb, LDAPURLDesc *srv,
+ struct sockaddr *addr, struct ldap_conncb *ctx)
{
- int fd;
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 = get_fd_from_ldap(sh->ldap, &fd);
- if (ret) return ret;
+ 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;
+ }
- sh->fde = tevent_add_fd(ev, sh, fd, TEVENT_FD_READ, sdap_ldap_result, sh);
- if (!sh->fde) 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;
- DEBUG(8, ("Trace: sh[%p], connected[%d], ops[%p], fde[%p], ldap[%p]\n",
- sh, (int)sh->connected, sh->ops, sh->fde, sh->ldap));
+ DLIST_ADD(cb_data->fd_list, fd_event_item);
- return EOK;
+ 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;
+}
/* ==LDAP-Operations-Helpers============================================== */
diff --git a/server/providers/ldap/sdap_async_connection.c b/server/providers/ldap/sdap_async_connection.c
index 7ccb301bd..99cb3754f 100644
--- a/server/providers/ldap/sdap_async_connection.c
+++ b/server/providers/ldap/sdap_async_connection.c
@@ -56,6 +56,7 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
int lret;
int ret = EOK;
int msgid;
+ struct ldap_cb_data *cb_data;
req = tevent_req_create(memctx, &state, struct sdap_connect_state);
if (!req) return NULL;
@@ -108,6 +109,34 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
goto fail;
}
+ /* 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"));
+ goto fail;
+ }
+
/* 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 */
if (!use_start_tls) {
@@ -124,8 +153,6 @@ struct tevent_req *sdap_connect_send(TALLOC_CTX *memctx,
}
state->sh->connected = true;
- ret = sdap_install_ldap_callbacks(state->sh, state->ev);
- if (ret) goto fail;
/* FIXME: get timeouts from configuration, for now 5 secs. */
ret = sdap_op_add(state, ev, state->sh, msgid,
@@ -297,8 +324,6 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
if (!sh->connected) {
sh->connected = true;
- ret = sdap_install_ldap_callbacks(sh, ev);
- if (ret) goto fail;
}
/* FIXME: get timeouts from configuration, for now 5 secs. */
@@ -464,8 +489,6 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx,
if (!sh->connected) {
sh->connected = true;
- ret = sdap_install_ldap_callbacks(sh, ev);
- if (ret) goto fail;
}
tevent_req_post(req, ev);
@@ -889,7 +912,6 @@ 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) {
@@ -903,10 +925,6 @@ static void sdap_cli_rootdse_step(struct tevent_req *req)
* so we need to set up the callbacks or we will never get notified
* of a reply */
state->sh->connected = true;
- ret = sdap_install_ldap_callbacks(state->sh, state->ev);
- if (ret) {
- tevent_req_error(req, ret);
- }
}
}
diff --git a/server/providers/ldap/sdap_async_private.h b/server/providers/ldap/sdap_async_private.h
index 9237f15d4..5549626a4 100644
--- a/server/providers/ldap/sdap_async_private.h
+++ b/server/providers/ldap/sdap_async_private.h
@@ -26,8 +26,11 @@
void make_realm_upper_case(const char *upn);
struct sdap_handle *sdap_handle_create(TALLOC_CTX *memctx);
-int sdap_install_ldap_callbacks(struct sdap_handle *sh,
- struct tevent_context *ev);
+
+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);
int sdap_op_add(TALLOC_CTX *memctx, struct tevent_context *ev,
struct sdap_handle *sh, int msgid,