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