sdap_id_op.c revision d67a80baf0bdc888297d3587c98f8a12d4827ebc
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw LDAP ID backend operation retry logic and connection cache
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Eugene Indenbom <eindenbom@gmail.com>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw Copyright (C) 2008-2010 Red Hat
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 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 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/* LDAP async connection cache */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* list of all open connections */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* cached (current) connection */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* LDAP async operation tracker:
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright * - keeps track of connection usage
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright * - keeps track of operation retries */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* ID backend context */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* double linked list pointers */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* current connection */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* number of reconnects for this operation */
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/* LDAP connection cache connection attempt/established connection data */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* LDAP connection cache */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* double linked list pointers */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* sdap handle */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* connection request */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* timer for connection expiration */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* number of running connection notifies */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* list of operations using connect */
3db3f65c6274eb042354801a308c8e9bc4994553amw /* A flag which is signalizing that this
3db3f65c6274eb042354801a308c8e9bc4994553amw * connection will be disconnected and should
3db3f65c6274eb042354801a308c8e9bc4994553amw * not be used any more */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sdap_id_conn_cache_fo_reconnect_cb(void *pvt);
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,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int sdap_id_conn_data_set_expire_timer(struct sdap_id_conn_data *conn_data);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn_data *conn_data);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic bool sdap_id_op_can_reconnect(struct sdap_id_op *op);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int sdap_id_op_connect_step(struct tevent_req *req);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sdap_id_op_connect_done(struct tevent_req *subreq);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Create a connection cache */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw struct sdap_id_conn_cache *conn_cache = talloc_zero(memctx, struct sdap_id_conn_cache);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DEBUG(1, ("talloc_zero(struct sdap_id_conn_cache) failed.\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ret = be_add_offline_cb(conn_cache, id_conn->id_ctx->be,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ret = be_add_reconnect_cb(conn_cache, id_conn->id_ctx->be,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw DEBUG(SSSDBG_CRIT_FAILURE, ("be_add_reconnect_cb failed.\n"));
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Callback on BE going offline */
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 /* Release any cached connection on going offline */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Callback for attempt to reconnect to primary server */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic void sdap_id_conn_cache_fo_reconnect_cb(void *pvt)
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 /* Release any cached connection on going offline */
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 if (!conn_data || conn_data->ops || conn_data->notify_lock) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* connection is in use */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/* Destructor for struct sdap_id_conn_data */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwstatic int sdap_id_conn_data_destroy(struct sdap_id_conn_data *conn_data)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* we clean out list of ops to make sure that order of destruction does not matter */
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 if (!conn_data || !conn_data->sh || !conn_data->sh->connected) {
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh if ((expire_time != 0) && (expire_time < time( NULL ) + timeout) ) {
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh return false;
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 !conn_data->sh->connected || conn_data->disconnecting) {
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh return false;
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->id_ctx->opts->basic,
037cac007b685e7ea79f6ef7e8e62bfd342a4d56joyce mcintosh return !sdap_is_connection_expired(conn_data, timeout);
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 timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->id_ctx->opts->basic,
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 sdap_id_conn_data *conn_data = talloc_get_type(pvt,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright struct sdap_id_conn_cache *conn_cache = conn_data->conn_cache;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DEBUG(3, ("connection is about to expire, releasing it\n"));
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright if (conn_cache->cached_connection == conn_data) {
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 struct sdap_id_op *op = talloc_zero(memctx, struct sdap_id_op);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright talloc_set_destructor((void*)op, sdap_id_op_destroy);
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 struct sdap_id_conn_data *current = op->conn_data;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DLIST_ADD_END(conn_data->ops, op, struct sdap_id_op*);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* Destructor for sdap_id_op */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright struct sdap_id_op *op = talloc_get_type(pvt, struct sdap_id_op);
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 /* 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 count = be_fo_get_server_count(op->conn_cache->id_conn->id_ctx->be,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* state of connect request */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* Destructor for operation connection request */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightstatic int sdap_id_op_connect_state_destroy(void *pvt)
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright struct sdap_id_op_connect_state *state = talloc_get_type(pvt,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright /* clear destroyed connection request */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* Begin to connect to LDAP server */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightstruct tevent_req *sdap_id_op_connect_send(struct sdap_id_op *op,
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 req = tevent_req_create(memctx, &state, struct sdap_id_op_connect_state);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright talloc_set_destructor((void*)state, sdap_id_op_connect_state_destroy);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright /* If the operation is already connected,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright * reuse existing connection regardless of its status */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright } else if (op->conn_data && !op->conn_data->connect_req) {
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright /* Connection is already established */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* Begin a connection retry to LDAP server */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightstatic int sdap_id_op_connect_step(struct tevent_req *req)
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright tevent_req_data(req, struct sdap_id_op_connect_state);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright struct sdap_id_conn_cache *conn_cache = op->conn_cache;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright /* Try to reuse context cached connection */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DEBUG(9, ("waiting for connection to complete\n"));
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DEBUG(9, ("releasing expired cached connection\n"));
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright conn_data = talloc_zero(conn_cache, struct sdap_id_conn_data);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright talloc_set_destructor(conn_data, sdap_id_conn_data_destroy);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright subreq = sdap_cli_connect_send(conn_data, state->ev,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright tevent_req_set_callback(subreq, sdap_id_op_connect_done, conn_data);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightstatic void sdap_id_op_connect_reinit_done(struct tevent_req *req);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright/* Subrequest callback for connection completion */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wrightstatic void sdap_id_op_connect_done(struct tevent_req *subreq)
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 *current_srv_opts = NULL;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright bool can_retry = false;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright bool reinit = false;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright ret = sdap_cli_connect_recv(subreq, conn_data, &can_retry,
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DEBUG(0, ("Authentication mechanism not Supported by server\n"));
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 ("Failed to connect to server, but ignore mark offline "
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright "is enabled.\n"));
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright /* be is going offline as there is no more servers to try */
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright ("Failed to connect, going offline (%d [%s])\n",
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright be_mark_offline(conn_cache->id_conn->id_ctx->be);
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright current_srv_opts = conn_cache->id_conn->id_ctx->srv_opts;
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DEBUG(8, ("Old USN: %lu, New USN: %lu\n", current_srv_opts->last_usn, srv_opts->last_usn));
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright if (strcmp(srv_opts->server_id, current_srv_opts->server_id) == 0 &&
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright current_srv_opts->last_usn > srv_opts->last_usn) {
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright DEBUG(5, ("Server was probably re-initialized\n"));
29bd28862cfb8abbd3a0f0a4b17e08bbc3652836Alan Wright current_srv_opts->last_usn = srv_opts->last_usn;
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);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* do not attempt to retry on errors like ENOMEM */
int notify_count = 0;
if (!op) {
notify_count++;
bool retry = false;
if (can_retry) {
can_retry = false;
is_offline = true;
retry = true;
retry = true;
can_retry = false;
} else if (is_offline) {
if (reinit) {
NULL);
if (!req) {
struct sdap_id_op_connect_state);
bool communication_error;
switch (retval) {
case EIO:
case ETIMEDOUT:
communication_error = true;
communication_error = false;
int dp_err;
} else if (communication_error) {
if (current_conn) {
return retval;