sdap_id_op.c revision 10922e0293f3ebf056708acacce35e93fe07747e
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/*
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom SSSD
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom LDAP ID backend operation retry logic and connection cache
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom Authors:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom Eugene Indenbom <eindenbom@gmail.com>
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom Copyright (C) 2008-2010 Red Hat
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom This program is free software; you can redistribute it and/or modify
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom it under the terms of the GNU General Public License as published by
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom the Free Software Foundation; either version 3 of the License, or
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom (at your option) any later version.
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom This program is distributed in the hope that it will be useful,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom but WITHOUT ANY WARRANTY; without even the implied warranty of
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom GNU General Public License for more details.
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom You should have received a copy of the GNU General Public License
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom along with this program. If not, see <http://www.gnu.org/licenses/>.
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom*/
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce#include "providers/ldap/ldap_common.h"
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom#include "providers/ldap/sdap_async.h"
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce#include "providers/ldap/sdap_id_op.h"
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* LDAP async connection cache */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstruct sdap_id_conn_cache {
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce struct sdap_id_ctx *id_ctx;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* list of all open connections */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *connections;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* cached (current) connection */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *cached_connection;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom};
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* LDAP async operation tracker:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * - keeps track of connection usage
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * - keeps track of operation retries */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstruct sdap_id_op {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* ID backend context */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* double linked list pointers */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *prev, *next;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* current connection */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *conn_data;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* number of reconnects for this operation */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int reconnect_retry_count;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* connection request
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * It is required as we need to know which requests to notify
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * when shared connection request to sdap_handle completes.
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * This member is cleared when sdap_id_op_connect_state
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * associated with request is destroyed */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_req *connect_req;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom};
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* LDAP connection cache connection attempt/established connection data */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstruct sdap_id_conn_data {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* LDAP connection cache */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* double linked list pointers */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *prev, *next;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* sdap handle */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_handle *sh;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* connection request */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_req *connect_req;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* timer for connection expiration */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_timer *expire_timer;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* number of running connection notifies */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int notify_lock;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* list of operations using connect */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *ops;
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny /* A flag which is signalizing that this
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny * connection will be disconnected and should
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny * not be used any more */
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny bool disconnecting;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom};
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_conn_cache_be_offline_cb(void *pvt);
10922e0293f3ebf056708acacce35e93fe07747eJan Zelenystatic void sdap_id_conn_cache_fo_reconnect_cb(void *pvt);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_release_conn_data(struct sdap_id_conn_data *conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_conn_data_destroy(struct sdap_id_conn_data *conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic bool sdap_is_connection_expired(struct sdap_id_conn_data *conn_data, int timeout);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic bool sdap_can_reuse_connection(struct sdap_id_conn_data *conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_conn_data_expire_handler(struct tevent_context *ev,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_timer *te,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct timeval current_time,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom void *pvt);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_conn_data_set_expire_timer(struct sdap_id_conn_data *conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn_data *conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_op_destroy(void *pvt);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic bool sdap_id_op_can_reconnect(struct sdap_id_op *op);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_op_connect_state_destroy(void *pvt);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_op_connect_step(struct tevent_req *req);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_op_connect_done(struct tevent_req *subreq);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Create a connection cache */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomint sdap_id_conn_cache_create(TALLOC_CTX *memctx,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce struct sdap_id_ctx *id_ctx,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache** conn_cache_out)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int ret;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache = talloc_zero(memctx, struct sdap_id_conn_cache);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!conn_cache) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(1, ("talloc_zero(struct sdap_id_conn_cache) failed.\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = ENOMEM;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto fail;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce conn_cache->id_ctx = id_ctx;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce ret = be_add_offline_cb(conn_cache, id_ctx->be,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_conn_cache_be_offline_cb, conn_cache,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom NULL);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(1, ("be_add_offline_cb failed.\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto fail;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny ret = be_add_reconnect_cb(conn_cache, id_ctx->be,
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny sdap_id_conn_cache_fo_reconnect_cb, conn_cache,
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny NULL);
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (ret != EOK) {
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny DEBUG(SSSDBG_CRIT_FAILURE, ("be_add_reconnect_cb failed.\n"));
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny goto fail;
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny }
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom *conn_cache_out = conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomfail:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_zfree(conn_cache);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return ret;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Callback on BE going offline */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_conn_cache_be_offline_cb(void *pvt)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache = talloc_get_type(pvt, struct sdap_id_conn_cache);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *cached_connection = conn_cache->cached_connection;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* Release any cached connection on going offline */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (cached_connection != NULL) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(cached_connection);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny/* Callback for attempt to reconnect to primary server */
10922e0293f3ebf056708acacce35e93fe07747eJan Zelenystatic void sdap_id_conn_cache_fo_reconnect_cb(void *pvt)
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny{
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny struct sdap_id_conn_cache *conn_cache = talloc_get_type(pvt, struct sdap_id_conn_cache);
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny struct sdap_id_conn_data *cached_connection = conn_cache->cached_connection;
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny /* Release any cached connection on going offline */
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (cached_connection != NULL) {
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny cached_connection->disconnecting = true;
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny }
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny}
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Release sdap_id_conn_data and destroy it if no longer needed */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_release_conn_data(struct sdap_id_conn_data *conn_data)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!conn_data || conn_data->ops || conn_data->notify_lock) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* connection is in use */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache = conn_data->conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_data == conn_cache->cached_connection) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("releasing unused connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DLIST_REMOVE(conn_cache->connections, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_zfree(conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Destructor for struct sdap_id_conn_data */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_conn_data_destroy(struct sdap_id_conn_data *conn_data)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *op;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* we clean out list of ops to make sure that order of destruction does not matter */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom while ((op = conn_data->ops) != NULL) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->conn_data = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DLIST_REMOVE(conn_data->ops, op);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return 0;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Check whether connection will expire after timeout seconds */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic bool sdap_is_connection_expired(struct sdap_id_conn_data *conn_data, int timeout)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom time_t expire_time;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!conn_data || !conn_data->sh || !conn_data->sh->connected) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom expire_time = conn_data->sh->expire_time;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if ((expire_time != 0) && (expire_time < time( NULL ) + timeout) ) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Check whether connection can be reused for next LDAP ID operation */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic bool sdap_can_reuse_connection(struct sdap_id_conn_data *conn_data)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int timeout;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (!conn_data || !conn_data->sh ||
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny !conn_data->sh->connected || conn_data->disconnecting) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce timeout = dp_opt_get_int(conn_data->conn_cache->id_ctx->opts->basic,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce SDAP_OPT_TIMEOUT);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return !sdap_is_connection_expired(conn_data, timeout);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Set expiration timer for connection if needed */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_conn_data_set_expire_timer(struct sdap_id_conn_data *conn_data)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int timeout;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct timeval tv;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom memset(&tv, 0, sizeof(tv));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom tv.tv_sec = conn_data->sh->expire_time;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (tv.tv_sec <= 0) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce timeout = dp_opt_get_int(conn_data->conn_cache->id_ctx->opts->basic,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce SDAP_OPT_TIMEOUT);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (timeout > 0) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom tv.tv_sec -= timeout;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (tv.tv_sec <= time(NULL)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_zfree(conn_data->expire_timer);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce conn_data->expire_timer =
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce tevent_add_timer(conn_data->conn_cache->id_ctx->be->ev,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce conn_data, tv,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce sdap_id_conn_data_expire_handler,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!conn_data->expire_timer) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return ENOMEM;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Handler for connection expiration timer */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_conn_data_expire_handler(struct tevent_context *ev,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_timer *te,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct timeval current_time,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom void *pvt)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *conn_data = talloc_get_type(pvt,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(3, ("connection is about to expire, releasing it\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_cache->cached_connection == conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Create an operation object */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstruct sdap_id_op *sdap_id_op_create(TALLOC_CTX *memctx, struct sdap_id_conn_cache *conn_cache)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *op = talloc_zero(memctx, struct sdap_id_op);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!op) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->conn_cache = conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_set_destructor((void*)op, sdap_id_op_destroy);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return op;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Attach/detach connection to sdap_id_op */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn_data *conn_data)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!op) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(0, ("NULL op passed!!!\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *current = op->conn_data;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_data == current) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (current) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DLIST_REMOVE(current->ops, op);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->conn_data = conn_data;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DLIST_ADD_END(conn_data->ops, op, struct sdap_id_op*);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (current) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(current);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Destructor for sdap_id_op */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_op_destroy(void *pvt)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *op = talloc_get_type(pvt, struct sdap_id_op);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (op->conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("releasing operation connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, NULL);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return 0;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Check whether retry with reconnect can be performed for the operation */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic bool sdap_id_op_can_reconnect(struct sdap_id_op *op)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* we allow 2 retries for failover server configured:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * - one for connection broken during request execution
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * - one for the following (probably failed) reconnect attempt */
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce int max_retries;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce int count;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce count = be_fo_get_server_count(op->conn_cache->id_ctx->be,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce op->conn_cache->id_ctx->service->name);
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce max_retries = 2 * count -1;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (max_retries < 1) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom max_retries = 1;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return op->reconnect_retry_count < max_retries;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce/* state of connect request */
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorcestruct sdap_id_op_connect_state {
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce struct sdap_id_ctx *id_ctx;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce struct tevent_context *ev;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce struct sdap_id_op *op;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce int dp_error;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce int result;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce};
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Destructor for operation connection request */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_op_connect_state_destroy(void *pvt)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op_connect_state *state = talloc_get_type(pvt,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op_connect_state);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (state->op != NULL) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* clear destroyed connection request */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom state->op->connect_req = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return 0;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Begin to connect to LDAP server */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstruct tevent_req *sdap_id_op_connect_send(struct sdap_id_op *op,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom TALLOC_CTX *memctx,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int *ret_out)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_req *req = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op_connect_state *state;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int ret = EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!memctx) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(1, ("Bug: no memory context passed.\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = EINVAL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (op->connect_req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* Connection already in progress, invalid operation */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(1, ("Bug: connection request is already running or completed and leaked.\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = EINVAL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom req = tevent_req_create(memctx, &state, struct sdap_id_op_connect_state);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = ENOMEM;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_set_destructor((void*)state, sdap_id_op_connect_state_destroy);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce state->id_ctx = op->conn_cache->id_ctx;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce state->ev = state->id_ctx->be->ev;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom state->op = op;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->connect_req = req;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (op->conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* If the operation is already connected,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * reuse existing connection regardless of its status */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("reusing operation connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = sdap_id_op_connect_step(req);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomdone:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_zfree(req);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else if (op->conn_data && !op->conn_data->connect_req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* Connection is already established */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom tevent_req_done(req);
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce tevent_req_post(req, state->ev);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret_out) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom *ret_out = ret;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return req;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Begin a connection retry to LDAP server */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic int sdap_id_op_connect_step(struct tevent_req *req)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce struct sdap_id_op_connect_state *state =
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce tevent_req_data(req, struct sdap_id_op_connect_state);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *op = state->op;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache = op->conn_cache;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int ret = EOK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_data *conn_data;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_req *subreq = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* Try to reuse context cached connection */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data = conn_cache->cached_connection;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_data->connect_req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("waiting for connection to complete\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (sdap_can_reuse_connection(conn_data)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("reusing cached connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("releasing expired cached connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("beginning to connect\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data = talloc_zero(conn_cache, struct sdap_id_conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = ENOMEM;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_set_destructor(conn_data, sdap_id_conn_data_destroy);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data->conn_cache = conn_cache;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce subreq = sdap_cli_connect_send(conn_data, state->ev,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce state->id_ctx->opts,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce state->id_ctx->be,
9b9c7f8caddf2b57adfbef8741651ee5063fa3bdJakub Hrozek state->id_ctx->service, false,
9b9c7f8caddf2b57adfbef8741651ee5063fa3bdJakub Hrozek CON_TLS_DFL, false);
9b9c7f8caddf2b57adfbef8741651ee5063fa3bdJakub Hrozek
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!subreq) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = ENOMEM;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom tevent_req_set_callback(subreq, sdap_id_op_connect_done, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data->connect_req = subreq;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DLIST_ADD(conn_cache->connections, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = conn_data;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomdone:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK && conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_zfree(subreq);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return ret;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Subrequest callback for connection completion */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_op_connect_done(struct tevent_req *subreq)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
1d9eec9e868fbc2d996f1030a43675be9a840133Simo Sorce struct sdap_id_conn_data *conn_data =
1d9eec9e868fbc2d996f1030a43675be9a840133Simo Sorce tevent_req_callback_data(subreq, struct sdap_id_conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache;
85abff7f43e8006de2c2fa35612884d377b9a036Simo Sorce struct sdap_server_opts *srv_opts = NULL;
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny struct sdap_server_opts *current_srv_opts = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom bool can_retry = false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom bool is_offline = false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int ret;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
1d9eec9e868fbc2d996f1030a43675be9a840133Simo Sorce ret = sdap_cli_connect_recv(subreq, conn_data, &can_retry,
1d9eec9e868fbc2d996f1030a43675be9a840133Simo Sorce &conn_data->sh, &srv_opts);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data->connect_req = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom talloc_zfree(subreq);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data->notify_lock++;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == ENOTSUP) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(0, ("Authentication mechanism not Supported by server\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK && (!conn_data->sh || !conn_data->sh->connected)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(0, ("sdap_cli_connect_recv returned bogus connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = EFAULT;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK && !can_retry) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* be is going offline as there is no more servers to try */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(1, ("Failed to connect, going offline (%d [%s])\n",
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret, strerror(ret)));
45a1a6d68af7a22a13f046855c59329221667448Jan Zeleny be_mark_offline(conn_cache->id_ctx->be);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom is_offline = true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny current_srv_opts = conn_cache->id_ctx->srv_opts;
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny if (current_srv_opts) {
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny DEBUG(8, ("Old USN: %lu, New USN: %lu\n", current_srv_opts->last_usn, srv_opts->last_usn));
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny if (strcmp(srv_opts->server_id, current_srv_opts->server_id) == 0 &&
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny srv_opts->supports_usn &&
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny current_srv_opts->last_usn > srv_opts->last_usn) {
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny DEBUG(5, ("Server was probably re-initialized\n"));
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny
772764e048dcd15c6d9732574126eb83b53a60e2Jan Zeleny current_srv_opts->max_user_value = 0;
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny current_srv_opts->max_group_value = 0;
e2925c2d7d10cbb51098402233784044168f1a77Stephen Gallagher current_srv_opts->max_service_value = 0;
c8704f06db6dbbe39f50dfb35f20cdf27cf1f087Pavel Březina current_srv_opts->max_sudo_value = 0;
772764e048dcd15c6d9732574126eb83b53a60e2Jan Zeleny current_srv_opts->last_usn = srv_opts->last_usn;
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny }
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = sdap_id_conn_data_set_expire_timer(conn_data);
85abff7f43e8006de2c2fa35612884d377b9a036Simo Sorce sdap_steal_server_opts(conn_cache->id_ctx, &srv_opts);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (can_retry) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom switch (ret) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case EOK:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case ENOTSUP:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case EACCES:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case EIO:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case EFAULT:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case ETIMEDOUT:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom default:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* do not attempt to retry on errors like ENOMEM */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom can_retry = false;
45a1a6d68af7a22a13f046855c59329221667448Jan Zeleny is_offline = true;
45a1a6d68af7a22a13f046855c59329221667448Jan Zeleny be_mark_offline(conn_cache->id_ctx->be);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int notify_count = 0;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* Notify about connection */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom for(;;) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op *op;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK && !conn_data->sh->connected) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("connection was broken after %d notifies\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DLIST_FOR_EACH(op, conn_data->ops) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (op->connect_req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!op) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* another operation to notify */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom notify_count++;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK || !conn_data->sh->connected) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* failed to connect or connection got broken during notify */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom bool retry = false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* drop connection from cache now */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_cache->cached_connection == conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (can_retry) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* determining whether retry is possible */
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce if (be_is_offline(conn_cache->id_ctx->be)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* be is offline, no retry possible */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("skipping automatic retry on op #%d as be is offline\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = EIO;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom can_retry = false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom is_offline = true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("attempting automatic retry on op #%d\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom retry = true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else if (sdap_id_op_can_reconnect(op)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("attempting failover retry on op #%d\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->reconnect_retry_count++;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom retry = true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (retry && op->connect_req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int retry_ret = sdap_id_op_connect_step(op->connect_req);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (retry_ret != EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom can_retry = false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_connect_req_complete(op, DP_ERR_FATAL, retry_ret);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom continue;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("notify connected to op #%d\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_connect_req_complete(op, DP_ERR_OK, ret);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else if (is_offline) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("notify offline to op #%d\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_connect_req_complete(op, DP_ERR_OFFLINE, EAGAIN);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("notify error to op #%d: %d [%s]\n", notify_count, ret, strerror(ret)));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_connect_req_complete(op, DP_ERR_FATAL, ret);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* all operations notified */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_data->notify_lock > 0) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_data->notify_lock--;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce if ((ret == EOK) &&
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce conn_data->sh->connected &&
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce !be_is_offline(conn_cache->id_ctx->be)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("caching successful connection after %d notifies\n", notify_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = conn_data;
1639954090616f9e868a083f358c87e381b3fb78eindenbom
1639954090616f9e868a083f358c87e381b3fb78eindenbom /* Run any post-connection routines */
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce be_run_online_cb(conn_cache->id_ctx->be);
1639954090616f9e868a083f358c87e381b3fb78eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (conn_cache->cached_connection == conn_data) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Mark operation connection request as complete */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstatic void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct tevent_req *req = op->connect_req;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op_connect_state *state;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!req) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->connect_req = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom state = tevent_req_data(req, struct sdap_id_op_connect_state);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom state->dp_error = dp_error;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom state->result = ret;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom tevent_req_done(req);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, NULL);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom tevent_req_error(req, ret);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Get the result of an asynchronous connect operation on sdap_id_op
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom *
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * In dp_error data provider error code is returned:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_OK - connection established
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_OFFLINE - backend is offline, operation result is set EAGAIN
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_FATAL - operation failed
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomint sdap_id_op_connect_recv(struct tevent_req *req, int *dp_error)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op_connect_state *state = tevent_req_data(req,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom struct sdap_id_op_connect_state);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom *dp_error = state->dp_error;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return state->result;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Report completion of LDAP operation and release associated connection.
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * Returns operation result (possible updated) passed in ret parameter.
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom *
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * In dp_error data provider error code is returned:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_OK (operation result = EOK) - operation completed
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_OK (operation result != EOK) - operation can be retried
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_OFFLINE - backend is offline, operation result is set EAGAIN
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom * DP_ERR_FATAL - operation failed */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomint sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom bool communication_error;
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny struct sdap_id_conn_data *current_conn = op->conn_data;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom switch (retval) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case EIO:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom case ETIMEDOUT:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* this currently the only possible communication error after connection is established */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom communication_error = true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom default:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom communication_error = false;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (communication_error && current_conn != 0
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny && current_conn == op->conn_cache->cached_connection) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* do not reuse failed connection */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->conn_cache->cached_connection = NULL;
54577e54d1b6300aeb348087372c14ed72530f88eindenbom
54577e54d1b6300aeb348087372c14ed72530f88eindenbom DEBUG(5, ("communication error on cached connection, moving to next server\n"));
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce be_fo_try_next_server(op->conn_cache->id_ctx->be,
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce op->conn_cache->id_ctx->service->name);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int dp_err;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (retval == EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom dp_err = DP_ERR_OK;
cf1cf7b96d38c8b481a90d800cf53546ac15ce8aSimo Sorce } else if (be_is_offline(op->conn_cache->id_ctx->be)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* if backend is already offline, just report offline, do not duplicate errors */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom dp_err = DP_ERR_OFFLINE;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom retval = EAGAIN;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("falling back to offline data...\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else if (communication_error) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* communication error, can try to reconnect */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (!sdap_id_op_can_reconnect(op)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom dp_err = DP_ERR_FATAL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("too many communication failures, giving up...\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom dp_err = DP_ERR_OK;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom retval = EAGAIN;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom dp_err = DP_ERR_FATAL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (dp_err == DP_ERR_OK && retval != EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* reconnect retry */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->reconnect_retry_count++;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("advising for connection retry #%i\n", op->reconnect_retry_count));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* end of request */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom op->reconnect_retry_count = 0;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (current_conn) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom DEBUG(9, ("releasing operation connection\n"));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, NULL);
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (current_conn->ops == NULL || current_conn->disconnecting) {
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny DEBUG(SSSDBG_TRACE_FUNC, ("Connection is marked for "
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny "disconnection, executing ...\n"));
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny sdap_id_release_conn_data(current_conn);
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom *dp_err_out = dp_err;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return retval;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom/* Get SDAP handle associated with operation by sdap_id_op_connect */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbomstruct sdap_handle *sdap_id_op_handle(struct sdap_id_op *op)
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom{
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom return op && op->conn_data ? op->conn_data->sh : NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom}