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 {
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek struct sdap_id_conn_ctx *id_conn;
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,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek struct sdap_id_conn_ctx *id_conn,
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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "talloc_zero(struct sdap_id_conn_cache) failed.\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = ENOMEM;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto fail;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek conn_cache->id_conn = id_conn;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek ret = be_add_offline_cb(conn_cache, id_conn->id_ctx->be,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_conn_cache_be_offline_cb, conn_cache,
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom NULL);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "be_add_offline_cb failed.\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto fail;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek ret = be_add_reconnect_cb(conn_cache, id_conn->id_ctx->be,
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny sdap_id_conn_cache_fo_reconnect_cb, conn_cache,
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny NULL);
10922e0293f3ebf056708acacce35e93fe07747eJan Zeleny if (ret != EOK) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov 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
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "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
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->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
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek timeout = dp_opt_get_int(conn_data->conn_cache->id_conn->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 =
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek tevent_add_timer(conn_data->conn_cache->id_conn->id_ctx->be->ev,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek conn_data, tv,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek sdap_id_conn_data_expire_handler,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek 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
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_MINOR_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE, "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "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
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek count = be_fo_get_server_count(op->conn_cache->id_conn->id_ctx->be,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek op->conn_cache->id_conn->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 {
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek struct sdap_id_conn_ctx *id_conn;
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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "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 */
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek state->id_conn = op->conn_cache->id_conn;
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek state->ev = state->id_conn->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 */
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "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)) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "reusing cached connection\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom goto done;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "releasing expired cached connection\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = NULL;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_release_conn_data(conn_data);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "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,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek state->id_conn->id_ctx->opts,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek state->id_conn->id_ctx->be,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek state->id_conn->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
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinastatic void sdap_id_op_connect_reinit_done(struct tevent_req *req);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
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;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina struct tevent_req *reinit_req = NULL;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina bool reinit = 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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "Authentication mechanism not Supported by server\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK && (!conn_data->sh || !conn_data->sh->connected)) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FATAL_FAILURE,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "sdap_cli_connect_recv returned bogus connection\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = EFAULT;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret != EOK && !can_retry) {
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik if (conn_cache->id_conn->ignore_mark_offline) {
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik DEBUG(SSSDBG_TRACE_FUNC,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to connect to server, but ignore mark offline "
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "is enabled.\n");
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik } else {
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik /* be is going offline as there is no more servers to try */
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik DEBUG(SSSDBG_CRIT_FAILURE,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Failed to connect, going offline (%d [%s])\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov ret, strerror(ret));
0561d532cf76b035b73cfed929a6896071dac407Jakub Hrozek is_offline = true;
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik be_mark_offline(conn_cache->id_conn->id_ctx->be);
d67a80baf0bdc888297d3587c98f8a12d4827ebcLukas Slebodnik }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek current_srv_opts = conn_cache->id_conn->id_ctx->srv_opts;
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny if (current_srv_opts) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_INTERNAL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FUNC_DATA, "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;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina reinit = true;
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny }
743475e5d730f1438bff4bb086600186adfe8311Jan Zeleny }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom ret = sdap_id_conn_data_set_expire_timer(conn_data);
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio if (ret != EOK) {
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio DEBUG(SSSDBG_MINOR_FAILURE,
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio "sdap_id_conn_data_set_expire_timer() failed [%d]: %s",
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio ret, sss_strerror(ret));
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio /* Avoid causing the whole backend to be marked as offline because
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio * this operation failed. */
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio ret = EOK;
5a117d36030f589cc04430ea1c6c328a8fdb903fFabiano Fidêncio }
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek sdap_steal_server_opts(conn_cache->id_conn->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:
73dd89c3fb361dab43b4802510f4c64d282dbde1Pavel Březina case ERR_AUTH_FAILED:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom break;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom default:
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* do not attempt to retry on errors like ENOMEM */
362b8a94c0ffaa63af3a5a5772c29303be009640Fabiano Fidêncio DEBUG(SSSDBG_TRACE_FUNC,
362b8a94c0ffaa63af3a5a5772c29303be009640Fabiano Fidêncio "Marking the backend \"%s\" offline [%d]: %s\n",
362b8a94c0ffaa63af3a5a5772c29303be009640Fabiano Fidêncio conn_cache->id_conn->id_ctx->be->domain->name,
362b8a94c0ffaa63af3a5a5772c29303be009640Fabiano Fidêncio ret, sss_strerror(ret));
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom can_retry = false;
45a1a6d68af7a22a13f046855c59329221667448Jan Zeleny is_offline = true;
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek be_mark_offline(conn_cache->id_conn->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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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 */
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek if (be_is_offline(conn_cache->id_conn->id_ctx->be)) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom /* be is offline, no retry possible */
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (ret == EOK) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "attempting automatic retry on op #%d\n", notify_count);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom retry = true;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else if (sdap_id_op_can_reconnect(op)) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "notify offline to op #%d\n", notify_count);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_connect_req_complete(op, DP_ERR_OFFLINE, EAGAIN);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom } else {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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 &&
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek !be_is_offline(conn_cache->id_conn->id_ctx->be)) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "caching successful connection after %d notifies\n", notify_count);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom conn_cache->cached_connection = conn_data;
1639954090616f9e868a083f358c87e381b3fb78eindenbom
1639954090616f9e868a083f358c87e381b3fb78eindenbom /* Run any post-connection routines */
0a320004a9937295ba66a348d1e60682cfdceb26Sumit Bose be_run_unconditional_online_cb(conn_cache->id_conn->id_ctx->be);
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek be_run_online_cb(conn_cache->id_conn->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 }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (reinit) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Server reinitialization detected. "
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "Cleaning cache.\n");
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek reinit_req = sdap_reinit_cleanup_send(conn_cache->id_conn->id_ctx->be,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek conn_cache->id_conn->id_ctx->be,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek conn_cache->id_conn->id_ctx);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (reinit_req == NULL) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "clean up.\n");
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina return;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina tevent_req_set_callback(reinit_req, sdap_id_op_connect_reinit_done,
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina NULL);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina}
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březinastatic void sdap_id_op_connect_reinit_done(struct tevent_req *req)
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina{
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina errno_t ret;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina ret = sdap_reinit_cleanup_recv(req);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina talloc_zfree(req);
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina if (ret != EOK) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Unable to perform reinitialization "
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "clean up [%d]: %s\n", ret, strerror(ret));
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina /* not fatal */
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina return;
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina }
41be4e3976cf66823ad2c6880671ac7fbafdc640Pavel Březina
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_TRACE_FUNC, "Reinitialization clean up completed\n");
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
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_FUNC_DATA,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "communication error on cached connection, moving to next server\n");
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek be_fo_try_next_server(op->conn_cache->id_conn->id_ctx->be,
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek op->conn_cache->id_conn->service->name);
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom }
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom int dp_err;
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom if (retval == EOK) {
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom dp_err = DP_ERR_OK;
dcb44c39dda9699cdd6488fd116a51ced0687de3Jakub Hrozek } else if (be_is_offline(op->conn_cache->id_conn->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;
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "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;
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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++;
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL,
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov "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) {
83bf46f4066e3d5e838a32357c201de9bd6ecdfdNikolai Kondrashov DEBUG(SSSDBG_TRACE_ALL, "releasing operation connection\n");
2d7a7b0140a4d3fcef9148900276e24f82e33866eindenbom sdap_id_op_hook_conn_data(op, NULL);
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}