diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 73e7b34fbe1..29c4d6e94a9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -311,6 +311,9 @@ jobs:
--polarion-config=../polarion.yaml \
--output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \
${{ steps.select-tests.outputs.SELECT_TESTS }} \
+ --mh-not-topology=ipa --mh-not-topology=samba --mh-not-topology=ad \
+ --mh-not-topology=ipa-trust-samba \
+ -k "not test_logging__default_settings_logs_ and not test_failover and not test_autofs__propagate_offline_status_for_multiple_domains" \
--collect-only . |& tee $GITHUB_WORKSPACE/pytest-collect.log
- name: Run tests
@@ -331,6 +334,9 @@ jobs:
--output-polarion-testcase=$GITHUB_WORKSPACE/artifacts/testcase.xml \
--output-polarion-testrun=$GITHUB_WORKSPACE/artifacts/testrun.xml \
${{ steps.select-tests.outputs.SELECT_TESTS }} \
+ --mh-not-topology=ipa --mh-not-topology=samba --mh-not-topology=ad \
+ --mh-not-topology=ipa-trust-samba \
+ -k "not test_logging__default_settings_logs_ and not test_failover and not test_autofs__propagate_offline_status_for_multiple_domains" \
-vvv . |& tee $GITHUB_WORKSPACE/pytest.log
- name: Upload artifacts
diff --git a/Makefile.am b/Makefile.am
index 05e0baba934..aab25c20629 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -301,6 +301,7 @@ if HAVE_CMOCKA
test_sbus_message \
test_sbus_opath \
test_fo_srv \
+ test_failover_server \
pam-srv-tests \
ssh-srv-tests \
test_ipa_subdom_util \
@@ -648,6 +649,25 @@ SSSD_FAILOVER_OBJ = \
src/providers/fail_over_srv.c \
$(SSSD_RESOLV_OBJ)
+# Make sure to build new failover code to test compilation even though it is
+# not used anywhere yet.
+SSSD_NEW_FAILOVER_OBJ = \
+ src/providers/failover/failover.c \
+ src/providers/failover/failover_callback.c \
+ src/providers/failover/failover_refresh_candidates.c \
+ src/providers/failover/failover_group.c \
+ src/providers/failover/failover_server_resolve.c \
+ src/providers/failover/failover_server.c \
+ src/providers/failover/failover_srv.c \
+ src/providers/failover/failover_service.c \
+ src/providers/failover/failover_transaction.c \
+ src/providers/failover/failover_vtable_op.c \
+ src/providers/failover/failover_vtable.c \
+ src/providers/failover/ldap/failover_ldap_connect.c \
+ src/providers/failover/ldap/failover_ldap_kinit.c \
+ $(SSSD_RESOLV_OBJ) \
+ $(NULL)
+
SSSD_LIBS = \
$(TALLOC_LIBS) \
$(TEVENT_LIBS) \
@@ -840,6 +860,16 @@ dist_noinst_HEADERS = \
src/providers/be_refresh.h \
src/providers/fail_over.h \
src/providers/fail_over_srv.h \
+ src/providers/failover/failover.h \
+ src/providers/failover/failover_group.h \
+ src/providers/failover/failover_refresh_candidates.h \
+ src/providers/failover/failover_server.h \
+ src/providers/failover/failover_server_resolve.h \
+ src/providers/failover/failover_srv.h \
+ src/providers/failover/failover_transaction.h \
+ src/providers/failover/failover_vtable.h \
+ src/providers/failover/failover_vtable_op.h \
+ src/providers/failover/ldap/failover_ldap.h \
src/util/child_common.h \
src/util/child_bootstrap.h \
src/providers/simple/simple_access.h \
@@ -3471,6 +3501,24 @@ test_fo_srv_LDADD = \
libsss_test_common.la \
$(NULL)
+test_failover_server_SOURCES = \
+ src/tests/cmocka/test_failover_server.c \
+ src/providers/failover/failover_server.c \
+ $(SSSD_RESOLV_TESTS_OBJ) \
+ $(NULL)
+test_failover_server_CFLAGS = \
+ $(AM_CFLAGS) \
+ $(CMOCKA_CFLAGS) \
+ $(NULL)
+test_failover_server_LDADD = \
+ $(CARES_LIBS) \
+ $(CMOCKA_LIBS) \
+ $(POPT_LIBS) \
+ $(SSSD_INTERNAL_LTLIBS) \
+ $(TALLOC_LIBS) \
+ libsss_test_common.la \
+ $(NULL)
+
test_sdap_initgr_SOURCES = \
src/tests/cmocka/common_mock_sdap.c \
src/tests/cmocka/common_mock_sysdb_objects.c \
@@ -4335,6 +4383,7 @@ libsss_ldap_common_la_SOURCES = \
src/util/sss_sockets.c \
src/util/sss_ldap.c \
src/util/cert_derb64_to_ldap_filter.c \
+ $(SSSD_NEW_FAILOVER_OBJ) \
$(NULL)
libsss_ldap_common_la_CFLAGS = \
$(AM_CFLAGS) \
@@ -4414,7 +4463,8 @@ libsss_krb5_common_la_LDFLAGS = \
libsss_ldap_la_SOURCES = \
src/providers/ldap/ldap_init.c \
- src/providers/ldap/ldap_access.c
+ src/providers/ldap/ldap_access.c \
+ $(SSSD_NEW_FAILOVER_OBJ)
libsss_ldap_la_CFLAGS = \
$(AM_CFLAGS) \
$(OPENLDAP_CFLAGS)
diff --git a/minimal-provider-notes.txt b/minimal-provider-notes.txt
new file mode 100644
index 00000000000..45a5b7bf063
--- /dev/null
+++ b/minimal-provider-notes.txt
@@ -0,0 +1,88 @@
+# Minimal SSSD provider
+
+This is used as a proof of concept for the new failover implementation. It can
+also be used to see what changes are required in order to switch to the new
+code, however it really does only minimum amount of changes to get it working.
+It would be very good to provide more thorough refactoring in the real
+providers.
+
+The minimal provider supports:
+- services lookup (getent services)
+- user authentication
+
+## Populate LDAP
+
+```
+$ vim objects.ldif
+dn: ou=users,dc=ldap,dc=test
+objectClass: top
+objectClass: organizationalUnit
+ou: users
+
+# Password is Secret123
+dn: cn=user-1,ou=users,dc=ldap,dc=test
+uid: user-1
+uidNumber: 10000
+homeDirectory: /home/user-1
+gidNumber: 100000
+cn: user-1
+objectClass: posixAccount
+objectClass: top
+userPassword:: e1BCS0RGMi1TSEE1MTJ9MTAwMDAwJEVZU2lqOFgxTTVFZUIrMXlHQzdvZkhwZzd
+ XZXpYRGJwJG0vTVUyMUIrTGNNb2tkRVcvUFJ6YWlhc21zdlNDeVJWdGxPU3c3c05YbHk2NUxBcUcz
+ ODJqQUJWUEp2N1ZnOUtRdXhEamVlbmxEV3V5Ylg5UFdKMW5nPT0=
+
+dn: ou=services,dc=ldap,dc=test
+objectClass: top
+objectClass: organizationalUnit
+ou: services
+
+dn: cn=service0,ou=services,dc=ldap,dc=test
+objectClass: ipService
+cn: service0
+ipServiceProtocol: tcp
+ipServicePort: 12345
+
+$ ldapadd -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -f objects.ldif -vv
+```
+
+## Verify LDAP contents
+
+```
+$ ldapsearch -D "cn=Directory Manager" -w Secret123 -H ldap://master.ldap.test -b dc=ldap,dc=test
+```
+
+## Configure SSSD for services lookup
+
+```
+[sssd]
+domains = minimal
+
+[domain/minimal]
+debug_level = 9
+id_provider = minimal
+
+$ getent services -s sss service0
+service0 12345/tcp
+```
+
+## Configure SSSD for user authentication
+
+Note: user lookup is done by id provider
+
+```
+[sssd]
+services = nss, pam
+domains = minimal
+
+[domain/minimal]
+debug_level = 9
+id_provider = ldap
+auth_provider = minimal
+ldap_uri = _srv_
+dns_discovery_domain = ldap.test
+ldap_tls_reqcert = never
+
+$ su user-1
+Password: Secret123
+```
diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c
index c3686069e38..2c0653fd737 100644
--- a/src/providers/ad/ad_dyndns.c
+++ b/src/providers/ad/ad_dyndns.c
@@ -180,7 +180,6 @@ ad_dyndns_update_send(TALLOC_CTX *mem_ctx,
static void ad_dyndns_update_connect_done(struct tevent_req *subreq)
{
- int dp_error;
int ret;
struct tevent_req *req;
struct ad_dyndns_update_state *state;
@@ -191,11 +190,14 @@ static void ad_dyndns_update_connect_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_dyndns_update_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
+ ctx = state->ad_ctx;
+ sdap_ctx = ctx->id_ctx->sdap_id_ctx;
+
if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(sdap_ctx->be)) {
DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, "
"dynamic DNS update is skipped in offline mode.\n");
tevent_req_error(req, ERR_DYNDNS_OFFLINE);
@@ -208,9 +210,6 @@ static void ad_dyndns_update_connect_done(struct tevent_req *subreq)
return;
}
- ctx = state->ad_ctx;
- sdap_ctx = ctx->id_ctx->sdap_id_ctx;
-
ret = ldap_url_parse(ctx->service->sdap->uri, &lud);
if (ret != LDAP_SUCCESS) {
DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse ldap URI '%s': %d\n",
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c
index 952fa49a0e5..f2a8bd6f5e6 100644
--- a/src/providers/ad/ad_gpo.c
+++ b/src/providers/ad/ad_gpo.c
@@ -2135,7 +2135,6 @@ ad_gpo_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct ad_gpo_access_state *state;
- int dp_error;
errno_t ret;
char *server_uri;
LDAPURLDesc *lud;
@@ -2145,11 +2144,11 @@ ad_gpo_connect_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_gpo_access_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (dp_error != DP_ERR_OFFLINE) {
+ if (!be_is_offline(state->conn->id_ctx->be)) {
DEBUG(SSSDBG_OP_FAILURE,
"Failed to connect to AD server: [%d](%s)\n",
ret, sss_strerror(ret));
@@ -2256,7 +2255,7 @@ ad_gpo_connect_done(struct tevent_req *subreq)
subreq = groups_by_user_send(state, state->ev,
state->access_ctx->ad_id_ctx->sdap_id_ctx,
- sdom, state->conn,
+ sdom,
search_bases,
state->host_fqdn,
BE_FILTER_NAME,
@@ -2282,8 +2281,6 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_gpo_access_state *state;
int ret;
- int dp_error;
- int sdap_ret;
const char *target_dn = NULL;
uint32_t uac;
static const char *host_attrs[] = { SYSDB_ORIG_DN, SYSDB_AD_USER_ACCOUNT_CONTROL, SYSDB_SID_STR, NULL };
@@ -2293,10 +2290,10 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_gpo_access_state);
- ret = groups_by_user_recv(subreq, &dp_error, &sdap_ret);
+ ret = groups_by_user_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (sdap_ret == EAGAIN && dp_error == DP_ERR_OFFLINE) {
+ if (ret == EAGAIN) {
DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n");
ret = process_offline_gpos(state,
state->user,
@@ -2482,7 +2479,6 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_gpo_access_state *state;
int ret;
- int dp_error;
struct gp_gpo **candidate_gpos = NULL;
int num_candidate_gpos = 0;
int i = 0;
@@ -2494,7 +2490,7 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq)
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
+ ret = sdap_id_op_done(state->sdap_op, ret);
if (ret != EOK && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE,
@@ -3368,7 +3364,6 @@ ad_gpo_site_dn_retrieval_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_gpo_process_som_state *state;
int ret;
- int dp_error;
int i = 0;
size_t reply_count;
struct sysdb_attrs **reply;
@@ -3381,7 +3376,7 @@ ad_gpo_site_dn_retrieval_done(struct tevent_req *subreq)
&reply_count, &reply);
talloc_zfree(subreq);
if (ret != EOK) {
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
+ ret = sdap_id_op_done(state->sdap_op, ret);
DEBUG(SSSDBG_OP_FAILURE,
"Unable to get configNC: [%d](%s)\n", ret, sss_strerror(ret));
@@ -3494,7 +3489,6 @@ ad_gpo_get_som_attrs_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_gpo_process_som_state *state;
int ret;
- int dp_error;
size_t num_results;
struct sysdb_attrs **results;
struct ldb_message_element *el = NULL;
@@ -3510,7 +3504,7 @@ ad_gpo_get_som_attrs_done(struct tevent_req *subreq)
talloc_zfree(subreq);
if (ret != EOK) {
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
+ ret = sdap_id_op_done(state->sdap_op, ret);
DEBUG(SSSDBG_OP_FAILURE,
"Unable to get SOM attributes: [%d](%s)\n",
@@ -4217,7 +4211,6 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_gpo_process_gpo_state *state;
int ret;
- int dp_error;
size_t num_results, refcount;
struct sysdb_attrs **results;
char **refs;
@@ -4231,7 +4224,7 @@ ad_gpo_get_gpo_attrs_done(struct tevent_req *subreq)
talloc_zfree(subreq);
if (ret != EOK) {
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
+ ret = sdap_id_op_done(state->sdap_op, ret);
DEBUG(SSSDBG_OP_FAILURE,
"Unable to get GPO attributes: [%d](%s)\n",
@@ -4291,7 +4284,6 @@ void
ad_gpo_get_sd_referral_done(struct tevent_req *subreq)
{
errno_t ret;
- int dp_error;
struct sysdb_attrs *reply;
char *smb_host;
@@ -4304,7 +4296,7 @@ ad_gpo_get_sd_referral_done(struct tevent_req *subreq)
talloc_zfree(subreq);
if (ret != EOK) {
/* Terminate the sdap_id_op */
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
+ ret = sdap_id_op_done(state->sdap_op, ret);
DEBUG(SSSDBG_OP_FAILURE,
"Unable to get referred GPO attributes: [%d](%s)\n",
@@ -5026,7 +5018,6 @@ static void
ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq)
{
errno_t ret;
- int dp_error;
const char *attrs[] = AD_GPO_ATTRS;
LDAPURLDesc *lud = NULL;
@@ -5035,10 +5026,10 @@ ad_gpo_get_sd_referral_conn_done(struct tevent_req *subreq)
struct ad_gpo_get_sd_referral_state *state =
tevent_req_data(req, struct ad_gpo_get_sd_referral_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->conn->id_ctx->be)) {
DEBUG(SSSDBG_TRACE_FUNC,
"Backend is marked offline, retry later!\n");
tevent_req_done(req);
@@ -5092,7 +5083,6 @@ static void
ad_gpo_get_sd_referral_search_done(struct tevent_req *subreq)
{
errno_t ret;
- int dp_error;
size_t num_results, num_refs;
struct sysdb_attrs **results = NULL;
char **refs;
@@ -5106,7 +5096,7 @@ ad_gpo_get_sd_referral_search_done(struct tevent_req *subreq)
&num_refs, &refs);
talloc_zfree(subreq);
if (ret != EOK) {
- ret = sdap_id_op_done(state->ref_op, ret, &dp_error);
+ ret = sdap_id_op_done(state->ref_op, ret);
DEBUG(SSSDBG_OP_FAILURE,
"Unable to get GPO attributes: [%d](%s)\n",
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 4101e3b6661..cdcc71c919f 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -111,7 +111,6 @@ struct ad_handle_acct_info_state {
struct ad_options *ad_options;
bool using_pac;
- int dp_error;
const char *err;
};
@@ -240,8 +239,6 @@ static void
ad_handle_acct_info_done(struct tevent_req *subreq)
{
errno_t ret;
- int dp_error;
- int sdap_err;
const char *err;
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
@@ -249,32 +246,30 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
struct ad_handle_acct_info_state);
if (state->using_pac) {
- ret = ad_handle_pac_initgr_recv(subreq, &dp_error, &err, &sdap_err);
+ ret = ad_handle_pac_initgr_recv(subreq, &err);
} else {
- ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err, &sdap_err);
+ ret = sdap_handle_acct_req_recv(subreq, &err);
}
- if (dp_error == DP_ERR_OFFLINE
+ if (ret == ERR_OFFLINE
&& state->conn[state->cindex+1] != NULL
&& state->conn[state->cindex]->ignore_mark_offline) {
/* This is a special case: GC does not work.
* We need to Fall back to ldap
*/
- ret = EOK;
- sdap_err = ENOENT;
+ ret = ENOENT;
}
talloc_zfree(subreq);
if (ret != EOK) {
- /* if GC was not used dp error should be set */
- state->dp_error = dp_error;
+ /* if GC was not used error should be set */
state->err = err;
goto fail;
}
- if (sdap_err == EOK) {
+ if (ret == EOK) {
tevent_req_done(req);
return;
- } else if (sdap_err != ENOENT) {
+ } else if (ret != ENOENT) {
ret = EIO;
goto fail;
}
@@ -286,7 +281,6 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
/* No additional search in progress. Save the last
* error status, we'll be returning it.
*/
- state->dp_error = dp_error;
state->err = err;
if (ret == EOK) {
@@ -318,15 +312,11 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
errno_t
ad_handle_acct_info_recv(struct tevent_req *req,
- int *_dp_error, const char **_err)
+ const char **_err)
{
struct ad_handle_acct_info_state *state = tevent_req_data(req,
struct ad_handle_acct_info_state);
- if (_dp_error) {
- *_dp_error = state->dp_error;
- }
-
if (_err) {
*_err = state->err;
}
@@ -362,7 +352,6 @@ get_conn_list(TALLOC_CTX *mem_ctx, struct ad_id_ctx *ad_ctx,
struct ad_account_info_state {
const char *err_msg;
- int dp_error;
};
static void ad_account_info_done(struct tevent_req *subreq);
@@ -441,7 +430,7 @@ static void ad_account_info_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_account_info_state);
- ret = ad_handle_acct_info_recv(subreq, &state->dp_error, &state->err_msg);
+ ret = ad_handle_acct_info_recv(subreq, &state->err_msg);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"ad_handle_acct_info_recv failed [%d]: %s\n",
@@ -453,7 +442,6 @@ static void ad_account_info_done(struct tevent_req *subreq)
}
errno_t ad_account_info_recv(struct tevent_req *req,
- int *_dp_error,
const char **_err_msg)
{
struct ad_account_info_state *state = NULL;
@@ -464,11 +452,6 @@ errno_t ad_account_info_recv(struct tevent_req *req,
*_err_msg = state->err_msg;
}
- if (_dp_error) {
- *_dp_error = state->dp_error;
- }
-
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -517,7 +500,7 @@ ad_account_info_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -531,17 +514,16 @@ static void ad_account_info_handler_done(struct tevent_req *subreq)
struct ad_account_info_handler_state *state;
struct tevent_req *req;
const char *err_msg;
- int dp_error = DP_ERR_FATAL;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_account_info_handler_state);
- ret = ad_account_info_recv(subreq, &dp_error, &err_msg);
+ ret = ad_account_info_recv(subreq, &err_msg);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, err_msg);
+ dp_reply_std_set(&state->reply, ret, err_msg);
tevent_req_done(req);
}
@@ -583,7 +565,6 @@ struct ad_get_account_domain_state {
const char *base_filter;
char *filter;
const char **attrs;
- int dp_error;
struct dp_reply_std reply;
struct sdap_id_op *op;
struct sysdb_attrs **objects;
@@ -637,11 +618,11 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
if (domain == NULL) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"SID %s does not fit into any domain\n", data->filter_value);
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL);
+ dp_reply_std_set(&state->reply, ERR_NOT_FOUND, NULL);
} else {
DEBUG(SSSDBG_TRACE_INTERNAL,
"SID %s fits into domain %s\n", data->filter_value, domain->name);
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, domain->name);
+ dp_reply_std_set(&state->reply, EOK, domain->name);
}
tevent_req_done(req);
tevent_req_post(req, params->ev);
@@ -713,7 +694,7 @@ ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -795,16 +776,12 @@ static void ad_get_account_domain_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
- struct ad_get_account_domain_state *state = tevent_req_data(req,
- struct ad_get_account_domain_state);
- int dp_error = DP_ERR_FATAL;
errno_t ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -931,7 +908,7 @@ static void ad_get_account_domain_evaluate(struct tevent_req *req)
}
DEBUG(SSSDBG_TRACE_FUNC, "Not found\n");
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL);
+ dp_reply_std_set(&state->reply, ERR_NOT_FOUND, NULL);
tevent_req_done(req);
return;
} else if (state->count > 1) {
@@ -941,7 +918,7 @@ static void ad_get_account_domain_evaluate(struct tevent_req *req)
* from the responder side
*/
DEBUG(SSSDBG_OP_FAILURE, "Multiple entries found, error!\n");
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERANGE, NULL);
+ dp_reply_std_set(&state->reply, ERANGE, NULL);
tevent_req_done(req);
return;
}
@@ -953,14 +930,14 @@ static void ad_get_account_domain_evaluate(struct tevent_req *req)
if (obj_dom == NULL) {
DEBUG(SSSDBG_OP_FAILURE,
"Could not match entry with domain!\n");
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ERR_NOT_FOUND, NULL);
+ dp_reply_std_set(&state->reply, ERR_NOT_FOUND, NULL);
tevent_req_done(req);
return;
}
DEBUG(SSSDBG_TRACE_INTERNAL,
"Found object in domain %s\n", obj_dom->name);
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, obj_dom->name);
+ dp_reply_std_set(&state->reply, EOK, obj_dom->name);
tevent_req_done(req);
}
diff --git a/src/providers/ad/ad_id.h b/src/providers/ad/ad_id.h
index 664361e3f06..dede0eddfc2 100644
--- a/src/providers/ad/ad_id.h
+++ b/src/providers/ad/ad_id.h
@@ -40,7 +40,6 @@ ad_account_info_send(TALLOC_CTX *mem_ctx,
struct dp_id_data *data);
errno_t ad_account_info_recv(struct tevent_req *req,
- int *_dp_error,
const char **_err_msg);
struct tevent_req *
@@ -52,7 +51,7 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx,
struct sdap_id_conn_ctx **conn);
errno_t
ad_handle_acct_info_recv(struct tevent_req *req,
- int *_dp_error, const char **_err);
+ const char **_err);
struct tevent_req *
ad_get_account_domain_send(TALLOC_CTX *mem_ctx,
diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c
index fd15c63995c..4a8458bd3f9 100644
--- a/src/providers/ad/ad_pac.c
+++ b/src/providers/ad/ad_pac.c
@@ -523,7 +523,6 @@ struct ad_handle_pac_initgr_state {
struct dp_id_data *ar;
const char *err;
int dp_error;
- int sdap_ret;
struct sdap_options *opts;
size_t num_missing_sids;
@@ -569,8 +568,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx,
* sdap_handle_acct_req_recv() from the alternative group-membership
* lookup path. */
state->err = NULL;
- state->dp_error = DP_ERR_OK;
- state->sdap_ret = EOK;
+ state->dp_error = EOK;
ret = ad_get_pac_data_from_user_entry(state, msg,
id_ctx->opts->idmap_ctx->map,
@@ -726,24 +724,16 @@ static void ad_handle_pac_initgr_lookup_sids_done(struct tevent_req *subreq)
}
errno_t ad_handle_pac_initgr_recv(struct tevent_req *req,
- int *_dp_error, const char **_err,
- int *sdap_ret)
+ const char **_err)
{
struct ad_handle_pac_initgr_state *state;
state = tevent_req_data(req, struct ad_handle_pac_initgr_state);
- if (_dp_error) {
- *_dp_error = state->dp_error;
- }
-
if (_err) {
*_err = state->err;
}
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
diff --git a/src/providers/ad/ad_pac.h b/src/providers/ad/ad_pac.h
index 405d1c3af1b..e7657b0219e 100644
--- a/src/providers/ad/ad_pac.h
+++ b/src/providers/ad/ad_pac.h
@@ -77,8 +77,7 @@ struct tevent_req *ad_handle_pac_initgr_send(TALLOC_CTX *mem_ctx,
struct ldb_message *msg);
errno_t ad_handle_pac_initgr_recv(struct tevent_req *req,
- int *_dp_error, const char **_err,
- int *sdap_ret);
+ const char **_err);
errno_t check_upn_and_sid_from_user_and_pac(struct ldb_message *msg,
struct sss_idmap_ctx *ctx,
diff --git a/src/providers/ad/ad_refresh.c b/src/providers/ad/ad_refresh.c
index 7aa56f33edc..9b4d93dbce7 100644
--- a/src/providers/ad/ad_refresh.c
+++ b/src/providers/ad/ad_refresh.c
@@ -154,18 +154,17 @@ static void ad_refresh_done(struct tevent_req *subreq)
struct ad_refresh_state *state = NULL;
struct tevent_req *req = NULL;
const char *err_msg = NULL;
- errno_t dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_refresh_state);
- ret = ad_account_info_recv(subreq, &dp_error, &err_msg);
+ ret = ad_account_info_recv(subreq, &err_msg);
talloc_zfree(subreq);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, "
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s, "
"errno: %d]: %s\n", be_req2str(state->account_req->entry_type),
- dp_error, ret, err_msg);
+ ret, err_msg);
goto done;
}
diff --git a/src/providers/ad/ad_resolver.c b/src/providers/ad/ad_resolver.c
index 0ce4e2a6496..342837a3b7f 100644
--- a/src/providers/ad/ad_resolver.c
+++ b/src/providers/ad/ad_resolver.c
@@ -303,12 +303,12 @@ ad_resolver_enumeration_conn_done(struct tevent_req *subreq)
struct ad_resolver_enum_state *state = tevent_req_data(req,
struct ad_resolver_enum_state);
struct sdap_id_ctx *id_ctx = state->resolver_ctx->ad_id_ctx->sdap_id_ctx;
- int ret, dp_error;
+ int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(id_ctx->be)) {
DEBUG(SSSDBG_TRACE_FUNC,
"Backend is marked offline, retry later!\n");
tevent_req_done(req);
@@ -413,8 +413,7 @@ ad_resolver_enum_sdom(struct tevent_req *req,
subreq = sdap_dom_resolver_enum_send(state, state->ev,
sdap_resolver_ctx,
id_ctx->sdap_id_ctx,
- sd,
- id_ctx->ldap_ctx);
+ sd);
if (subreq == NULL) {
/* The ptask API will reschedule the enumeration on its own on
* failure */
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index bb652a63786..3040968fa3a 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -1191,7 +1191,6 @@ static void ad_get_slave_domain_connect_done(struct tevent_req *subreq)
{
struct ad_get_slave_domain_state *state;
struct tevent_req *req = NULL;
- int dp_error;
errno_t ret;
const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER,
AD_AT_SID, AD_AT_DOMAIN_NAME,
@@ -1200,17 +1199,12 @@ static void ad_get_slave_domain_connect_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_get_slave_domain_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
"[%d]: %s\n", ret, sss_strerror(ret));
- if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
- "cannot get the subdomain list while offline\n");
- ret = ERR_OFFLINE;
- }
tevent_req_error(req, ret);
return;
}
@@ -1238,7 +1232,6 @@ static void ad_get_slave_domain_done(struct tevent_req *subreq)
struct sysdb_attrs **subdoms;
size_t nsubdoms;
bool has_changes;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
@@ -1252,17 +1245,14 @@ static void ad_get_slave_domain_done(struct tevent_req *subreq)
/* We continue to finish sdap_id_op. */
}
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ ret = sdap_id_op_done(state->sdap_op, ret);
+ if (ret != EOK) {
/* retry */
ret = ad_get_slave_domain_retry(req);
if (ret != EOK) {
goto done;
}
return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- ret = ERR_OFFLINE;
- goto done;
} else if (ret != EOK) {
goto done;
}
@@ -2034,23 +2024,17 @@ static void ad_subdomains_refresh_connect_done(struct tevent_req *subreq)
{
struct ad_subdomains_refresh_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_subdomains_refresh_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
"[%d]: %s\n", ret, sss_strerror(ret));
- if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
- "cannot get the subdomain list while offline\n");
- ret = ERR_OFFLINE;
- }
tevent_req_error(req, ret);
return;
}
@@ -2262,7 +2246,6 @@ static void ad_subdomains_refresh_root_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_id_ctx *root_id_ctx;
struct sysdb_attrs *root_attrs;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
@@ -2283,17 +2266,14 @@ static void ad_subdomains_refresh_root_done(struct tevent_req *subreq)
/* We finish sdap_id_op here since we connect
* to forest root for slave domains. */
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ ret = sdap_id_op_done(state->sdap_op, ret);
+ if (ret != EOK) {
/* retry */
ret = ad_subdomains_refresh_retry(req);
if (ret != EOK) {
tevent_req_error(req, ret);
}
return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- tevent_req_error(req, ERR_OFFLINE);
- return;
} else if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -2385,7 +2365,7 @@ ad_subdomains_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -2407,7 +2387,7 @@ static void ad_subdomains_handler_done(struct tevent_req *subreq)
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
@@ -2671,22 +2651,16 @@ static void ad_check_domain_connect_done(struct tevent_req *subreq)
struct tevent_req *req;
struct ad_check_domain_state *state;
int ret;
- int dp_error;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ad_check_domain_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
"[%d]: %s\n", ret, sss_strerror(ret));
- if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_MINOR_FAILURE, "No AD server is available, "
- "cannot get the subdomain list while offline\n");
- ret = ERR_OFFLINE;
- }
tevent_req_error(req, ret);
return;
}
diff --git a/src/providers/backend.h b/src/providers/backend.h
index fc13942bcbc..618e865ab06 100644
--- a/src/providers/backend.h
+++ b/src/providers/backend.h
@@ -114,7 +114,7 @@ struct be_ctx {
struct sbus_connection *conn;
/* Indicates whether the last state of the DP that has been logged is
- * DP_ERR_OK or DP_ERR_OFFLINE. The only usage of this var, so far, is
+ * EOK or ERR_OFFLINE. The only usage of this var, so far, is
* to log the DP status without spamming the syslog/journal. */
int last_dp_state;
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h
index 7509fb9566a..89aad995207 100644
--- a/src/providers/data_provider.h
+++ b/src/providers/data_provider.h
@@ -110,12 +110,6 @@
* @}
*/ /* end of group pamHandler */
-#define DP_ERR_DECIDE -1
-#define DP_ERR_OK 0
-#define DP_ERR_OFFLINE 1
-#define DP_ERR_TIMEOUT 2
-#define DP_ERR_FATAL 3
-
#define BE_FILTER_NAME 1
#define BE_FILTER_IDNUM 2
#define BE_FILTER_ENUM 3
diff --git a/src/providers/data_provider/dp_custom_data.h b/src/providers/data_provider/dp_custom_data.h
index 1ca85f70632..407f3e85468 100644
--- a/src/providers/data_provider/dp_custom_data.h
+++ b/src/providers/data_provider/dp_custom_data.h
@@ -66,23 +66,21 @@ struct dp_resolver_data {
/* Reply private data. */
struct dp_reply_std {
- int dp_error;
int error;
const char *message;
};
void dp_reply_std_set(struct dp_reply_std *reply,
- int dp_error,
int error,
const char *msg);
+void dp_req_reply_std_with_msg(const char *request_name,
+ struct dp_reply_std *reply,
+ uint32_t *_error,
+ const char **_message);
+
void dp_req_reply_std(const char *request_name,
struct dp_reply_std *reply,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_message);
-
-/* Convert pair of ret and dp_error to single ret value. */
-errno_t dp_error_to_ret(errno_t ret, int dp_error);
+ uint32_t *_error);
#endif /* _DP_CUSTOM_DATA_H_ */
diff --git a/src/providers/data_provider/dp_iface.h b/src/providers/data_provider/dp_iface.h
index 87e0687045f..c2fc2a0c8dd 100644
--- a/src/providers/data_provider/dp_iface.h
+++ b/src/providers/data_provider/dp_iface.h
@@ -40,9 +40,7 @@ dp_get_account_info_send(TALLOC_CTX *mem_ctx,
errno_t
dp_get_account_info_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg);
+ uint32_t *_error);
struct tevent_req *
dp_pam_handler_send(TALLOC_CTX *mem_ctx,
@@ -66,9 +64,7 @@ dp_sudo_handler_send(TALLOC_CTX *mem_ctx,
errno_t
dp_sudo_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg);
+ uint32_t *_error);
struct tevent_req *
dp_host_handler_send(TALLOC_CTX *mem_ctx,
@@ -83,9 +79,7 @@ dp_host_handler_send(TALLOC_CTX *mem_ctx,
errno_t
dp_host_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg);
+ uint32_t *_error);
struct tevent_req *
dp_autofs_handler_send(TALLOC_CTX *mem_ctx,
@@ -98,9 +92,7 @@ dp_autofs_handler_send(TALLOC_CTX *mem_ctx,
errno_t
dp_autofs_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg);
+ uint32_t *_error);
struct tevent_req *
dp_autofs_get_map_send(TALLOC_CTX *mem_ctx,
@@ -146,9 +138,7 @@ dp_subdomains_handler_send(TALLOC_CTX *mem_ctx,
errno_t
dp_subdomains_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg);
+ uint32_t *_error);
struct tevent_req *
dp_resolver_handler_send(TALLOC_CTX *mem_ctx,
@@ -164,20 +154,18 @@ dp_resolver_handler_send(TALLOC_CTX *mem_ctx,
errno_t
dp_resolver_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg);
+ uint32_t *_error);
/*
* Return a domain the account belongs to.
*
* The request uses the dp_reply_std structure for reply, with the following
* semantics:
- * - DP_ERR_OK - it is expected that the string message contains the domain name
+ * - ERR_OK - it is expected that the string message contains the domain name
* the entry was found in. A 'negative' reply where the
- * request returns DP_ERR_OK, but no domain should be treated
+ * request returns ERR_OK, but no domain should be treated
* as authoritative, as if the entry does not exist.
- * - DP_ERR_* - the string message contains error string that corresponds
+ * - ERR_* - the string message contains error string that corresponds
* to the errno field in dp_reply_std().
*/
struct tevent_req *
@@ -193,7 +181,6 @@ dp_get_account_domain_send(TALLOC_CTX *mem_ctx,
errno_t
dp_get_account_domain_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
uint32_t *_error,
const char **_err_msg);
diff --git a/src/providers/data_provider/dp_reply_std.c b/src/providers/data_provider/dp_reply_std.c
index 74e8e044e19..201f6547048 100644
--- a/src/providers/data_provider/dp_reply_std.c
+++ b/src/providers/data_provider/dp_reply_std.c
@@ -25,32 +25,17 @@
#include "util/sss_utf8.h"
#include "util/util.h"
-static const char *dp_err_to_string(int dp_err_type)
-{
- switch (dp_err_type) {
- case DP_ERR_OK:
- return "Success";
- case DP_ERR_OFFLINE:
- return "Provider is Offline";
- case DP_ERR_TIMEOUT:
- return "Request timed out";
- case DP_ERR_FATAL:
- return "Internal Error";
- default:
- break;
- }
-
- return "Unknown Error";
-}
-
static const char *safe_be_req_err_msg(const char *msg_in,
- int dp_err_type)
+ int error)
{
bool ok;
+ const char *def_msg;
+
+ def_msg = sss_strerror(error);
if (msg_in == NULL) {
/* No custom error, just use default */
- return dp_err_to_string(dp_err_type);
+ return def_msg;
}
ok = sss_utf8_check((const uint8_t *) msg_in,
@@ -59,7 +44,7 @@ static const char *safe_be_req_err_msg(const char *msg_in,
DEBUG(SSSDBG_MINOR_FAILURE,
"Back end message [%s] contains invalid non-UTF8 character, " \
"using default\n", msg_in);
- return dp_err_to_string(dp_err_type);
+ return def_msg;
}
return msg_in;
@@ -67,84 +52,43 @@ static const char *safe_be_req_err_msg(const char *msg_in,
void dp_req_reply_std(const char *request_name,
struct dp_reply_std *reply,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_message)
+ uint32_t *_error)
+{
+ const char *msg;
+
+ msg = sss_strerror(*_error);
+
+ DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name, "Returning [%d]: %s",
+ *_error, msg);
+
+ *_error = reply->error;
+ msg = reply->message;
+}
+
+void dp_req_reply_std_with_msg(const char *request_name,
+ struct dp_reply_std *reply,
+ uint32_t *_error,
+ const char **_message)
{
const char *safe_err_msg;
- safe_err_msg = safe_be_req_err_msg(reply->message, reply->dp_error);
+ safe_err_msg = safe_be_req_err_msg(reply->message, reply->error);
- DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name, "Returning [%s]: %d,%d,%s",
- dp_err_to_string(reply->dp_error), reply->dp_error,
+ DP_REQ_DEBUG(SSSDBG_TRACE_LIBS, request_name, "Returning [%d]: %s",
reply->error, reply->message);
- *_dp_error = reply->dp_error;
*_error = reply->error;
*_message = safe_err_msg;
}
void dp_reply_std_set(struct dp_reply_std *reply,
- int dp_error,
int error,
const char *msg)
{
const char *def_msg;
- if (dp_error == DP_ERR_DECIDE) {
- switch (error) {
- case EOK:
- dp_error = DP_ERR_OK;
- break;
- case ERR_OFFLINE:
- dp_error = DP_ERR_OFFLINE;
- break;
- case ETIMEDOUT:
- dp_error = DP_ERR_TIMEOUT;
- break;
- default:
- dp_error = DP_ERR_FATAL;
- break;
- }
- }
-
- switch (dp_error) {
- case DP_ERR_OK:
- def_msg = "Success";
- break;
- case DP_ERR_OFFLINE:
- def_msg = "Offline";
- break;
- default:
- def_msg = sss_strerror(error);
- break;
- }
+ def_msg = sss_strerror(error);
- if (dp_error == DP_ERR_OK && error != EOK) {
- DEBUG(SSSDBG_MINOR_FAILURE, "DP Error is OK on failed request?\n");
- }
-
- reply->dp_error = dp_error;
reply->error = error;
reply->message = msg == NULL ? def_msg : msg;
}
-
-errno_t dp_error_to_ret(errno_t ret, int dp_error)
-{
- if (ret != EOK) {
- return ret;
- }
-
- switch (dp_error) {
- case DP_ERR_OK:
- return EOK;
- case DP_ERR_OFFLINE:
- return ERR_OFFLINE;
- case DP_ERR_TIMEOUT:
- return ETIMEDOUT;
- case DP_ERR_FATAL:
- return EFAULT;
- }
-
- return ERR_INTERNAL;
-}
diff --git a/src/providers/data_provider/dp_target_hostid.c b/src/providers/data_provider/dp_target_hostid.c
index ea8f29014bc..f7441e06c32 100644
--- a/src/providers/data_provider/dp_target_hostid.c
+++ b/src/providers/data_provider/dp_target_hostid.c
@@ -110,9 +110,7 @@ static void dp_host_handler_done(struct tevent_req *subreq)
errno_t
dp_host_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg)
+ uint32_t *_error)
{
struct dp_host_handler_state *state;
state = tevent_req_data(req, struct dp_host_handler_state);
@@ -120,7 +118,7 @@ dp_host_handler_recv(TALLOC_CTX *mem_ctx,
TEVENT_REQ_RETURN_ON_ERROR(req);
dp_req_reply_std(state->request_name, &state->reply,
- _dp_error, _error, _err_msg);
+ _error);
return EOK;
}
diff --git a/src/providers/data_provider/dp_target_id.c b/src/providers/data_provider/dp_target_id.c
index 83641c3cae2..a25e19655bb 100644
--- a/src/providers/data_provider/dp_target_id.c
+++ b/src/providers/data_provider/dp_target_id.c
@@ -434,7 +434,7 @@ static void dp_req_initgr_pp_set_initgr_timestamp(struct dp_initgr_ctx *ctx,
{
errno_t ret;
- if (reply->dp_error != DP_ERR_OK || reply->error != EOK) {
+ if (reply->error != EOK) {
/* Only bump the timestamp on successful lookups */
return;
}
@@ -887,17 +887,14 @@ static void dp_get_account_info_done(struct tevent_req *subreq)
errno_t
dp_get_account_info_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg)
+ uint32_t *_error)
{
struct dp_get_account_info_state *state;
state = tevent_req_data(req, struct dp_get_account_info_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- dp_req_reply_std(state->request_name, &state->reply,
- _dp_error, _error, _err_msg);
+ dp_req_reply_std(state->request_name, &state->reply, _error);
return EOK;
}
@@ -1025,7 +1022,6 @@ static void dp_get_account_domain_done(struct tevent_req *subreq)
errno_t
dp_get_account_domain_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
uint32_t *_error,
const char **_err_msg)
{
@@ -1034,8 +1030,8 @@ dp_get_account_domain_recv(TALLOC_CTX *mem_ctx,
TEVENT_REQ_RETURN_ON_ERROR(req);
- dp_req_reply_std(state->request_name, &state->reply,
- _dp_error, _error, _err_msg);
+ dp_req_reply_std_with_msg(state->request_name, &state->reply, _error,
+ _err_msg);
return EOK;
}
@@ -1061,7 +1057,7 @@ default_account_domain_send(TALLOC_CTX *mem_ctx,
}
dp_reply_std_set(&state->reply,
- DP_ERR_DECIDE, ERR_GET_ACCT_DOM_NOT_SUPPORTED,
+ ERR_GET_ACCT_DOM_NOT_SUPPORTED,
NULL);
tevent_req_done(req);
tevent_req_post(req, params->ev);
diff --git a/src/providers/data_provider/dp_target_resolver.c b/src/providers/data_provider/dp_target_resolver.c
index 7dd24d3119c..6f759efdc98 100644
--- a/src/providers/data_provider/dp_target_resolver.c
+++ b/src/providers/data_provider/dp_target_resolver.c
@@ -132,17 +132,14 @@ static void dp_resolver_handler_done(struct tevent_req *subreq)
errno_t
dp_resolver_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg)
+ uint32_t *_error)
{
struct dp_resolver_handler_state *state;
state = tevent_req_data(req, struct dp_resolver_handler_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- dp_req_reply_std(state->request_name, &state->reply,
- _dp_error, _error, _err_msg);
+ dp_req_reply_std(state->request_name, &state->reply, _error);
return EOK;
}
diff --git a/src/providers/data_provider/dp_target_subdomains.c b/src/providers/data_provider/dp_target_subdomains.c
index e405d8c9a05..6411311e2af 100644
--- a/src/providers/data_provider/dp_target_subdomains.c
+++ b/src/providers/data_provider/dp_target_subdomains.c
@@ -106,17 +106,14 @@ static void dp_subdomains_handler_done(struct tevent_req *subreq)
errno_t
dp_subdomains_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg)
+ uint32_t *_error)
{
struct dp_subdomains_handler_state *state;
state = tevent_req_data(req, struct dp_subdomains_handler_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- dp_req_reply_std(state->request_name, &state->reply,
- _dp_error, _error, _err_msg);
+ dp_req_reply_std(state->request_name, &state->reply, _error);
return EOK;
}
diff --git a/src/providers/data_provider/dp_target_sudo.c b/src/providers/data_provider/dp_target_sudo.c
index f90589f6677..dbf9a7f3301 100644
--- a/src/providers/data_provider/dp_target_sudo.c
+++ b/src/providers/data_provider/dp_target_sudo.c
@@ -189,17 +189,14 @@ static void dp_sudo_handler_done(struct tevent_req *subreq)
errno_t
dp_sudo_handler_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_err_msg)
+ uint32_t *_error)
{
struct dp_sudo_handler_state *state;
state = tevent_req_data(req, struct dp_sudo_handler_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- dp_req_reply_std(state->request_name, &state->reply,
- _dp_error, _error, _err_msg);
+ dp_req_reply_std(state->request_name, &state->reply, _error);
return EOK;
}
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index a01f83531c3..fc981b74044 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -343,30 +343,30 @@ static void be_check_online_done(struct tevent_req *req)
goto done;
}
- switch (reply->dp_error) {
- case DP_ERR_OK:
- if (be_ctx->last_dp_state != DP_ERR_OK) {
- be_ctx->last_dp_state = DP_ERR_OK;
+ switch (reply->error) {
+ case EOK:
+ if (be_ctx->last_dp_state != EOK) {
+ be_ctx->last_dp_state = EOK;
sss_log(SSS_LOG_INFO, "Backend is online\n");
}
DEBUG(SSSDBG_TRACE_FUNC, "Backend is online\n");
break;
- case DP_ERR_OFFLINE:
- if (be_ctx->last_dp_state != DP_ERR_OFFLINE) {
- be_ctx->last_dp_state = DP_ERR_OFFLINE;
+ case ERR_OFFLINE:
+ if (be_ctx->last_dp_state != ERR_OFFLINE) {
+ be_ctx->last_dp_state = ERR_OFFLINE;
sss_log(SSS_LOG_INFO, "Backend is offline\n");
}
DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline\n");
break;
default:
DEBUG(SSSDBG_TRACE_FUNC, "Error during online check [%d]: %s\n",
- ret, sss_strerror(ret));
+ reply->error, sss_strerror(reply->error));
break;
}
be_ctx->check_online_ref_count--;
- if (reply->dp_error != DP_ERR_OK && be_ctx->check_online_ref_count > 0) {
+ if (reply->error != EOK && be_ctx->check_online_ref_count > 0) {
be_ctx->check_online_retry_delay *= 2;
if (be_ctx->check_online_retry_delay > ONLINE_CB_RETRY_MAX_DELAY) {
be_ctx->check_online_retry_delay = ONLINE_CB_RETRY_MAX_DELAY;
@@ -390,8 +390,8 @@ static void be_check_online_done(struct tevent_req *req)
done:
be_ctx->check_online_ref_count = 0;
- if (reply && reply->dp_error != DP_ERR_OFFLINE) {
- if (reply->dp_error != DP_ERR_OK) {
+ if (reply && reply->error != ERR_OFFLINE) {
+ if (reply->error != EOK) {
reset_fo(be_ctx);
}
be_reset_offline(be_ctx);
diff --git a/src/providers/failover/failover.c b/src/providers/failover/failover.c
new file mode 100644
index 00000000000..c42d9c81cba
--- /dev/null
+++ b/src/providers/failover/failover.c
@@ -0,0 +1,214 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_group.h"
+#include "util/util.h"
+#include "util/sss_ptr_list.h"
+
+static struct sss_failover_candidates_ctx *
+sss_failover_candidates_init(TALLOC_CTX *mem_ctx,
+ unsigned int max_servers,
+ unsigned int min_refresh_time)
+{
+ struct sss_failover_candidates_ctx *ctx;
+ errno_t ret;
+
+ ctx = talloc_zero(mem_ctx, struct sss_failover_candidates_ctx);
+ if (ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return NULL;
+ }
+
+ ctx->refresh_req = NULL;
+ ctx->last_refresh_time = 0;
+ ctx->min_refresh_time = min_refresh_time;
+
+ /* Setup list of candidate servers. */
+ ctx->servers = talloc_zero_array(ctx, struct sss_failover_server *,
+ max_servers + 1);
+ if (ctx->servers == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ctx->notify_queue = tevent_queue_create(ctx, "candidates_notify_queue");
+ if (ctx->notify_queue == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Stop the queue. It will be started when candidates are refreshed. */
+ tevent_queue_stop(ctx->notify_queue);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(ctx);
+ return NULL;
+ }
+
+ return ctx;
+}
+
+static int
+sss_failover_destructor(struct sss_failover_ctx *fctx)
+{
+ return 0;
+}
+
+struct sss_failover_ctx *
+sss_failover_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *name,
+ struct resolv_ctx *resolver_ctx,
+ enum restrict_family family_order)
+{
+ struct sss_failover_ctx *fctx;
+ errno_t ret;
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Creating failover context for service %s\n",
+ name);
+
+ fctx = talloc_zero(mem_ctx, struct sss_failover_ctx);
+ if (fctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return NULL;
+ }
+
+ /* TODO init */
+ fctx->ev = ev;
+ fctx->name = talloc_strdup(fctx, name);
+ fctx->resolver_ctx = resolver_ctx;
+ fctx->family_order = family_order;
+ fctx->kinit_ctx = NULL;
+
+ if (fctx->name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Configuration. TODO make it configurable. */
+ fctx->opts.max_candidates = 5;
+ fctx->opts.min_refresh_time = 60;
+ fctx->opts.ping_timeout = 3;
+ fctx->opts.negative_dns_srv_ttl = 3600;
+ fctx->opts.min_candidates_lookup_time = 1;
+
+ /* Setup server groups. We expect at least two groups: primary and backup */
+ fctx->current_group = 0;
+ fctx->groups = talloc_zero_array(fctx, struct sss_failover_group *, 3);
+ if (fctx->groups == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Setup list of candidate servers. */
+ fctx->candidates = sss_failover_candidates_init(
+ fctx, fctx->opts.max_candidates, fctx->opts.min_refresh_time);
+ if (fctx->candidates == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* We are not connected to any server yet. */
+ fctx->active_server = NULL;
+
+ fctx->vtable = talloc_zero(fctx, struct sss_failover_vtable);
+ if (fctx->vtable == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ fctx->vtable_op_queue = tevent_queue_create(fctx, "vtable_op_queue");
+ if (fctx->vtable_op_queue == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ talloc_set_destructor(fctx, sss_failover_destructor);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_zfree(fctx);
+ }
+
+ return fctx;
+}
+
+void
+sss_failover_set_active_server(struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server)
+{
+ if (fctx->active_server != NULL) {
+ if (server == fctx->active_server) {
+ /* it is the same server, nothing to do */
+ return;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Releasing old active server %s\n",
+ fctx->active_server->name);
+
+ talloc_unlink(fctx, fctx->active_server);
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Setting new active server %s\n", server->name);
+ fctx->active_server = talloc_reference(fctx, server);
+}
+
+void
+sss_failover_set_connection(struct sss_failover_ctx *fctx, void *connection)
+{
+ if (fctx->connection != NULL) {
+ if (connection == fctx->connection) {
+ /* it is the same connection, nothing to do */
+ return;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Releasing old connection %p\n",
+ fctx->connection);
+
+ talloc_unlink(fctx, fctx->connection);
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Setting new connection %p\n", connection);
+ fctx->connection = talloc_steal(fctx, connection);
+}
+
+void *
+sss_failover_get_connection(TALLOC_CTX *mem_ctx, struct sss_failover_ctx *fctx)
+{
+ if (fctx->connection == NULL) {
+ return NULL;
+ }
+
+ return talloc_reference(mem_ctx, fctx->connection);
+}
diff --git a/src/providers/failover/failover.h b/src/providers/failover/failover.h
new file mode 100644
index 00000000000..91d34b2610b
--- /dev/null
+++ b/src/providers/failover/failover.h
@@ -0,0 +1,151 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_H_
+#define _FAILOVER_H_
+
+#include
+#include
+
+#include "config.h"
+#include "resolv/async_resolv.h"
+#include "providers/failover/failover_server.h"
+#include "providers/failover/failover_group.h"
+#include "providers/failover/failover_vtable.h"
+#include "util/util.h"
+
+struct sss_failover_candidates_ctx {
+ /* List of servers that were found as working. */
+ struct sss_failover_server **servers;
+
+ /* Active refresh request. NULL if there is no ongoing refresh. */
+ struct tevent_req *refresh_req;
+
+ /* This queue serves as a notification mechanism. It is started when
+ * candidates list were refreshed and is stopped when the list is being
+ * refreshed.
+ */
+ struct tevent_queue *notify_queue;
+
+ /* Last refresh time. */
+ unsigned int last_refresh_time;
+
+ /* Do not issue new refresh if now < last_refresh_time + min_refresh_time */
+ unsigned int min_refresh_time;
+};
+
+struct sss_failover_options {
+ /* Maximum number of candidate servers. */
+ unsigned int max_candidates;
+
+ /* Minimum time that has to elapse before refreshing candidates again. */
+ unsigned int min_refresh_time;
+
+ /* Minimum amount of time that will wait for candidates servers to respond
+ to a ping. If any server is found within this time, we do not wait for other
+ servers to respond and return what we have. */
+ unsigned int min_candidates_lookup_time;
+
+ /* How long do we want to wait for a server ping to succeed. */
+ unsigned int ping_timeout;
+
+ /* TTL for missing DNS SRV records. */
+ unsigned int negative_dns_srv_ttl;
+};
+
+struct sss_failover_ctx {
+ struct tevent_context *ev;
+ char *name;
+ struct resolv_ctx *resolver_ctx;
+ struct sss_failover_vtable *vtable;
+ enum restrict_family family_order;
+
+ struct sss_failover_options opts;
+
+ /* NULL-terminated list of failover server groups. The first group has the
+ * highest priority. */
+ struct sss_failover_group **groups;
+
+ /* Currently selected group that provided server candidates. */
+ unsigned int current_group;
+
+ /* Non-NULL if kinit is required to connect to the server. The context may
+ * be the same to make sure the same server is used for KDC and connection
+ * or different. */
+ struct sss_failover_ctx *kinit_ctx;
+
+ /* Candidate servers. */
+ struct sss_failover_candidates_ctx *candidates;
+
+ /* Currently active server. */
+ struct sss_failover_server *active_server;
+
+ /* Backend specific established connection. */
+ void *connection;
+
+ /* Queue of sss_vtable_op tevent requests. These requests are used to
+ * connect to the server and the queue serializes the requests to ensure
+ * that we establish only one connection that is then reused. */
+ struct tevent_queue *vtable_op_queue;
+};
+
+/**
+ * @brief Initialize failover context.
+ *
+ * @param mem_ctx
+ * @param ev
+ * @param resolver_ctx
+ * @param family_order
+ * @return struct sss_failover_ctx*
+ */
+struct sss_failover_ctx *
+sss_failover_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *name,
+ struct resolv_ctx *resolver_ctx,
+ enum restrict_family family_order);
+
+/**
+ * @brief Set active server.
+ *
+ * This is a noop if @server and @fctx->active_server is identical.
+ */
+void
+sss_failover_set_active_server(struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server);
+
+/**
+ * @brief Set new connection, release old one.
+ *
+ * This is a noop if @connection and @fctx->connection is identical.
+ */
+void
+sss_failover_set_connection(struct sss_failover_ctx *fctx, void *connection);
+
+/**
+ * @brief Get connection.
+ *
+ * The connection is talloc_reference to mem_ctx.
+ *
+ * @param mem_ctx
+ * @param fctx
+ * @return void*
+ */
+void *
+sss_failover_get_connection(TALLOC_CTX *mem_ctx, struct sss_failover_ctx *fctx);
+
+#endif /* _FAILOVER_H_ */
diff --git a/src/providers/failover/failover_callback.c b/src/providers/failover/failover_callback.c
new file mode 100644
index 00000000000..1d43351bbee
--- /dev/null
+++ b/src/providers/failover/failover_callback.c
@@ -0,0 +1,22 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "util/util.h"
diff --git a/src/providers/failover/failover_group.c b/src/providers/failover/failover_group.c
new file mode 100644
index 00000000000..ef38044e86e
--- /dev/null
+++ b/src/providers/failover/failover_group.c
@@ -0,0 +1,383 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#include "config.h"
+#include "providers/failover/failover_group.h"
+#include "providers/failover/failover_server.h"
+#include "providers/failover/failover_srv.h"
+#include "providers/failover/failover.h"
+#include "util/util.h"
+
+static errno_t
+sss_failover_group_allocate_slot(struct sss_failover_ctx *fctx,
+ unsigned int *_slot)
+{
+ size_t count;
+ unsigned int slot;
+
+ count = talloc_array_length(fctx->groups);
+
+ for (slot = 0; fctx->groups[slot] != NULL && slot < count; slot++) {
+ /* Find the first NULL slot. slot < count is just for safety */
+ }
+
+ /* We need to allocate more items? */
+ if (slot >= count - 1) {
+ fctx->groups = talloc_realloc(fctx, fctx->groups,
+ struct sss_failover_group *, count + 1);
+ if (fctx->groups == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ fctx->groups[count] = NULL;
+ fctx->groups[count - 1] = NULL;
+ slot = count - 1;
+ }
+
+ *_slot = slot;
+
+ return EOK;
+}
+
+struct sss_failover_group *
+sss_failover_group_new(struct sss_failover_ctx *fctx,
+ const char *name)
+{
+ struct sss_failover_group *group;
+ unsigned int slot;
+ errno_t ret;
+
+ if (name == NULL || fctx == NULL || fctx->groups == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid parameters!\n");
+ return NULL;
+ }
+
+ ret = sss_failover_group_allocate_slot(fctx, &slot);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to allocate slot [%d]: %s\n", ret,
+ sss_strerror(ret));
+ return NULL;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Creating failover group %s:%u\n", name, slot);
+
+ group = talloc_zero(fctx->groups, struct sss_failover_group);
+ if (group == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return NULL;
+ }
+
+ group->name = talloc_strdup(group, name);
+ if (group->name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ group->slot = slot;
+
+ group->configured_servers = talloc_zero_array(group, struct sss_failover_server *, 1);
+ if (group->configured_servers == NULL) {
+ ret = ENOMEM;
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ goto done;
+ }
+
+ group->dns_discovery_enabled = false;
+ group->discovered_servers = talloc_zero_array(group, struct sss_failover_server *, 1);
+ if (group->discovered_servers == NULL) {
+ ret = ENOMEM;
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ goto done;
+ }
+
+ group->servers = talloc_zero_array(group, struct sss_failover_server *, 1);
+ if (group->servers == NULL) {
+ ret = ENOMEM;
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ goto done;
+ }
+
+ fctx->groups[slot] = group;
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(group);
+ return NULL;
+ }
+
+ return group;
+}
+
+errno_t
+sss_failover_group_setup_dns_discovery(struct sss_failover_group *group)
+{
+ group->dns_discovery_enabled = true;
+
+ return EOK;
+}
+
+errno_t
+sss_failover_group_add_server(struct sss_failover_group *group,
+ struct sss_failover_server *server)
+{
+ struct sss_failover_server **new_array;
+ size_t count;
+
+ if (group == NULL || group->configured_servers == NULL || server == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid arguments\n");
+ return EINVAL;
+ }
+
+ count = talloc_array_length(group->configured_servers);
+
+ new_array = talloc_realloc(group, group->configured_servers,
+ struct sss_failover_server *, count + 1);
+ if (new_array == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ group->configured_servers = new_array;
+ group->configured_servers[count - 1] = talloc_steal(group->configured_servers, server);
+ group->configured_servers[count] = NULL;
+
+ return EOK;
+}
+
+struct sss_failover_group_resolve_state {
+ struct sss_failover_ctx *fctx;
+ struct sss_failover_group *group;
+};
+
+static void sss_failover_group_resolve_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sss_failover_group_resolve_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_group *group)
+{
+ struct sss_failover_group_resolve_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+ time_t now;
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Resolving server group %s:%d\n", group->name,
+ group->slot);
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_group_resolve_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->fctx = fctx;
+ state->group = group;
+
+ now = time(NULL);
+ if (group->dns_discovery_enabled && group->dns_expiration_time < now) {
+ /* Refresh SRV records. */
+ const char *domains[] = {"ldap.test", NULL};
+ const char *protocol = "tcp";
+ const char *service = "ldap";
+
+ // TODO handle protocol, service, domains and plugin
+ subreq = sss_failover_srv_resolve_send(state, ev, fctx, service,
+ protocol, domains);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_group_resolve_done, req);
+
+ ret = EAGAIN;
+ } else {
+ /* We have what we need. */
+ ret = EOK;
+ }
+
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ tevent_req_post(req, ev);
+ } else if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void sss_failover_group_resolve_done(struct tevent_req *subreq)
+{
+ struct sss_failover_group_resolve_state *state;
+ struct sss_failover_server **servers;
+ struct tevent_req *req;
+ uint32_t ttl;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_group_resolve_state);
+
+ ret = sss_failover_srv_resolve_recv(state, subreq, &ttl,
+ &servers);
+ talloc_zfree(subreq);
+ if (ret == ENOENT) {
+ ttl = state->fctx->opts.negative_dns_srv_ttl;
+ servers = talloc_zero_array(state, struct sss_failover_server *, 1);
+ if (servers == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ ret = EOK;
+ } else if (ret != EOK) {
+ goto done;
+ }
+
+ talloc_zfree(state->group->discovered_servers);
+ state->group->discovered_servers = talloc_steal(state->group, servers);
+ state->group->dns_expiration_time = time(NULL) + ttl;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+sss_failover_group_resolve_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server ***_servers)
+{
+ struct sss_failover_group_resolve_state *state;
+ struct sss_failover_server *current;
+ struct sss_failover_server **out;
+ size_t count_conf;
+ size_t count_dns;
+ size_t count;
+ int i, j, k;
+ bool found;
+
+ state = tevent_req_data(req, struct sss_failover_group_resolve_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ count_conf = talloc_array_length(state->group->configured_servers) - 1;
+ count_dns = talloc_array_length(state->group->discovered_servers) - 1;
+ count = count_conf + count_dns;
+
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "There are %zu configured servers inside group %d:%s:\n",
+ count_conf, state->group->slot, state->group->name);
+
+ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
+ for (i = 0; state->group->configured_servers[i] != NULL; i++) {
+ current = state->group->configured_servers[i];
+ DEBUG(SSSDBG_TRACE_ALL, "- %s:%u\n", current->name, current->port);
+ }
+ }
+
+ if (state->group->dns_discovery_enabled) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Discovered %zu servers from DNS inside group %d:%s:\n",
+ count_dns, state->group->slot, state->group->name);
+
+ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
+ for (i = 0; state->group->discovered_servers[i] != NULL; i++) {
+ current = state->group->discovered_servers[i];
+ DEBUG(SSSDBG_TRACE_ALL, "- %s:%u\n", current->name,
+ current->port);
+ }
+ }
+ }
+
+ out = talloc_zero_array(mem_ctx, struct sss_failover_server *, count + 1);
+ if (out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ /* Add configured servers first. */
+ for (i = 0; state->group->configured_servers[i] != NULL; i++) {
+ out[i] = talloc_reference(out, state->group->configured_servers[i]);
+ if (out[i] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ talloc_free(out);
+ return ENOMEM;
+ }
+ }
+
+ /* Now add discovered servers. But avoid adding duplicates. */
+ for (j = 0; state->group->discovered_servers[j] != NULL; j++, i++) {
+ found = false;
+ current = state->group->discovered_servers[j];
+ for (k = 0; out[k] != NULL; k++) {
+ if (sss_failover_server_equal(out[k], current)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ break;
+ }
+
+ out[i] = talloc_reference(out, current);
+ if (out[i] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ talloc_free(out);
+ return ENOMEM;
+ }
+ }
+
+
+ // TODO sort by priority and weight
+
+ for (count = 0; out[count] != NULL; count++);
+ out = talloc_realloc(mem_ctx, out, struct sss_failover_server *, count + 1);
+ if (out == NULL) {
+ talloc_free(out);
+ return ENOMEM;
+ }
+
+ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
+ DEBUG(SSSDBG_TRACE_ALL, "Sorted server list without duplicates:\n");
+ for (i = 0; out[i] != NULL; i++) {
+ DEBUG(SSSDBG_TRACE_ALL, "- %s:%u\n", out[i]->name, out[i]->port);
+ }
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Returning %zu servers from group %d:%s\n", count,
+ state->group->slot, state->group->name);
+
+ *_servers = out;
+
+ return EOK;
+}
diff --git a/src/providers/failover/failover_group.h b/src/providers/failover/failover_group.h
new file mode 100644
index 00000000000..0527109d6e6
--- /dev/null
+++ b/src/providers/failover/failover_group.h
@@ -0,0 +1,116 @@
+;/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_GROUP_H_
+#define _FAILOVER_GROUP_H_
+
+#include
+
+#include "config.h"
+#include "util/util.h"
+#include "providers/failover/failover_server.h"
+
+struct sss_failover_ctx;
+
+struct sss_failover_group {
+ struct sss_failover_ctx *fctx;
+
+ /* Group name. */
+ char *name;
+
+ /* Priority. 0 = highest priority (primary servers). */
+ unsigned int slot;
+
+ /* DNS SRV plugin information */
+ bool dns_discovery_enabled;
+ time_t dns_expiration_time;
+ void *dns_plugin_data;
+ void *dns_plugin;
+
+ /* Configured or discovered servers. */
+ struct sss_failover_server **configured_servers;
+ struct sss_failover_server **discovered_servers;
+
+ /* Servers inside this group. Sorted by priority and weight. */
+ struct sss_failover_server **servers;
+};
+
+/**
+ * @brief Create new server group @name.
+ *
+ * Add new static servers to it with @sss_failover_server_group_add_server.
+ *
+ * @param fctx
+ * @param name
+ * @return struct sss_failover_group*
+ */
+struct sss_failover_group *
+sss_failover_group_new(struct sss_failover_ctx *fctx,
+ const char *name);
+
+/**
+ * @brief Enable DNS discovery within this group.
+ *
+ * @param group
+ * @return errno_t
+ */
+errno_t
+sss_failover_group_setup_dns_discovery(struct sss_failover_group *group);
+
+/**
+ * @brief Add new server to the failover group.
+ *
+ * @param group
+ * @param server
+ * @return errno_t
+ */
+errno_t
+sss_failover_group_add_server(struct sss_failover_group *group,
+ struct sss_failover_server *server);
+
+/**
+ * @brief Resolve servers within this group.
+ *
+ * It does not resolve servers to IP address, it resolves the DNS SRV record
+ * (if required) and combine SRV servers with those statically configured.
+ *
+ * @param mem_ctx
+ * @param ev
+ * @param fctx
+ * @param group
+ * @return struct tevent_req*
+ */
+struct tevent_req *
+sss_failover_group_resolve_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_group *group);
+
+/**
+ * @brief Return list of servers within this group.
+ *
+ * @param mem_ctx
+ * @param req
+ * @param _servers
+ * @return errno_t
+ */
+errno_t
+sss_failover_group_resolve_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server ***_servers);
+
+#endif /* _FAILOVER_GROUP_H_ */
diff --git a/src/providers/failover/failover_refresh_candidates.c b/src/providers/failover/failover_refresh_candidates.c
new file mode 100644
index 00000000000..d8a12bff96c
--- /dev/null
+++ b/src/providers/failover/failover_refresh_candidates.c
@@ -0,0 +1,766 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+
+#include "config.h"
+#include "util/util.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_group.h"
+#include "providers/failover/failover_refresh_candidates.h"
+#include "providers/failover/failover_server_resolve.h"
+#include "util/sss_sockets.h"
+
+struct sss_failover_ping_state {
+ struct tevent_context *ev;
+ struct sss_failover_ctx *fctx;
+ struct sss_failover_server *server;
+ unsigned int timeout;
+
+ struct timeval ping_start;
+};
+
+static void
+sss_failover_ping_resolved(struct tevent_req *subreq);
+
+static void
+sss_failover_ping_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+sss_failover_ping_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ unsigned int timeout)
+{
+ struct sss_failover_ping_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_ping_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->fctx = fctx;
+ state->server = server;
+ state->timeout = timeout;
+
+ subreq = sss_failover_server_resolve_send(state, ev,
+ state->fctx->resolver_ctx,
+ state->fctx->family_order,
+ state->server);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_ping_resolved, req);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void
+sss_failover_ping_resolved(struct tevent_req *subreq)
+{
+ struct sss_failover_ping_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ping_state);
+
+ ret = sss_failover_server_resolve_recv(subreq, NULL);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Pinging %s:%d (%s)\n", state->server->name,
+ state->server->port, state->server->addr->human);
+
+ state->ping_start = tevent_timeval_current();
+
+ subreq = sssd_async_socket_init_send(state, state->ev, false,
+ state->server->addr->sockaddr,
+ state->server->addr->sockaddr_len,
+ state->timeout);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_ping_done, req);
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+}
+
+static void sss_failover_ping_done(struct tevent_req *subreq)
+{
+ struct sss_failover_ping_state *state;
+ struct timeval ping_duration;
+ struct timeval ping_end;
+ struct tevent_req *req;
+ errno_t ret;
+ int fd;
+
+ ping_end = tevent_timeval_current();
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ping_state);
+
+ ret = sssd_async_socket_init_recv(subreq, &fd);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Server %s:%d is not reachable within %d seconds [%d]: %s\n",
+ state->server->name, state->server->port, state->timeout, ret,
+ sss_strerror(ret));
+ goto done;
+ }
+
+ close(fd);
+
+ ping_duration = tevent_timeval_until(&state->ping_start, &ping_end);
+ DEBUG(SSSDBG_TRACE_FUNC, "Server %s:%d responded in %lds:%ldus\n",
+ state->server->name, state->server->port, ping_duration.tv_sec,
+ ping_duration.tv_usec);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static errno_t
+sss_failover_ping_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server **_server)
+{
+ struct sss_failover_ping_state *state;
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ state = tevent_req_data(req, struct sss_failover_ping_state);
+ *_server = talloc_reference(mem_ctx, state->server);
+
+ return EOK;
+}
+
+struct sss_failover_ping_parallel_state {
+ struct tevent_context *ev;
+ struct sss_failover_ctx *fctx;
+ struct sss_failover_server **servers;
+ unsigned int shortcut_time;
+ unsigned int max_servers;
+
+ TALLOC_CTX *reqs_ctx;
+ struct tevent_timer *shortcut_te;
+ struct tevent_timer *batch_te;
+ unsigned int shortcut_attempts;
+ unsigned int active_requests;
+ unsigned int batch;
+ size_t next_server;
+ size_t count;
+
+ struct sss_failover_server **candidates;
+ size_t candidates_index;
+};
+
+static void
+sss_failover_ping_parallel_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state);
+
+static struct tevent_timer *
+sss_failover_ping_parallel_shortcut_setup(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ unsigned int delay,
+ struct tevent_req *req);
+static void
+sss_failover_ping_parallel_shortcut(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv,
+ void *data);
+
+static void
+sss_failover_ping_parallel_batch(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv,
+ void *data);
+
+static void
+sss_failover_ping_parallel_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+sss_failover_ping_parallel_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server **servers,
+ unsigned int max_servers,
+ unsigned int shortcut_time)
+{
+ struct sss_failover_ping_parallel_state *state;
+ struct timeval tv = {0, 0};
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_ping_parallel_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->fctx = fctx;
+ state->servers = servers;
+ state->max_servers = max_servers;
+ state->shortcut_time = shortcut_time;
+
+ state->batch = 1;
+ state->next_server = 0;
+ state->count = talloc_array_length(servers) - 1;
+
+ state->reqs_ctx = talloc_new(state);
+ if (state->reqs_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ state->candidates_index = 0;
+ state->candidates = talloc_zero_array(state, struct sss_failover_server *,
+ max_servers + 1);
+ if (state->candidates == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_cleanup_fn(req, sss_failover_ping_parallel_cleanup);
+
+ state->shortcut_attempts = 0;
+ state->shortcut_te = sss_failover_ping_parallel_shortcut_setup(
+ state, state->ev, state->shortcut_time, req);
+
+ sss_failover_ping_parallel_batch(ev, NULL, tv, req);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void
+sss_failover_ping_parallel_cleanup(struct tevent_req *req,
+ enum tevent_req_state req_state)
+{
+ struct sss_failover_ping_parallel_state *state;
+
+ state = tevent_req_data(req, struct sss_failover_ping_parallel_state);
+
+ /* This request is done. Terminate any remaining timers and pings. */
+ talloc_zfree(state->shortcut_te);
+ talloc_zfree(state->batch_te);
+ talloc_zfree(state->reqs_ctx);
+ state->active_requests = 0;
+}
+
+static struct tevent_timer *
+sss_failover_ping_parallel_shortcut_setup(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ unsigned int delay,
+ struct tevent_req *req)
+{
+ struct tevent_timer *te;
+ struct timeval tv;
+
+ tv = tevent_timeval_current_ofs(delay, 0);
+ te = tevent_add_timer(ev, mem_ctx, tv,
+ sss_failover_ping_parallel_shortcut, req);
+ if (te == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule next shortcut!\n");
+ }
+
+ return te;
+}
+
+static void
+sss_failover_ping_parallel_shortcut(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv,
+ void *data)
+{
+ struct sss_failover_ping_parallel_state *state;
+ struct tevent_req *req;
+
+ req = talloc_get_type(data, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ping_parallel_state);
+
+ state->shortcut_te = NULL;
+ state->shortcut_attempts++;
+
+ /* There is at least one candidate server available. Return it. */
+ if (state->candidates[0] != NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Some candidates were already found in %d seconds, do not wait "
+ "for others\n",
+ state->shortcut_time * state->shortcut_attempts);
+ tevent_req_done(req);
+ return;
+ }
+
+ state->shortcut_te = sss_failover_ping_parallel_shortcut_setup(
+ state, state->ev, state->shortcut_time, req);
+}
+
+static void
+sss_failover_ping_parallel_batch(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval tv,
+ void *data)
+{
+ struct sss_failover_ping_parallel_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ uint32_t delay;
+ size_t limit;
+ size_t i;
+
+ req = talloc_get_type(data, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ping_parallel_state);
+
+ state->batch_te = NULL;
+
+ /* Issue three batches in total to avoid pinging too many servers if not
+ * necessary. We want to find @max_servers working servers. The first batch
+ * (@max_servers pings) is issued immediately and we will wait 400ms for it
+ * to finish. If we don't get a reply in time we issue next batch
+ * (@max_servers pings) and wait 200ms. If we still have no reply, we ping
+ * remaining servers.
+ */
+ switch (state->batch) {
+ case 1:
+ case 2:
+ limit = MIN(state->count, state->max_servers + state->next_server);
+ delay = 400000 / state->batch;
+ break;
+ default:
+ limit = state->count;
+ delay = 0;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Sending ping to servers from batch %d\n",
+ state->batch);
+
+ for (i = state->next_server; i < limit; i++) {
+ DEBUG(SSSDBG_TRACE_ALL, "Batch %d: %s:%d\n", state->batch,
+ state->servers[i]->name, state->servers[i]->port);
+ }
+
+ for (; state->next_server < limit; state->next_server++) {
+ subreq = sss_failover_ping_send(state->reqs_ctx, ev, state->fctx,
+ state->servers[state->next_server],
+ state->fctx->opts.ping_timeout);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to create new ping request\n");
+ goto fail;
+ }
+
+ state->active_requests++;
+ tevent_req_set_callback(subreq, sss_failover_ping_parallel_done, req);
+ }
+
+ state->batch++;
+ if (delay > 0) {
+ tv = tevent_timeval_current_ofs(0, delay);
+ state->batch_te = tevent_add_timer(ev, state, tv,
+ sss_failover_ping_parallel_batch, req);
+ if (state->batch_te == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to schedule next batch!\n");
+ goto fail;
+ }
+ }
+
+ return;
+
+fail:
+ if (state->active_requests == 0) {
+ tevent_req_error(req, ENOMEM);
+ if (state->batch == 1) {
+ tevent_req_post(req, ev);
+ }
+ }
+}
+
+static void
+sss_failover_ping_parallel_done(struct tevent_req *subreq)
+{
+ struct sss_failover_ping_parallel_state *state;
+ struct timeval tv = {0, 0};
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ping_parallel_state);
+
+ ret = sss_failover_ping_recv(state->candidates, subreq,
+ &state->candidates[state->candidates_index]);
+ talloc_zfree(subreq);
+ state->active_requests--;
+
+ if (ret == EOK) {
+ state->candidates_index++;
+ }
+
+ /* Are we done? */
+ if (state->candidates_index == state->max_servers) {
+ tevent_req_done(req);
+ return;
+ }
+
+ if (state->active_requests == 0) {
+ /* There are still servers to try, don't wait for the timer. */
+ if (state->next_server < state->count) {
+ talloc_zfree(state->batch_te);
+ sss_failover_ping_parallel_batch(state->ev, NULL, tv, req);
+ return;
+ }
+
+ /* All servers were tried. */
+ tevent_req_done(req);
+ return;
+ }
+
+ /* Wait for another ping to finish. */
+}
+
+static errno_t
+sss_failover_ping_parallel_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ size_t *_num_servers,
+ struct sss_failover_server ***_servers)
+{
+ struct sss_failover_ping_parallel_state *state;
+
+ state = tevent_req_data(req, struct sss_failover_ping_parallel_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_num_servers = state->candidates_index;
+ *_servers = talloc_steal(mem_ctx, state->candidates);
+
+ return EOK;
+}
+
+struct sss_failover_refresh_candidates_state {
+ struct tevent_context *ev;
+ struct sss_failover_ctx *fctx;
+
+ unsigned int current_group;
+ struct sss_failover_group *group;
+ struct sss_failover_server **group_servers;
+};
+
+static errno_t
+sss_failover_refresh_candidates_group_next(struct tevent_req *req);
+
+static void
+sss_failover_refresh_candidates_group_resolved(struct tevent_req *subreq);
+
+static void
+sss_failover_refresh_candidates_done(struct tevent_req *subreq);
+
+errno_t
+sss_failover_refresh_candidates_recv(struct tevent_req *subreq);
+
+struct tevent_req *
+sss_failover_refresh_candidates_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx)
+{
+ struct sss_failover_refresh_candidates_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_refresh_candidates_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->fctx = fctx;
+ state->current_group = 0;
+ state->group = state->fctx->groups[0];
+
+ state->fctx->candidates->last_refresh_time = time(NULL);
+ state->fctx->candidates->refresh_req = req;
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Refreshing failover server candidates\n");
+
+ /* Stop the queue as we are refreshing the candidates list now. */
+ DEBUG(SSSDBG_TRACE_FUNC, "Stopping candidates notification queue\n");
+ tevent_queue_stop(fctx->candidates->notify_queue);
+
+ ret = sss_failover_refresh_candidates_group_next(req);
+
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static errno_t
+sss_failover_refresh_candidates_group_next(struct tevent_req *req)
+{
+ struct sss_failover_refresh_candidates_state *state;
+ struct tevent_req *subreq;
+
+ state = tevent_req_data(req, struct sss_failover_refresh_candidates_state);
+ state->group = state->fctx->groups[state->current_group];
+
+ if (state->group == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "No more groups to try\n");
+ return ENOENT;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Trying failover group: %s:%u\n",
+ state->group->name, state->group->slot);
+
+ subreq = sss_failover_group_resolve_send(state, state->ev, state->fctx,
+ state->group);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq,
+ sss_failover_refresh_candidates_group_resolved,
+ req);
+
+ return EOK;
+}
+
+static void
+sss_failover_refresh_candidates_group_resolved(struct tevent_req *subreq)
+{
+ struct sss_failover_refresh_candidates_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_refresh_candidates_state);
+
+ talloc_zfree(state->group_servers);
+ ret = sss_failover_group_resolve_recv(state, subreq, &state->group_servers);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* No servers found, try next group. */
+ if (state->group_servers[0] == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC, "No servers found, trying next group\n");
+
+ state->current_group++;
+ ret = sss_failover_refresh_candidates_group_next(req);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ return;
+ }
+
+ /* Servers found. Ping them in multiple batches. */
+ subreq = sss_failover_ping_parallel_send(state, state->ev, state->fctx,
+ state->group_servers,
+ state->fctx->opts.max_candidates,
+ state->fctx->opts.min_candidates_lookup_time);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_refresh_candidates_done, req);
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ }
+}
+
+static void
+sss_failover_refresh_candidates_done(struct tevent_req *subreq)
+{
+ struct sss_failover_refresh_candidates_state *state;
+ struct sss_failover_server **candidates;
+ struct tevent_req *req;
+ size_t count;
+ errno_t ret;
+ int i;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_refresh_candidates_state);
+
+ ret = sss_failover_ping_parallel_recv(state, subreq, &count, &candidates);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ /* This is system error like ENOMEM. Not functional. */
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to ping any server [%d]: %s\n", ret,
+ sss_strerror(ret));
+ goto done;
+ }
+
+ if (count == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, "No servers found, trying next group\n");
+
+ state->current_group++;
+ ret = sss_failover_refresh_candidates_group_next(req);
+ if (ret != EOK) {
+ goto done;
+ }
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Found %zu candidate servers in group %s:%u\n",
+ count, state->group->name, state->group->slot);
+
+ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) {
+ for (i = 0; candidates[i] != NULL; i++) {
+ DEBUG(SSSDBG_TRACE_ALL, "Found candidate server: %s:%u\n",
+ candidates[i]->name, candidates[i]->port);
+ }
+ }
+
+ talloc_unlink(state->fctx->candidates, state->fctx->candidates->servers);
+ state->fctx->candidates->servers = talloc_steal(state->fctx->candidates,
+ candidates);
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+sss_failover_refresh_candidates_recv(struct tevent_req *req)
+{
+ struct sss_failover_refresh_candidates_state *state;
+
+ state = tevent_req_data(req, struct sss_failover_refresh_candidates_state);
+
+ state->fctx->candidates->last_refresh_time = time(NULL);
+ state->fctx->candidates->refresh_req = NULL;
+
+ /* Notify listeners that refresh is finished. */
+ DEBUG(SSSDBG_TRACE_FUNC, "Starting candidates notification queue\n");
+ tevent_queue_start(state->fctx->candidates->notify_queue);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
+bool
+sss_failover_refresh_candidates_oob_can_run(struct sss_failover_ctx *fctx)
+{
+ time_t now;
+
+ now = time(NULL);
+
+ /* There is ongoing active request? */
+ if (fctx->candidates->refresh_req != NULL) {
+ return false;
+ }
+
+ /* Has enough time elapsed? */
+ if (now <= fctx->candidates->last_refresh_time
+ + fctx->candidates->min_refresh_time) {
+ return false;
+ }
+
+ return true;
+}
+
+static void
+sss_failover_refresh_candidates_oob_done(struct tevent_req *subreq);
+
+void
+sss_failover_refresh_candidates_oob_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx)
+{
+ struct tevent_req *subreq;
+
+ if (!sss_failover_refresh_candidates_oob_can_run(fctx)) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Minimum refresh time has not elapsed yet or "
+ "there is an active refresh request.\n");
+ return;
+ }
+
+ subreq = sss_failover_refresh_candidates_send(mem_ctx, ev, fctx);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_refresh_candidates_oob_done,
+ NULL);
+}
+
+static void
+sss_failover_refresh_candidates_oob_done(struct tevent_req *subreq)
+{
+ sss_failover_refresh_candidates_recv(subreq);
+ talloc_free(subreq);
+}
diff --git a/src/providers/failover/failover_refresh_candidates.h b/src/providers/failover/failover_refresh_candidates.h
new file mode 100644
index 00000000000..1bbdaa1abe5
--- /dev/null
+++ b/src/providers/failover/failover_refresh_candidates.h
@@ -0,0 +1,42 @@
+;/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_REFRESH_CANDIDATES_H_
+#define _FAILOVER_REFRESH_CANDIDATES_H_
+
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+
+struct tevent_req *
+sss_failover_refresh_candidates_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx);
+
+errno_t
+sss_failover_refresh_candidates_recv(struct tevent_req *req);
+
+bool
+sss_failover_refresh_candidates_oob_can_run(struct sss_failover_ctx *fctx);
+
+void
+sss_failover_refresh_candidates_oob_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx);
+
+#endif /* _FAILOVER_REFRESH_CANDIDATES_H_ */
diff --git a/src/providers/failover/failover_server.c b/src/providers/failover/failover_server.c
new file mode 100644
index 00000000000..bc7a5e124ce
--- /dev/null
+++ b/src/providers/failover/failover_server.c
@@ -0,0 +1,353 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover_server.h"
+#include "util/util.h"
+
+static struct sss_failover_server_address *
+sss_failover_server_address_new(TALLOC_CTX *mem_ctx,
+ const uint16_t port,
+ const int family,
+ const time_t expire,
+ const uint8_t *addr_binary)
+{
+ struct sss_failover_server_address *out;
+ char buf[INET6_ADDRSTRLEN] = {0};
+ const char *ntop_result;
+ struct sockaddr_in *in4;
+ struct sockaddr_in6 *in6;
+ errno_t ret;
+
+ if (addr_binary == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Empty IP address!\n");
+ return NULL;
+ }
+
+ out = talloc_zero(mem_ctx, struct sss_failover_server_address);
+ if (out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ out->family = family;
+ out->expire = expire;
+
+ switch (family) {
+ case AF_INET:
+ out->binary_len = sizeof(struct in_addr);
+ out->sockaddr_len = sizeof(struct sockaddr_in);
+
+ in4 = talloc_zero(out, struct sockaddr_in);
+ if (in4 == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ in4->sin_family = AF_INET;
+ in4->sin_port = (in_port_t)htons(port);
+ memcpy(&in4->sin_addr, addr_binary, out->binary_len);
+ out->sockaddr = (struct sockaddr *)in4;
+ break;
+ case AF_INET6:
+ out->binary_len = sizeof(struct in6_addr);
+ out->sockaddr_len = sizeof(struct sockaddr_in6);
+
+ in6 = talloc_zero(out, struct sockaddr_in6);
+ if (in6 == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ in6->sin6_family = AF_INET6;
+ in6->sin6_port = (in_port_t)htons(port);
+ memcpy(&in6->sin6_addr, addr_binary, out->binary_len);
+ out->sockaddr = (struct sockaddr *)in6;
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown IP family: %d\n", out->family);
+ ret = EINVAL;
+ goto done;
+ }
+
+ out->binary = talloc_memdup(out, addr_binary, out->binary_len);
+ if (out->binary == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ntop_result = inet_ntop(family, addr_binary, buf, INET6_ADDRSTRLEN);
+ if (ntop_result == NULL) {
+ ret = errno;
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unable to convert IP address to string [%d]: %s\n", ret,
+ sss_strerror(ret));
+ goto done;
+ }
+
+ out->human = talloc_strdup(out, ntop_result);
+ if (out->human == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(out);
+ return NULL;
+ }
+
+ return out;
+}
+
+struct sss_failover_server *
+sss_failover_server_new(TALLOC_CTX *mem_ctx,
+ const char *hostname,
+ const char *uri,
+ const uint16_t port,
+ const int priority,
+ const int weight)
+{
+ struct sss_failover_server *srv;
+
+ if (hostname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Hostname is not set!\n");
+ return NULL;
+ }
+
+ srv = talloc_zero(mem_ctx, struct sss_failover_server);
+ if (srv == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return NULL;
+ }
+
+ srv->name = talloc_strdup(srv, hostname);
+ if (srv->name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ talloc_free(srv);
+ return NULL;
+ }
+
+ srv->uri = talloc_strdup(srv, uri);
+ if (srv->uri == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ talloc_free(srv);
+ return NULL;
+ }
+
+ srv->port = port;
+ srv->priority = priority;
+ srv->weight = weight;
+
+ return srv;
+}
+
+errno_t
+sss_failover_server_set_address(struct sss_failover_server *srv,
+ int family,
+ int ttl,
+ const uint8_t *addr)
+{
+ struct sss_failover_server_address *new_addr;
+ time_t expire;
+
+ if (family != AF_INET && family != AF_INET6) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid family given: %d\n", family);
+ return EINVAL;
+ }
+
+ if (addr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Empty addr given\n");
+ return EINVAL;
+ }
+
+ expire = time(NULL) + ttl;
+ new_addr = sss_failover_server_address_new(srv, srv->port, family, expire,
+ addr);
+ if (new_addr == NULL) {
+ return ENOMEM;
+ }
+
+ if (srv->addr != NULL) {
+ talloc_free(srv->addr);
+ }
+
+ srv->addr = new_addr;
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Server %s resolved to %s, ttl %d\n",
+ srv->name, srv->addr->human, ttl);
+
+ return EOK;
+}
+
+struct sss_failover_server *
+sss_failover_server_clone(TALLOC_CTX *mem_ctx,
+ const struct sss_failover_server *srv)
+{
+ struct sss_failover_server *out;
+ errno_t ret;
+
+ if (srv == NULL || srv->name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Empty failover server information!\n");
+ return NULL;
+ }
+
+ if (srv->addr != NULL
+ && (srv->addr->binary == NULL || srv->addr->human == NULL)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Address is not complete!\n");
+ return NULL;
+ }
+
+ out = talloc_zero(mem_ctx, struct sss_failover_server);
+ if (out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return NULL;
+ }
+
+ out->priority = srv->priority;
+ out->weight = srv->weight;
+ out->port = srv->port;
+ out->state = srv->state;
+
+ out->name = talloc_strdup(out, srv->name);
+ if (out->name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (srv->uri != NULL) {
+ out->uri = talloc_strdup(out, srv->uri);
+ if (out->uri == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ if (srv->addr == NULL) {
+ ret = EOK;
+ goto done;
+ }
+
+ out->addr = sss_failover_server_address_new(out, srv->port,
+ srv->addr->family,
+ srv->addr->expire,
+ srv->addr->binary);
+ if (out->addr == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create new server address!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(out);
+ return NULL;
+ }
+
+ return out;
+}
+
+bool
+sss_failover_server_maybe_working(struct sss_failover_server *srv)
+{
+ switch (srv->state) {
+ case SSS_FAILOVER_SERVER_STATE_OFFLINE:
+ case SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR:
+ return false;
+ case SSS_FAILOVER_SERVER_STATE_UNKNOWN:
+ case SSS_FAILOVER_SERVER_STATE_REACHABLE:
+ case SSS_FAILOVER_SERVER_STATE_WORKING:
+ return true;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: unknown state [%d]!\n", srv->state);
+ return false;
+ }
+}
+
+void
+sss_failover_server_mark_unknown(struct sss_failover_server *srv)
+{
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Marking server [%s] as state unknown\n", srv->name);
+ srv->state = SSS_FAILOVER_SERVER_STATE_UNKNOWN;
+}
+
+void
+sss_failover_server_mark_reachable(struct sss_failover_server *srv)
+{
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Marking server [%s] as reachable\n", srv->name);
+ srv->state = SSS_FAILOVER_SERVER_STATE_REACHABLE;
+}
+
+void
+sss_failover_server_mark_working(struct sss_failover_server *srv)
+{
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Marking server [%s] as functional\n", srv->name);
+ srv->state = SSS_FAILOVER_SERVER_STATE_WORKING;
+}
+
+void
+sss_failover_server_mark_offline(struct sss_failover_server *srv)
+{
+ DEBUG(SSSDBG_TRACE_FUNC, "Marking server [%s] as offline\n", srv->name);
+ srv->state = SSS_FAILOVER_SERVER_STATE_OFFLINE;
+}
+
+void
+sss_failover_server_mark_resolver_error(struct sss_failover_server *srv)
+{
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Marking server [%s] as unable to resolve hostname\n", srv->name);
+ srv->state = SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR;
+}
+
+bool
+sss_failover_server_equal(const struct sss_failover_server *a,
+ const struct sss_failover_server *b)
+{
+ if (a->name == NULL || b->name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: server with no name?\n");
+ return false;
+ }
+
+ if (strcmp(a->name, b->name) != 0) {
+ return false;
+ }
+
+ if (a->port != b->port) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/providers/failover/failover_server.h b/src/providers/failover/failover_server.h
new file mode 100644
index 00000000000..98b9d4ddf73
--- /dev/null
+++ b/src/providers/failover/failover_server.h
@@ -0,0 +1,189 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_SERVER_H_
+#define _FAILOVER_SERVER_H_
+
+#include
+
+#include "config.h"
+#include "util/util.h"
+
+enum sss_failover_server_state {
+ /**
+ * @brief State of the server is unknown.
+ */
+ SSS_FAILOVER_SERVER_STATE_UNKNOWN,
+
+ /**
+ * @brief The server is responding but there is no active connection.
+ *
+ * E.g. ping succeeded, but full connection was not done.
+ */
+ SSS_FAILOVER_SERVER_STATE_REACHABLE,
+
+ /**
+ * @brief The server is fully functional.
+ */
+ SSS_FAILOVER_SERVER_STATE_WORKING,
+
+ /**
+ * @brief The server is currently offline.
+ */
+ SSS_FAILOVER_SERVER_STATE_OFFLINE,
+
+ /**
+ * @brief The server host name can not be resolved.
+ */
+ SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR,
+};
+
+struct sss_failover_server_address {
+ /* AF_INET or AF_INET6 */
+ int family;
+
+ /* Human readable IP address. */
+ char *human;
+
+ /* IP address in binary format. */
+ uint8_t *binary;
+
+ /* Length of @binary */
+ size_t binary_len;
+
+ /* Generic sockaddr record. */
+ struct sockaddr *sockaddr;
+
+ /* @sockaddr length */
+ socklen_t sockaddr_len;
+
+ /* Time when the address will be expired and needs to be resolved again. */
+ time_t expire;
+};
+
+struct sss_failover_server {
+ /* DNS hostname */
+ char *name;
+
+ /* Server URI */
+ char *uri;
+
+ /* Service port. */
+ uint16_t port;
+
+ /* DNS priority */
+ int priority;
+
+ /* DNS weight */
+ int weight;
+
+ /* Host IP address. */
+ struct sss_failover_server_address *addr;
+
+ /* Current state. */
+ enum sss_failover_server_state state;
+
+ /* Connection handle if state is CONNECTED. */
+ void *connection;
+};
+
+/**
+ * @brief Create new failover server record.
+ *
+ * @return struct sss_failover_server *
+ */
+struct sss_failover_server *
+sss_failover_server_new(TALLOC_CTX *mem_ctx,
+ const char *hostname,
+ const char *uri,
+ const uint16_t port,
+ const int priority,
+ const int weight);
+
+/**
+ * @brief Set resolved IP address of the server hostname.
+ *
+ * @param srv
+ * @param family
+ * @param ttl
+ * @param addr
+ * @return errno_t
+ */
+errno_t
+sss_failover_server_set_address(struct sss_failover_server *srv,
+ int family,
+ int ttl,
+ const uint8_t *addr);
+
+/**
+ * @brief Clone failover server record.
+ *
+ * @param mem_ctx
+ * @param srv
+ * @return struct sss_failover_server *
+ */
+struct sss_failover_server *
+sss_failover_server_clone(TALLOC_CTX *mem_ctx,
+ const struct sss_failover_server *srv);
+
+
+/**
+ * @brief Return true if server state suggest that the server may work.
+ */
+bool
+sss_failover_server_maybe_working(struct sss_failover_server *srv);
+
+/**
+ * @brief Mark server as state unknown
+ */
+void
+sss_failover_server_mark_unknown(struct sss_failover_server *srv);
+
+/**
+ * @brief Mark server as reachable.
+ */
+void
+sss_failover_server_mark_reachable(struct sss_failover_server *srv);
+
+/**
+ * @brief Mark server as fully functional and working.
+ */
+void
+sss_failover_server_mark_working(struct sss_failover_server *srv);
+
+/**
+ * @brief Mark server as offline.
+ */
+void
+sss_failover_server_mark_offline(struct sss_failover_server *srv);
+
+/**
+ * @brief Mark server as unable to resolve hostname.
+ */
+void
+sss_failover_server_mark_resolver_error(struct sss_failover_server *srv);
+
+/**
+ * @brief Compare two servers and return true if they are equal.
+ *
+ * Note: this only compares name and port.
+ */
+bool
+sss_failover_server_equal(const struct sss_failover_server *a,
+ const struct sss_failover_server *b);
+
+#endif /* _FAILOVER_SERVER_H_ */
diff --git a/src/providers/failover/failover_server_resolve.c b/src/providers/failover/failover_server_resolve.c
new file mode 100644
index 00000000000..e3a8f998bca
--- /dev/null
+++ b/src/providers/failover/failover_server_resolve.c
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover_server.h"
+#include "resolv/async_resolv.h"
+#include "util/util.h"
+
+static bool
+sss_failover_server_resolve_address_changed(struct sss_failover_server *server,
+ struct resolv_hostent *hostent)
+{
+ if (server->addr == NULL) {
+ /* this is the first resolution */
+ return true;
+ }
+
+ if (server->addr->family != hostent->family) {
+ /* new address has different family */
+ return true;
+ }
+
+ return memcmp(server->addr->binary, hostent->addr_list[0]->ipaddr,
+ server->addr->binary_len) == 0;
+}
+
+struct sss_failover_server_resolve_state {
+ struct sss_failover_server *server;
+ bool changed;
+};
+
+static void
+sss_failover_server_resolve_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sss_failover_server_resolve_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resolv_ctx *resolv_ctx,
+ enum restrict_family family_order,
+ struct sss_failover_server *server)
+{
+ struct sss_failover_server_resolve_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+ time_t now;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_server_resolve_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ state->changed = false;
+ state->server = talloc_reference(mem_ctx, server);
+ if (state->server == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+
+ now = time(NULL);
+ if (state->server->addr != NULL && state->server->addr->expire > now) {
+ /* Address is still valid. */
+ tevent_req_done(req);
+ tevent_req_post(req, ev);
+ return req;
+ }
+
+ subreq = resolv_gethostbyname_send(state, ev, resolv_ctx, server->name,
+ family_order, default_host_dbs);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_server_resolve_done, req);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void
+sss_failover_server_resolve_done(struct tevent_req *subreq)
+{
+ struct sss_failover_server_resolve_state *state;
+ struct resolv_hostent *hostent;
+ struct tevent_req *req;
+ int resolv_status;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_server_resolve_state);
+
+ ret = resolv_gethostbyname_recv(subreq, req, &resolv_status, NULL,
+ &hostent);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ if (resolv_status == ARES_EFILE) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Failed to resolve server '%s': %s [local hosts file]\n",
+ state->server->name, resolv_strerror(resolv_status));
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to resolve server '%s': %s\n",
+ state->server->name, resolv_strerror(resolv_status));
+ }
+
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ if (hostent->addr_list == NULL || hostent->addr_list[0] == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "No IP address found\n");
+ tevent_req_error(req, ENOENT);
+ return;
+ }
+
+ /* check if address has changed */
+ state->changed = sss_failover_server_resolve_address_changed(state->server,
+ hostent);
+
+ ret = sss_failover_server_set_address(state->server, hostent->family,
+ hostent->addr_list[0]->ttl,
+ hostent->addr_list[0]->ipaddr);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set server address [%d]: %s\n",
+ ret, sss_strerror(ret));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+sss_failover_server_resolve_recv(struct tevent_req *req,
+ bool *_changed)
+{
+ struct sss_failover_server_resolve_state *state;
+
+ state = tevent_req_data(req, struct sss_failover_server_resolve_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ if (_changed != NULL) {
+ *_changed = state->changed;
+ }
+
+ return EOK;
+}
diff --git a/src/providers/failover/failover_server_resolve.h b/src/providers/failover/failover_server_resolve.h
new file mode 100644
index 00000000000..54032915aa1
--- /dev/null
+++ b/src/providers/failover/failover_server_resolve.h
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_SERVER_RESOLVE_H_
+#define _FAILOVER_SERVER_RESOLVE_H_
+
+#include
+#include
+
+#include "config.h"
+#include "resolv/async_resolv.h"
+#include "util/util.h"
+
+/**
+ * @brief Resolve server hostname into an IP address.
+ *
+ * When IP address is resolved, it calls @sss_failover_server_set_address to
+ * store the address in the @sss_failover_server record. Otherwise it keeps it
+ * intact.
+ *
+ * @param mem_ctx
+ * @param ev
+ * @param resolv_ctx
+ * @param family_order
+ * @param server
+ * @return struct tevent_req*
+ */
+struct tevent_req *
+sss_failover_server_resolve_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct resolv_ctx *resolv_ctx,
+ enum restrict_family family_order,
+ struct sss_failover_server *server);
+
+/**
+ * @brief Receives the return code.
+ *
+ * If EOK, IP address has been stored inside the server record. @_changed is
+ * true if the IP address of the host has changed, false if it is still the
+ * same.
+ *
+ * @param req
+ * @param _changed
+ * @return errno_t
+ */
+errno_t
+sss_failover_server_resolve_recv(struct tevent_req *req,
+ bool *_changed);
+
+#endif /* _FAILOVER_SERVER_RESOLVE_H_ */
diff --git a/src/providers/failover/failover_service.c b/src/providers/failover/failover_service.c
new file mode 100644
index 00000000000..1d43351bbee
--- /dev/null
+++ b/src/providers/failover/failover_service.c
@@ -0,0 +1,22 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "util/util.h"
diff --git a/src/providers/failover/failover_srv.c b/src/providers/failover/failover_srv.c
new file mode 100644
index 00000000000..1f72ec574d4
--- /dev/null
+++ b/src/providers/failover/failover_srv.c
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_server.h"
+#include "resolv/async_resolv.h"
+#include "util/util.h"
+
+struct sss_failover_resolve_srv_state {
+ struct sss_failover_server **servers;
+ char *final_discovery_domain;
+ uint32_t ttl;
+};
+
+static void sss_failover_resolve_srv_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sss_failover_srv_resolve_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ const char *service,
+ const char *protocol,
+ const char * const * discovery_domains)
+{
+ struct sss_failover_resolve_srv_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ const char **domains_dup;
+ size_t count;
+ size_t i;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_resolve_srv_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ for (count = 0; discovery_domains[count] != NULL; count++);
+ domains_dup = talloc_zero_array(state, const char *, count + 1);
+ for (i = 0; discovery_domains[i] != NULL; i++) {
+ domains_dup[i] = talloc_strdup(domains_dup, discovery_domains[i]);
+ if (domains_dup[i] == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Discovering servers for %s/%s from DNS\n",
+ service, protocol);
+
+ subreq = resolv_discover_srv_send(state, ev, fctx->resolver_ctx, service,
+ protocol, domains_dup);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_resolve_srv_done, req);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void sss_failover_resolve_srv_done(struct tevent_req *subreq)
+{
+ struct sss_failover_resolve_srv_state *state;
+ struct ares_srv_reply *reply_list;
+ struct ares_srv_reply *record;
+ struct tevent_req *req;
+ size_t num_servers;
+ errno_t ret;
+ int i;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_resolve_srv_state);
+
+ ret = resolv_discover_srv_recv(state, subreq, &reply_list, &state->ttl,
+ &state->final_discovery_domain);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Got answer. Processing...\n");
+
+ /* sort and store the answer */
+ ret = resolv_sort_srv_reply(&reply_list);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not sort the answers from DNS "
+ "[%d]: %s\n", ret, strerror(ret));
+ goto done;
+ }
+
+ num_servers = 0;
+ for (record = reply_list; record != NULL; record = record->next) {
+ num_servers++;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Got %zu servers\n", num_servers);
+
+ state->servers = talloc_zero_array(state, struct sss_failover_server *,
+ num_servers + 1);
+ if (state->servers == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (record = reply_list, i = 0;
+ record != NULL;
+ record = record->next, i++) {
+ // TODO handle uri
+ state->servers[i] = sss_failover_server_new(
+ state->servers, record->host, "ldap://master.ldap.test", record->port, record->priority,
+ record->weight);
+ if (state->servers[i] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ goto done;
+ }
+ }
+
+ talloc_zfree(reply_list);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+sss_failover_srv_resolve_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ uint32_t *_ttl,
+ struct sss_failover_server ***_servers)
+{
+ struct sss_failover_resolve_srv_state *state;
+
+ state = tevent_req_data(req, struct sss_failover_resolve_srv_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_servers = talloc_steal(mem_ctx, state->servers);
+
+ return EOK;
+}
diff --git a/src/providers/failover/failover_srv.h b/src/providers/failover/failover_srv.h
new file mode 100644
index 00000000000..3b944a37aaa
--- /dev/null
+++ b/src/providers/failover/failover_srv.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_SRV_H_
+#define _FAILOVER_SRV_H_
+
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_server.h"
+#include "util/util.h"
+
+/**
+ * @brief Resolve DNS SRV record using selected discovery domains.
+ *
+ * If the first discovery domain yields no servers, we proceed with the next
+ * domain.
+ *
+ * @param mem_ctx
+ * @param ev
+ * @param fctx
+ * @param service
+ * @param protocol
+ * @param discovery_domains
+ * @return struct tevent_req*
+ */
+struct tevent_req *
+sss_failover_srv_resolve_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ const char *service,
+ const char *protocol,
+ const char * const * discovery_domains);
+
+/**
+ * @brief Get TTL and discovered servers.
+ *
+ * @param mem_ctx
+ * @param req
+ * @param _ttl
+ * @param _servers
+ * @return errno_t
+ */
+errno_t
+sss_failover_srv_resolve_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ uint32_t *_ttl,
+ struct sss_failover_server ***_servers);
+
+#endif /* _FAILOVER_SRV_H_ */
diff --git a/src/providers/failover/failover_transaction.c b/src/providers/failover/failover_transaction.c
new file mode 100644
index 00000000000..e5f4a3bd740
--- /dev/null
+++ b/src/providers/failover/failover_transaction.c
@@ -0,0 +1,467 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover_transaction.h"
+#include "providers/failover/failover_vtable_op.h"
+#include "util/util.h"
+
+errno_t
+sss_failover_transaction_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct tevent_req *caller_req,
+ tevent_req_fn connected_callback)
+{
+ return sss_failover_transaction_ex_send(mem_ctx, ev, fctx, caller_req,
+ connected_callback, true, true, true,
+ SSS_FAILOVER_TRANSACTION_TLS_DEFAULT);
+}
+
+struct sss_failover_transaction_connected_state {
+ struct sss_failover_ctx *fctx;
+};
+
+struct sss_failover_transaction_state {
+ struct tevent_context *ev;
+ struct sss_failover_ctx *fctx;
+
+ bool reuse_connection;
+ bool authenticate_connection;
+ bool read_rootdse;
+ enum sss_failover_transaction_tls force_tls;
+
+ /* Top level tevent request. Finished when this transaction is done. */
+ struct tevent_req *caller_req;
+ void *caller_data;
+ size_t caller_data_size;
+ const char *caller_data_type;
+
+ /* Connection request. Finished when we have a connection and
+ * connected_callback is fired. */
+ struct tevent_req *connected_req;
+ tevent_req_fn connected_callback;
+
+ /* Single transaction attempt. If successful, the main transaction request
+ * is finished. Otherwise, we try next server. */
+ struct tevent_req *attempt_req;
+
+ /* How many times was this transaction restarted. */
+ unsigned int attempts;
+
+ /* Connection information. */
+ struct sss_failover_server *current_server;
+ time_t kinit_expiration_time;
+ void *connection;
+};
+
+static errno_t
+sss_failover_transaction_restart(struct tevent_req *req);
+
+static errno_t
+sss_failover_transaction_next(struct tevent_req *req);
+
+static errno_t
+sss_failover_transaction_kinit(struct tevent_req *req);
+
+static void
+sss_failover_transaction_kinit_done(struct tevent_req *subreq);
+
+static errno_t
+sss_failover_transaction_connect(struct tevent_req *req);
+
+static void
+sss_failover_transaction_connect_done(struct tevent_req *subreq);
+
+static void
+sss_failover_transaction_attempt_done(struct tevent_req *attempt_req);
+
+static void
+sss_failover_transaction_done(struct tevent_req *subreq);
+
+errno_t
+sss_failover_transaction_ex_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct tevent_req *caller_req,
+ tevent_req_fn connected_callback,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls)
+{
+ struct sss_failover_transaction_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Creating new failover transaction for service %s\n", fctx->name);
+
+ req = tevent_req_create(mem_ctx, &state, struct sss_failover_transaction_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return ENOMEM;
+ }
+
+ state->ev = ev;
+ state->fctx = fctx;
+ state->reuse_connection = reuse_connection;
+ state->authenticate_connection = authenticate_connection;
+ state->read_rootdse = read_rootdse;
+
+ state->caller_req = caller_req;
+ state->caller_data = _tevent_req_data(caller_req);
+ state->caller_data_size = talloc_get_size(state->caller_data);
+ state->caller_data_type = talloc_get_name(state->caller_data);
+ state->connected_callback = connected_callback;
+ state->attempts = 0;
+
+ tevent_req_set_callback(req, sss_failover_transaction_done, caller_req);
+
+ ret = sss_failover_transaction_restart(req);
+ if (ret != EOK) {
+ /* We cannot get any working server. Just cancel this request. */
+ talloc_free(req);
+ }
+
+ return ret;
+}
+
+static errno_t
+sss_failover_transaction_restart(struct tevent_req *req)
+{
+ struct sss_failover_transaction_connected_state *connected_state;
+ struct sss_failover_transaction_state *state;
+ void *attempt_state;
+ errno_t ret;
+
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+ state->attempts++;
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Transaction attempt %u\n", state->attempts);
+
+ /* This request is what fires up the connected_callback - we have active
+ * connection to a server and the user can start querying it. */
+ state->connected_req = tevent_req_create(state,
+ &connected_state, struct sss_failover_transaction_connected_state);
+ if (state->connected_req == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ connected_state->fctx = state->fctx;
+
+ /* Create attempt req, this is used by the user as a replacement for
+ * caller_req. The user will seamlessly call
+ * tevent_req_done/error(attempt_req). */
+ state->attempt_req = __tevent_req_create(state, &attempt_state,
+ state->caller_data_size, state->caller_data_type,
+ __func__, __location__);
+ if (state->attempt_req == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Switch the attempt_req state to caller_req state so it is used seamlessly
+ * by the user. This is quite a hack and the attempt_state must stay
+ * attached to attempt_req otherwise tevent_req_destructor will cause double
+ * free. We also cannot free req nor attempt_req to make sure all data is
+ * available to the caller_req recv function. This is not nice, but OK as
+ * there should not be many retry attempts and the memory is freed when
+ * caller_req is freed. */
+ memcpy(attempt_state, state->caller_data, state->caller_data_size);
+
+ tevent_req_set_callback(state->attempt_req,
+ sss_failover_transaction_attempt_done, req);
+
+ tevent_req_set_callback(state->connected_req, state->connected_callback,
+ state->attempt_req);
+
+ ret = sss_failover_transaction_next(req);
+
+done:
+ if (ret != EOK && state->attempts > 1) {
+ /* The failover transaction was restarted due to server error but we
+ * cannot retrieve any new server. Terminate the main request since we
+ * are already in an async loop. This in turn will finish the
+ * caller_req. */
+ tevent_req_error(req, ret);
+ }
+
+ return ret;
+}
+
+static errno_t
+sss_failover_transaction_next(struct tevent_req *req)
+{
+ struct sss_failover_transaction_state *state;
+ errno_t ret;
+
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+
+ /* Unlink current server to decrease refcount. */
+ if (state->current_server != NULL) {
+ talloc_unlink(state, state->current_server);
+ state->current_server = NULL;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Trying to find a working server\n");
+ if (state->fctx->kinit_ctx != NULL && state->authenticate_connection) {
+ ret = sss_failover_transaction_kinit(req);
+ } else {
+ ret = sss_failover_transaction_connect(req);
+ }
+
+ return ret;
+}
+
+static errno_t
+sss_failover_transaction_kinit(struct tevent_req *req)
+{
+ struct sss_failover_transaction_state *state;
+ struct tevent_req *subreq;
+
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Attempting to kinit\n");
+
+ subreq = sss_failover_vtable_op_kinit_send(state, state->ev,
+ state->fctx->kinit_ctx);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_transaction_kinit_done, req);
+ return EOK;
+}
+
+static void
+sss_failover_transaction_kinit_done(struct tevent_req *subreq)
+{
+ struct sss_failover_transaction_state *state;
+ struct sss_failover_server *server;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+
+ ret = sss_failover_vtable_op_kinit_recv(state, subreq, &server,
+ &state->kinit_expiration_time);
+ talloc_zfree(subreq);
+ if (ret == ERR_NO_MORE_SERVERS) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "There are no more servers to try, cancelling operation\n");
+ goto done;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Error while attempting to kinit, cancelling operation [%d]: %s\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "kinit against KDC %s was successful\n",
+ server->name);
+
+ /* We do not need this server anymore. */
+ talloc_unlink(state, server);
+
+ ret = sss_failover_transaction_connect(req);
+
+done:
+ if (ret != EOK) {
+ /* We cannot get TGT. Terminate main request. */
+ tevent_req_error(req, ret);
+ return;
+ }
+}
+
+static errno_t
+sss_failover_transaction_connect(struct tevent_req *req)
+{
+ struct sss_failover_transaction_state *state;
+ struct tevent_req *subreq;
+
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Trying to establish connection\n");
+
+ subreq = sss_failover_vtable_op_connect_send(state, state->ev, state->fctx,
+ state->reuse_connection,
+ state->authenticate_connection,
+ state->read_rootdse,
+ state->force_tls,
+ state->kinit_expiration_time);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_transaction_connect_done, req);
+ return EOK;
+}
+
+static void
+sss_failover_transaction_connect_done(struct tevent_req *subreq)
+{
+ struct sss_failover_transaction_state *state;
+ struct tevent_req *req;
+ void *connection;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+
+ /* If successful, state->current_server is additional talloc_reference
+ * to an active, connected server. */
+ ret = sss_failover_vtable_op_connect_recv(state, subreq,
+ &state->current_server,
+ &connection);
+ talloc_zfree(subreq);
+ if (ret == ERR_NO_MORE_SERVERS) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "There are no more servers to try, cancelling operation\n");
+ goto done;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Error while attempting to connect, cancelling operation [%d]: %s\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Connected to %s, connection %p\n",
+ state->current_server->name, connection);
+
+ sss_failover_set_active_server(state->fctx, state->current_server);
+ sss_failover_set_connection(state->fctx, connection);
+
+ /* We are connected. Now continue with connected_callback. */
+ tevent_req_done(state->connected_req);
+
+done:
+ if (ret != EOK) {
+ /* We cannot establish connection. Terminate main request. */
+ tevent_req_error(req, ret);
+ return;
+ }
+}
+
+/* Finish the main failover transaction request or try next server. */
+static void sss_failover_transaction_attempt_done(struct tevent_req *attempt_req)
+{
+ struct sss_failover_transaction_state *state;
+ struct tevent_req *req;
+ void *attempt_state;
+ enum tevent_req_state treq_state;
+ uint64_t treq_error;
+
+ req = tevent_req_callback_data(attempt_req, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_transaction_state);
+ attempt_state = _tevent_req_data(attempt_req);
+
+ /* Copy the transaction_req state back to the caller_req state. We can not
+ * free the transaction state as there is no way to move possible new data
+ * to the caller state context. If the transaction is restarted we will
+ * allocate new transaction state, keeping this one hanging. It is OK as
+ * there is only finite number of possible restarts and eventually all the
+ * memory will be freed when the caller_req state is freed. */
+ memcpy(state->caller_data, attempt_state, state->caller_data_size);
+
+ if (tevent_req_is_error(attempt_req, &treq_state, &treq_error)) {
+ switch (treq_state) {
+ case TEVENT_REQ_USER_ERROR:
+ /* Try next server. */
+ if (treq_error == ERR_SERVER_FAILURE) {
+ sss_failover_server_mark_offline(state->current_server);
+ sss_failover_transaction_restart(req);
+ return;
+ }
+
+ tevent_req_error(req, treq_error);
+ return;
+ case TEVENT_REQ_TIMED_OUT:
+ tevent_req_error(req, ETIMEDOUT);
+ return;
+ case TEVENT_REQ_NO_MEMORY:
+ tevent_req_oom(req);
+ return;
+ default:
+ tevent_req_error(req, ERR_INTERNAL);
+ return;
+ }
+ }
+
+ tevent_req_done(req);
+}
+
+/* The failover transaction is done. Finish the caller request. */
+static void sss_failover_transaction_done(struct tevent_req *req)
+{
+ struct tevent_req *caller_req;
+ enum tevent_req_state req_state;
+ uint64_t req_error;
+
+ caller_req = tevent_req_callback_data(req, struct tevent_req);
+
+ /* Terminate the caller req. */
+ if (tevent_req_is_error(req, &req_state, &req_error)) {
+ switch (req_state) {
+ case TEVENT_REQ_USER_ERROR:
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Failover transaction end up with error "
+ "[%" PRIu64 "]: %s\n", req_error, sss_strerror(req_error));
+ tevent_req_error(caller_req, req_error);
+ return;
+ case TEVENT_REQ_TIMED_OUT:
+ DEBUG(SSSDBG_TRACE_FUNC, "Failover transaction timed out\n");
+ tevent_req_error(caller_req, ETIMEDOUT);
+ return;
+ case TEVENT_REQ_NO_MEMORY:
+ tevent_req_oom(caller_req);
+ return;
+ default:
+ DEBUG(SSSDBG_TRACE_FUNC, "Bug: Unexpected state %d\n", req_state);
+ tevent_req_error(caller_req, ERR_INTERNAL);
+ return;
+ }
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Failover transaction was successful\n");
+ tevent_req_done(caller_req);
+}
+
+/* Return connection. This is only called if we have a successful connection. */
+void *
+_sss_failover_transaction_connected_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req)
+{
+ struct sss_failover_transaction_connected_state *state;
+ void *connection;
+
+ state = tevent_req_data(req,
+ struct sss_failover_transaction_connected_state);
+
+ connection = sss_failover_get_connection(mem_ctx, state->fctx);
+ if (connection == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: connection should not be NULL!\n");
+ }
+
+ return connection;
+}
diff --git a/src/providers/failover/failover_transaction.h b/src/providers/failover/failover_transaction.h
new file mode 100644
index 00000000000..7c1f1227a2b
--- /dev/null
+++ b/src/providers/failover/failover_transaction.h
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+/**
+ * The failover transaction code is responsible for choosing and connecting to a
+ * server and retrying the whole operation if the server stops working in the
+ * middle of the request.
+ *
+ * The operation is wrapped by @sss_failover_transaction_send and it should make
+ * sure to fetch all required data from the server before writing them to the
+ * sysdb. If the operation fails due to the server failure, the operation tevent
+ * request must fail with ERR_SERVER_FAILURE to indicate the failure to the
+ * failover transaction code. In this case, the failover mechanism marks the
+ * server as offline, picks the next available server and restarts the whole
+ * operation. Neither the caller nor the operation has to deal with any failover
+ * mechanics.
+ *
+ * The result of the operation can be received by
+ * @sss_failover_transaction_recv.
+ */
+
+#ifndef _FAILOVER_TRANSACTION_H_
+#define _FAILOVER_TRANSACTION_H_
+
+#include
+#include
+
+#include "config.h"
+#include "resolv/async_resolv.h"
+#include "util/util.h"
+
+struct sss_failover_ctx;
+
+enum sss_failover_transaction_tls {
+ SSS_FAILOVER_TRANSACTION_TLS_DEFAULT,
+ SSS_FAILOVER_TRANSACTION_TLS_ON,
+ SSS_FAILOVER_TRANSACTION_TLS_OFF
+};
+
+errno_t
+sss_failover_transaction_ex_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct tevent_req *caller_req,
+ tevent_req_fn connected_callback,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls);
+
+errno_t
+sss_failover_transaction_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct tevent_req *caller_req,
+ tevent_req_fn connected_callback);
+
+/**
+ * @brief Submit a failover transaction.
+ *
+ * The failover code will pick a working server and submit a working connection
+ * to the underlying @req_send tevent request, passing @input_data along.
+ *
+ * If the receive @req_recv function returns ERR_SERVER_FAILURE, the transaction
+ * is repeated with another server as long as there is a server available. The
+ * transaction is cancelled if there are no more servers to try.
+ *
+ * The callback and data types are checked during compilation.
+ */
+
+void *
+_sss_failover_transaction_connected_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req);
+
+#define sss_failover_transaction_connected_recv(mem_ctx, req, type) \
+ talloc_get_type_abort(_sss_failover_transaction_connected_recv((mem_ctx), (req)), type)
+
+#endif /* _FAILOVER_TRANSACTION_H_ */
diff --git a/src/providers/failover/failover_vtable.c b/src/providers/failover/failover_vtable.c
new file mode 100644
index 00000000000..52c5067cb1c
--- /dev/null
+++ b/src/providers/failover/failover_vtable.c
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover_vtable.h"
+#include "providers/failover/failover.h"
+#include "util/util.h"
+
+void
+sss_failover_vtable_set_connect(struct sss_failover_ctx *fctx,
+ sss_failover_vtable_connect_send_t send_fn,
+ sss_failover_vtable_connect_recv_t recv_fn,
+ void *data)
+{
+ fctx->vtable->connect.send = send_fn;
+ fctx->vtable->connect.recv = recv_fn;
+ fctx->vtable->connect.data = data;
+}
+
+void
+sss_failover_vtable_set_kinit(struct sss_failover_ctx *fctx,
+ sss_failover_vtable_kinit_send_t send_fn,
+ sss_failover_vtable_kinit_recv_t recv_fn,
+ void *data)
+{
+ fctx->vtable->kinit.send = send_fn;
+ fctx->vtable->kinit.recv = recv_fn;
+ fctx->vtable->kinit.data = data;
+}
diff --git a/src/providers/failover/failover_vtable.h b/src/providers/failover/failover_vtable.h
new file mode 100644
index 00000000000..cd7733e5be0
--- /dev/null
+++ b/src/providers/failover/failover_vtable.h
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_VTABLE_H_
+#define _FAILOVER_VTABLE_H_
+
+#include
+#include
+
+#include "config.h"
+#include "resolv/async_resolv.h"
+#include "providers/failover/failover_server.h"
+#include "util/util.h"
+
+struct sss_failover_ctx;
+enum sss_failover_transaction_tls;
+
+struct sss_failover_vtable_kinit_output_data {
+ time_t expiration_time;
+};
+
+typedef struct tevent_req *
+(*sss_failover_vtable_kinit_send_t)(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed,
+ void *pvt);
+
+typedef errno_t
+(*sss_failover_vtable_kinit_recv_t)(TALLOC_CTX *mem_ctx,
+ struct tevent_req *,
+ time_t *_expiration_time);
+
+struct sss_failover_vtable_kinit {
+ sss_failover_vtable_kinit_send_t send;
+ sss_failover_vtable_kinit_recv_t recv;
+ void *data;
+};
+
+typedef struct tevent_req *
+(*sss_failover_vtable_connect_send_t)(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls,
+ time_t kinit_expiration_time,
+ void *pvt);
+
+typedef errno_t
+(*sss_failover_vtable_connect_recv_t)(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ void **_connection);
+
+
+struct sss_failover_vtable_connect {
+ sss_failover_vtable_connect_send_t send;
+ sss_failover_vtable_connect_recv_t recv;
+ void *data;
+};
+
+struct sss_failover_vtable {
+ struct sss_failover_vtable_kinit kinit;
+ struct sss_failover_vtable_connect connect;
+};
+
+void
+sss_failover_vtable_set_connect(struct sss_failover_ctx *fctx,
+ sss_failover_vtable_connect_send_t send_fn,
+ sss_failover_vtable_connect_recv_t recv_fn,
+ void *data);
+
+void
+sss_failover_vtable_set_kinit(struct sss_failover_ctx *fctx,
+ sss_failover_vtable_kinit_send_t send_fn,
+ sss_failover_vtable_kinit_recv_t recv_fn,
+ void *data);
+
+#endif /* _FAILOVER_VTABLE_H_ */
diff --git a/src/providers/failover/failover_vtable_op.c b/src/providers/failover/failover_vtable_op.c
new file mode 100644
index 00000000000..735c9a67678
--- /dev/null
+++ b/src/providers/failover/failover_vtable_op.c
@@ -0,0 +1,596 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_transaction.h"
+#include "providers/failover/failover_server.h"
+#include "providers/failover/failover_server_resolve.h"
+#include "providers/failover/failover_refresh_candidates.h"
+#include "providers/failover/failover_vtable_op.h"
+#include "util/util.h"
+
+static struct sss_failover_server *
+sss_failover_vtable_op_pick_server(TALLOC_CTX *mem_ctx,
+ struct sss_failover_ctx *fctx)
+{
+ struct sss_failover_server *server;
+ size_t index;
+ size_t start;
+ size_t count;
+
+ /* Total count of elements. */
+ count = talloc_array_length(fctx->candidates->servers) - 1;
+
+ start = sss_rand() % count;
+ for (size_t i = 0; i < count; i++) {
+ index = (start + i) % count;
+
+ server = fctx->candidates->servers[index];
+
+ /* This slot is empty. Continue. */
+ if (server == NULL) {
+ continue;
+ }
+
+ if (sss_failover_server_maybe_working(server)) {
+ return talloc_reference(mem_ctx, server);
+ }
+ }
+
+ /* We iterated over all candidates and none is working. */
+ return NULL;
+}
+
+enum sss_failover_vtable_op {
+ /* Perform kinit against given KDC. */
+ SSS_FAILOVER_VTABLE_OP_KINIT,
+
+ /* Connect to the server. */
+ SSS_FAILOVER_VTABLE_OP_CONNECT,
+};
+
+/**
+ * @brief Issue vtable operation against specific server.
+ *
+ * The operation should check the @server state and shortcut if possible (for
+ * example if the server is already connected and working). @addr_changed is
+ * true if the server hostname resolved to different address then what is stored
+ * (it was previously unresolved, or the DNS record has changed). The operation
+ * should take this information into consideration (e.g. reconnect to the server
+ * with new address).
+ *
+ * The server state can be unknown, reachable or working. The server address
+ * is guaranteed to be resolved.
+ */
+typedef struct tevent_req *
+(*sss_failover_vtable_op_send_t)(TALLOC_CTX *mem_ctx,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed);
+
+/**
+ * @brief Receive operation result and point to its private data.
+ *
+ * The private data is then stored on the server structure by caller.
+ */
+typedef errno_t
+(*sss_failover_vtable_op_recv_t)(TALLOC_CTX *mem_ctx,
+ struct tevent_req *,
+ void **_op_private_data);
+
+struct sss_failover_vtable_op_args {
+ union {
+ struct {
+ bool reuse_connection;
+ bool authenticate_connection;
+ bool read_rootdse;
+ enum sss_failover_transaction_tls force_tls;
+ time_t expiration_time;
+ } connect;
+ } input;
+
+ union {
+ struct {
+ time_t expiration_time;
+ } kinit;
+
+ struct {
+ void *connection;
+ } connect;
+ } output;
+};
+
+struct sss_failover_vtable_op_state {
+ struct tevent_context *ev;
+ struct sss_failover_ctx *fctx;
+ enum sss_failover_vtable_op operation;
+ struct sss_failover_vtable_op_args *args;
+
+ struct sss_failover_server *current_server;
+ bool candidates_refreshed;
+};
+
+static void
+sss_failover_vtable_op_trigger(struct tevent_req *req,
+ void *pvt);
+
+static errno_t
+sss_failover_vtable_op_server_next(struct tevent_req *req);
+
+static errno_t
+sss_failover_vtable_op_refresh_candidates(struct tevent_req *req);
+
+static void
+sss_failover_vtable_op_refresh_candidates_done(struct tevent_req *subreq);
+
+static void
+sss_failover_vtable_op_server_resolved(struct tevent_req *subreq);
+
+static struct tevent_req *
+sss_failover_vtable_op_subreq_send(struct sss_failover_vtable_op_state *state,
+ bool addr_changed);
+
+static errno_t
+sss_failover_vtable_op_subreq_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *subreq);
+
+static void
+sss_failover_vtable_op_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+sss_failover_vtable_op_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ enum sss_failover_vtable_op operation,
+ struct sss_failover_vtable_op_args *args)
+{
+ struct sss_failover_vtable_op_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+ bool bret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_vtable_op_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+
+ /* Free args to simplify logic in the caller. */
+ talloc_free(args);
+ return NULL;
+ }
+
+ state->ev = ev;
+ state->fctx = fctx;
+ state->operation = operation;
+ state->args = talloc_steal(state, args);
+
+ switch (state->operation) {
+ case SSS_FAILOVER_VTABLE_OP_KINIT:
+ case SSS_FAILOVER_VTABLE_OP_CONNECT:
+ /* Correct operation. */
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid operation: [%d]\n", state->operation);
+ ret = EINVAL;
+ goto done;
+ }
+
+ /* Queuing the requests ensures that there is only one request that does
+ * actual server selection and resolution. All subsequent requests will just
+ * shortcut and pick the last selected server, if it is still working. */
+ bret = tevent_queue_add(fctx->vtable_op_queue, fctx->ev, req,
+ sss_failover_vtable_op_trigger, NULL);
+ if (!bret) {
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to add request to tevent queue\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void
+sss_failover_vtable_op_trigger(struct tevent_req *req,
+ void *pvt)
+{
+ errno_t ret;
+
+ ret = sss_failover_vtable_op_server_next(req);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ }
+}
+
+static errno_t
+sss_failover_vtable_op_server_next(struct tevent_req *req)
+{
+ struct sss_failover_vtable_op_state *state;
+ struct tevent_req *subreq;
+
+ state = tevent_req_data(req, struct sss_failover_vtable_op_state);
+
+ if (state->current_server == NULL) {
+ /* Select first server to try.*/
+ if (state->fctx->active_server != NULL
+ && sss_failover_server_maybe_working(state->fctx->active_server)) {
+ /* Try active server first. */
+ state->current_server = state->fctx->active_server;
+ DEBUG(SSSDBG_TRACE_FUNC, "Trying current active server: %s\n",
+ state->current_server->name);
+ } else {
+ /* Pick a first server from candidates. */
+ state->current_server = sss_failover_vtable_op_pick_server(state, state->fctx);
+ if (state->current_server == NULL) {
+ /* No candidates are available, schedule a refresh. */
+ return sss_failover_vtable_op_refresh_candidates(req);
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Trying candidate server: %s\n",
+ state->current_server->name);
+ }
+ } else {
+ /* We already tried this server and it is not working. Submit an out of
+ * band request of server candidates and try the next available
+ * server. */
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Server %s does not work\n",
+ state->current_server->name);
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Issuing out of band refresh of candidates\n");
+
+ if (sss_failover_refresh_candidates_oob_can_run(state->fctx)) {
+ sss_failover_refresh_candidates_oob_send(state->fctx, state->ev,
+ state->fctx);
+ }
+
+ state->current_server = sss_failover_vtable_op_pick_server(state, state->fctx);
+ if (state->current_server == NULL) {
+ /* No candidates are available. Wait for new ones. */
+ return sss_failover_vtable_op_refresh_candidates(req);
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Trying next candidate server: %s\n",
+ state->current_server->name);
+ }
+
+ /* TODO shortcut if already connected */
+
+ /* First resolve the hostname. */
+ DEBUG(SSSDBG_TRACE_FUNC, "Resolving hostname of %s\n",
+ state->current_server->name);
+
+ subreq = sss_failover_server_resolve_send(state, state->ev,
+ state->fctx->resolver_ctx,
+ state->fctx->family_order,
+ state->current_server);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_vtable_op_server_resolved,
+ req);
+
+ return EOK;
+}
+
+static errno_t
+sss_failover_vtable_op_refresh_candidates(struct tevent_req *req)
+{
+ struct sss_failover_vtable_op_state *state;
+ struct tevent_queue *queue;
+ struct tevent_req *subreq;
+
+ state = tevent_req_data(req, struct sss_failover_vtable_op_state);
+ queue = state->fctx->candidates->notify_queue;
+
+ if (state->candidates_refreshed) {
+ /* We already refreshed the candidates. */
+ DEBUG(SSSDBG_TRACE_FUNC, "Refresh did not find any working server\n");
+ return ERR_NO_MORE_SERVERS;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "No more candidate servers are available, wait for a refresh\n");
+
+ state->candidates_refreshed = true;
+
+ /* Issue refresh request if there is none. */
+ if (sss_failover_refresh_candidates_oob_can_run(state->fctx)) {
+ sss_failover_refresh_candidates_oob_send(state->fctx, state->ev,
+ state->fctx);
+ }
+
+ /* Register for notification. */
+ subreq = tevent_queue_wait_send(state, state->ev, queue);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(subreq,
+ sss_failover_vtable_op_refresh_candidates_done,
+ req);
+
+ return EOK;
+}
+
+static void
+sss_failover_vtable_op_refresh_candidates_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+
+ ret = sss_failover_vtable_op_server_next(req);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ }
+}
+
+static void
+sss_failover_vtable_op_server_resolved(struct tevent_req *subreq)
+{
+ struct sss_failover_vtable_op_state *state;
+ struct tevent_req *req;
+ bool addr_changed;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_vtable_op_state);
+
+ ret = sss_failover_server_resolve_recv(subreq, &addr_changed);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unable to resolve server hostname %s [%d]: %s\n",
+ state->current_server->name, ret, sss_strerror(ret));
+ sss_failover_server_mark_resolver_error(state->current_server);
+ ret = sss_failover_vtable_op_server_next(req);
+ goto done;
+ }
+
+ /* Trigger the operation. */
+ DEBUG(SSSDBG_TRACE_FUNC, "Name resolved, starting vtable operation\n");
+
+ subreq = sss_failover_vtable_op_subreq_send(state, addr_changed);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_vtable_op_done, req);
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+}
+
+static struct tevent_req *
+sss_failover_vtable_op_subreq_send(struct sss_failover_vtable_op_state *state,
+ bool addr_changed)
+{
+ switch (state->operation) {
+ case SSS_FAILOVER_VTABLE_OP_KINIT:
+ return state->fctx->vtable->kinit.send(
+ state, state->ev, state->fctx, state->current_server, addr_changed,
+ state->fctx->vtable->kinit.data);
+ case SSS_FAILOVER_VTABLE_OP_CONNECT:
+ return state->fctx->vtable->connect.send(
+ state, state->ev, state->fctx, state->current_server, addr_changed,
+ state->args->input.connect.reuse_connection,
+ state->args->input.connect.authenticate_connection,
+ state->args->input.connect.read_rootdse,
+ state->args->input.connect.force_tls,
+ state->args->input.connect.expiration_time,
+ state->fctx->vtable->connect.data);
+ }
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: Unknown operation\n");
+ return NULL;
+}
+
+static errno_t
+sss_failover_vtable_op_subreq_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *subreq)
+{
+ struct sss_failover_vtable_op_state *state;
+ struct tevent_req *req;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_vtable_op_state);
+
+ switch (state->operation) {
+ case SSS_FAILOVER_VTABLE_OP_KINIT:
+ return state->fctx->vtable->kinit.recv(state, subreq,
+ &state->args->output.kinit.expiration_time);
+ case SSS_FAILOVER_VTABLE_OP_CONNECT:
+ return state->fctx->vtable->connect.recv(state, subreq,
+ &state->args->output.connect.connection);
+ }
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: Unknown operation\n");
+ return ENOTSUP;
+}
+
+static void sss_failover_vtable_op_done(struct tevent_req *subreq)
+{
+ struct sss_failover_vtable_op_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_vtable_op_state);
+
+ ret = sss_failover_vtable_op_subreq_recv(state, subreq);
+ talloc_zfree(subreq);
+
+ switch (ret) {
+ case EOK:
+ /* The operation was successful. */
+ sss_failover_server_mark_working(state->current_server);
+
+ /* Remember this server. */
+ talloc_unlink(state->fctx, state->fctx->active_server);
+ state->fctx->active_server = talloc_reference(state->fctx,
+ state->current_server);
+ break;
+ case ENOMEM:
+ /* There is no reason to retry if we our out of memory. */
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ goto done;
+ default:
+ /* Server is not working. */
+ sss_failover_server_mark_offline(state->current_server);
+ ret = sss_failover_vtable_op_server_next(req);
+ if (ret == EOK) {
+ return;
+ }
+ }
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static errno_t
+sss_failover_vtable_op_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server **_server,
+ struct sss_failover_vtable_op_args **_args)
+{
+ struct sss_failover_vtable_op_state *state = NULL;
+ state = tevent_req_data(req, struct sss_failover_vtable_op_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ if (_server != NULL) {
+ *_server = talloc_reference(mem_ctx, state->current_server);
+ }
+
+ if (_args != NULL) {
+ *_args = talloc_steal(mem_ctx, state->args);
+ }
+
+ return EOK;
+}
+
+struct tevent_req *
+sss_failover_vtable_op_kinit_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx)
+{
+ struct sss_failover_vtable_op_args *args;
+
+ args = talloc_zero(NULL, struct sss_failover_vtable_op_args);
+ if (args == NULL) {
+ return NULL;
+ }
+
+ return sss_failover_vtable_op_send(mem_ctx, ev, fctx,
+ SSS_FAILOVER_VTABLE_OP_KINIT, args);
+}
+
+errno_t
+sss_failover_vtable_op_kinit_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server **_server,
+ time_t *_expiration_time)
+{
+ struct sss_failover_vtable_op_args *args;
+ errno_t ret;
+
+ ret = sss_failover_vtable_op_recv(mem_ctx, req, _server, &args);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (_expiration_time != NULL) {
+ *_expiration_time = args->output.kinit.expiration_time;
+ }
+
+ talloc_free(args);
+ return EOK;
+}
+
+struct tevent_req *
+sss_failover_vtable_op_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls,
+ time_t kinit_expiration_time)
+{
+ struct sss_failover_vtable_op_args *args;
+
+ args = talloc_zero(NULL, struct sss_failover_vtable_op_args);
+ if (args == NULL) {
+ return NULL;
+ }
+
+ args->input.connect.reuse_connection = reuse_connection;
+ args->input.connect.authenticate_connection = authenticate_connection;
+ args->input.connect.read_rootdse = read_rootdse;
+ args->input.connect.force_tls = force_tls;
+ args->input.connect.expiration_time = kinit_expiration_time;
+ return sss_failover_vtable_op_send(mem_ctx, ev, fctx,
+ SSS_FAILOVER_VTABLE_OP_CONNECT, args);
+}
+
+errno_t
+sss_failover_vtable_op_connect_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server **_server,
+ void **_connection)
+{
+ struct sss_failover_vtable_op_args *args;
+ errno_t ret;
+
+ ret = sss_failover_vtable_op_recv(mem_ctx, req, _server, &args);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (_connection != NULL) {
+ *_connection = talloc_steal(mem_ctx, args->output.connect.connection);
+ }
+
+ talloc_free(args);
+ return EOK;
+}
diff --git a/src/providers/failover/failover_vtable_op.h b/src/providers/failover/failover_vtable_op.h
new file mode 100644
index 00000000000..d244e62a724
--- /dev/null
+++ b/src/providers/failover/failover_vtable_op.h
@@ -0,0 +1,131 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_VTABLE_OP_H_
+#define _FAILOVER_VTABLE_OP_H_
+
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_server.h"
+#include "util/util.h"
+
+/**
+ * @defgroup Failover vtable operations.
+ *
+ * The purpose of sss_failover_vtable_op_* requests is to find a working server
+ * on which the operation succeeds.
+ *
+ * - If there is already working and active server, use it.
+ * - Otherwise find first available server, resolve its hostname and use it.
+ * - If the operation succeeds, mark the server as working and store operation
+ * data.
+ * - If the operation fails, mark the server as not working and try next server.
+ *
+ * Note that this request does not decide if the operation should be started or
+ * not (e.g. if the server is already connected or not). To simplify the logic,
+ * this is the responsibility of the operation it self (e.g. check if the server
+ * is already connected in the @send_fn and then shortcut, otherwise try to
+ * establish connection).
+ *
+ * The requests are serialized in @fctx->vtable_op_queue to ensure that we
+ * always talk to a single server at the same time.
+ *
+ * @{
+ */
+
+/**
+ * @brief Select a KDC and attempt to kinit with the host credentials.
+ *
+ * @param mem_ctx
+ * @param ev
+ * @param fctx
+ * @return struct tevent_req *
+ */
+struct tevent_req *
+sss_failover_vtable_op_kinit_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx);
+
+/**
+ * @brief Receive result of the operation.
+ *
+ * If @_server is not NULL and EOK is returned, it contains the server that was
+ * successfully used to finish the operation. The server reference count is
+ * increased and linked to @mem_ctx.
+ *
+ * @param mem_ctx
+ * @param req
+ * @param _server
+ * @param _expiration_time Host TGT expiration time.
+ * @return errno_t
+ */
+errno_t
+sss_failover_vtable_op_kinit_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server **_server,
+ time_t *_expiration_time);
+
+/**
+ * @brief Select a server and attempt to establish a working connection.
+ *
+ * @param mem_ctx
+ * @param ev
+ * @param fctx
+ * @param reuse_connection
+ * @param authenticate_connection
+ * @param read_rootdse
+ * @param force_tls
+ * @param kinit_expiration_time
+ * @return struct tevent_req *
+ */
+struct tevent_req *
+sss_failover_vtable_op_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls,
+ time_t kinit_expiration_time);
+
+/**
+ * @brief Receive result of the operation.
+ *
+ * If @_server is not NULL and EOK is returned, it contains the server that was
+ * successfully used to finish the operation. The server reference count is
+ * increased and linked to @mem_ctx.
+ *
+ * @param mem_ctx
+ * @param req
+ * @param _server
+ * @param _connection Established connection data.
+ * @return errno_t
+ */
+errno_t
+sss_failover_vtable_op_connect_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct sss_failover_server **_server,
+ void **_connection);
+
+/**
+ * @}
+ */
+
+#endif /* _FAILOVER_VTABLE_OP_H_ */
diff --git a/src/providers/failover/ldap/failover_ldap.h b/src/providers/failover/ldap/failover_ldap.h
new file mode 100644
index 00000000000..ba90f6eeac8
--- /dev/null
+++ b/src/providers/failover/ldap/failover_ldap.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _FAILOVER_LDAP_H_
+#define _FAILOVER_LDAP_H_
+
+#include
+#include
+
+#include "config.h"
+#include "resolv/async_resolv.h"
+#include "providers/failover/failover_server.h"
+#include "util/util.h"
+
+struct sss_failover_ldap_connection {
+ struct sdap_server_opts *srv_opts;
+ struct sdap_handle *sh;
+ char *uri;
+};
+
+struct tevent_req *
+sss_failover_ldap_kinit_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed,
+ void *pvt);
+
+errno_t
+sss_failover_ldap_kinit_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ time_t *_expiration_time);
+
+struct tevent_req *
+sss_failover_ldap_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls,
+ time_t kinit_expiration_time,
+ void *pvt);
+
+errno_t
+sss_failover_ldap_connect_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ void **_connection);
+
+#endif /* _FAILOVER_LDAP_H_ */
diff --git a/src/providers/failover/ldap/failover_ldap_connect.c b/src/providers/failover/ldap/failover_ldap_connect.c
new file mode 100644
index 00000000000..6799c68b3ad
--- /dev/null
+++ b/src/providers/failover/ldap/failover_ldap_connect.c
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_transaction.h"
+#include "providers/failover/failover_server.h"
+#include "providers/failover/ldap/failover_ldap.h"
+#include "providers/ldap/sdap_async_private.h"
+#include "util/util.h"
+
+struct sss_failover_ldap_connect_state {
+ struct sss_failover_ldap_connection *connection;
+};
+
+static void sss_failover_ldap_connect_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sss_failover_ldap_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed,
+ bool reuse_connection,
+ bool authenticate_connection,
+ bool read_rootdse,
+ enum sss_failover_transaction_tls force_tls,
+ time_t kinit_expiration_time,
+ void *pvt)
+{
+ struct sss_failover_ldap_connect_state *state;
+ struct sdap_options *opts;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ enum connect_tls tls;
+ errno_t ret;
+
+ /* TODO handle active connection */
+
+ opts = talloc_get_type_abort(pvt, struct sdap_options);
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_ldap_connect_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->connection = talloc_zero(state, struct sss_failover_ldap_connection);
+ if (state->connection == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ state->connection->uri = talloc_strdup(state->connection, server->uri);
+ if (state->connection->uri == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ switch (force_tls) {
+ case SSS_FAILOVER_TRANSACTION_TLS_DEFAULT:
+ tls = CON_TLS_DFL;
+ break;
+ case SSS_FAILOVER_TRANSACTION_TLS_ON:
+ tls = CON_TLS_ON;
+ break;
+ case SSS_FAILOVER_TRANSACTION_TLS_OFF:
+ tls = CON_TLS_OFF;
+ break;
+ }
+
+ subreq = sdap_cli_connect_send(state, ev, opts, server->uri,
+ server->addr->sockaddr,
+ server->addr->sockaddr_len, !read_rootdse,
+ tls, !authenticate_connection,
+ kinit_expiration_time);
+ if (subreq == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_ldap_connect_done, req);
+
+ return req;
+
+done:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+
+ return req;
+}
+
+static void
+sss_failover_ldap_connect_done(struct tevent_req *subreq)
+{
+ struct sss_failover_ldap_connect_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ldap_connect_state);
+
+ ret = sdap_cli_connect_recv(subreq, state, &state->connection->sh,
+ &state->connection->srv_opts);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ talloc_steal(state->connection, state->connection->sh);
+ talloc_steal(state->connection, state->connection->srv_opts);
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+sss_failover_ldap_connect_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ void **_connection)
+{
+ struct sss_failover_ldap_connect_state *state;
+ state = tevent_req_data(req, struct sss_failover_ldap_connect_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ if (_connection != NULL) {
+ *_connection = (void*)talloc_steal(mem_ctx, state->connection);
+ }
+
+ return EOK;
+}
diff --git a/src/providers/failover/ldap/failover_ldap_kinit.c b/src/providers/failover/ldap/failover_ldap_kinit.c
new file mode 100644
index 00000000000..3d7d4bbfc06
--- /dev/null
+++ b/src/providers/failover/ldap/failover_ldap_kinit.c
@@ -0,0 +1,199 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+
+#include "config.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_server.h"
+#include "providers/failover/failover_server_resolve.h"
+#include "providers/failover/failover_vtable_op.h"
+#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/ldap_common.h"
+#include "util/util.h"
+
+static void
+sss_failover_ldap_kinit_options(struct sdap_options *opts,
+ const char **_keytab,
+ const char **_realm,
+ const char **_principal,
+ bool *_canonicalize,
+ int *_lifetime,
+ int *_timeout)
+{
+ *_keytab = dp_opt_get_string(opts->basic, SDAP_KRB5_KEYTAB);
+ *_realm = sdap_gssapi_realm(opts->basic);
+ *_principal = dp_opt_get_string(opts->basic, SDAP_SASL_AUTHID);
+ *_canonicalize = dp_opt_get_bool(opts->basic, SDAP_KRB5_CANONICALIZE);
+ *_lifetime = dp_opt_get_int(opts->basic, SDAP_KRB5_TICKET_LIFETIME);
+ *_timeout = dp_opt_get_int(opts->basic, SDAP_OPT_TIMEOUT);
+}
+
+struct sss_failover_ldap_kinit_state {
+ time_t expiration_time;
+};
+
+static void sss_failover_ldap_kinit_done(struct tevent_req *subreq);
+
+struct tevent_req *
+sss_failover_ldap_kinit_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sss_failover_server *server,
+ bool addr_changed,
+ void *pvt)
+{
+ struct sss_failover_ldap_kinit_state *state;
+ struct sdap_options *opts;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ const char *keytab;
+ const char *principal;
+ const char *realm;
+ bool canonicalize;
+ int timeout;
+ int lifetime;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sss_failover_ldap_kinit_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ opts = talloc_get_type_abort(pvt, struct sdap_options);
+
+ sss_failover_ldap_kinit_options(opts, &keytab, &realm, &principal,
+ &canonicalize, &lifetime, &timeout);
+
+ ret = setenv("KRB5_CANONICALIZE", canonicalize ? "true" : "false", 1);
+ if (ret != 0) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to set KRB5_CANONICALIZE to %s\n",
+ canonicalize ? "true" : "false");
+ ret = errno;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, "Attempting kinit (%s, %s, %s, %d, %s)\n",
+ keytab != NULL ? keytab : "default", principal, realm, lifetime,
+ server->name);
+
+ /* TODO write kdcinfo */
+
+ subreq = sdap_get_tgt_send(state, ev, realm, principal, keytab, lifetime,
+ timeout);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, sss_failover_ldap_kinit_done, req);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void
+sss_failover_ldap_kinit_done(struct tevent_req *subreq)
+{
+ struct sss_failover_ldap_kinit_state *state;
+ struct tevent_req *req;
+ krb5_error_code kerr;
+ char *ccname;
+ int result;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct sss_failover_ldap_kinit_state);
+
+ ret = sdap_get_tgt_recv(subreq, state, &result, &kerr, &ccname,
+ &state->expiration_time);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ /* ret is request error, result is child error, kerr is kerberos error */
+ switch (ret) {
+ case EOK:
+ if (result == EOK) {
+ /* TGT acquired. */
+ ret = setenv("KRB5CCNAME", ccname, 1);
+ if (ret != 0) {
+ ret = errno;
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unable to set env. variable KRB5CCNAME!\n");
+ goto done;
+ }
+ ret = EOK;
+ goto done;
+ } else if (kerr == KRB5_KDC_UNREACH) {
+ ret = ERR_SERVER_FAILURE;
+ goto done;
+ } else if (result == EFAULT || result == EIO || result == EPERM) {
+ ret = ERR_AUTH_FAILED;
+ goto done;
+ } else {
+ ret = ERR_AUTH_FAILED;
+ goto done;
+ }
+ break;
+ case ETIMEDOUT:
+ /* The child did not responds. Try another KDC. */
+ ret = ERR_SERVER_FAILURE;
+ goto done;
+ default:
+ /* Child did not execute correctly. Terminate. */
+ goto done;
+ }
+
+done:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+sss_failover_ldap_kinit_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ time_t *_expiration_time)
+{
+ struct sss_failover_ldap_kinit_state *state = NULL;
+ state = tevent_req_data(req, struct sss_failover_ldap_kinit_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ if (_expiration_time != NULL) {
+ *_expiration_time = state->expiration_time;
+ }
+
+ return EOK;
+}
diff --git a/src/providers/idp/idp_id.c b/src/providers/idp/idp_id.c
index 8ad85fb9217..8de4d4f4b2f 100644
--- a/src/providers/idp/idp_id.c
+++ b/src/providers/idp/idp_id.c
@@ -162,7 +162,6 @@ struct idp_type_get_state {
struct tevent_context *ev;
struct idp_id_ctx *idp_id_ctx;
struct idp_req *idp_req;
- int dp_error;
int idp_ret;
enum idp_lookup_type lookup_type;
const char *filter_value;
@@ -202,7 +201,6 @@ static struct tevent_req *idp_type_get_send(TALLOC_CTX *memctx,
state->ev = ev;
state->idp_id_ctx = idp_id_ctx;
- state->dp_error = DP_ERR_FATAL;
state->idp_ret = ENODATA;
state->lookup_type = lookup_type;
state->filter_value = talloc_strdup(state, filter_value);
@@ -295,7 +293,6 @@ static void idp_type_get_done(struct tevent_req *subreq)
ret = handle_oidc_child_recv(subreq, state, &buf, &buflen);
talloc_zfree(subreq);
if (ret != EOK) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -336,27 +333,21 @@ static void idp_type_get_done(struct tevent_req *subreq)
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Failed to evaluate user data returned by oidc_child.\n");
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
-static int idp_type_get_recv(struct tevent_req *req, int *dp_error_out,
+static int idp_type_get_recv(struct tevent_req *req,
int *idp_ret)
{
struct idp_type_get_state *state;
state = tevent_req_data(req, struct idp_type_get_state);
- if (dp_error_out != NULL) {
- *dp_error_out = state->dp_error;
- }
-
if (idp_ret != NULL) {
*idp_ret = state->idp_ret;
}
@@ -380,10 +371,10 @@ static struct tevent_req *idp_users_get_send(TALLOC_CTX *memctx,
noexist_delete, false, set_non_posix);
}
-static int idp_users_get_recv(struct tevent_req *req, int *dp_error_out,
+static int idp_users_get_recv(struct tevent_req *req,
int *idp_ret)
{
- return idp_type_get_recv(req, dp_error_out, idp_ret);
+ return idp_type_get_recv(req, idp_ret);
}
static struct tevent_req *idp_groups_get_send(TALLOC_CTX *memctx,
@@ -400,10 +391,10 @@ static struct tevent_req *idp_groups_get_send(TALLOC_CTX *memctx,
no_members, set_non_posix);
}
-static int idp_groups_get_recv(struct tevent_req *req, int *dp_error_out,
+static int idp_groups_get_recv(struct tevent_req *req,
int *idp_ret)
{
- return idp_type_get_recv(req, dp_error_out, idp_ret);
+ return idp_type_get_recv(req, idp_ret);
}
static struct tevent_req *idp_groups_by_user_send(TALLOC_CTX *memctx,
@@ -420,16 +411,15 @@ static struct tevent_req *idp_groups_by_user_send(TALLOC_CTX *memctx,
false, set_non_posix);
}
-static int idp_groups_by_user_recv(struct tevent_req *req, int *dp_error_out,
+static int idp_groups_by_user_recv(struct tevent_req *req,
int *idp_ret)
{
- return idp_type_get_recv(req, dp_error_out, idp_ret);
+ return idp_type_get_recv(req, idp_ret);
}
struct idp_handle_acct_req_state {
struct dp_id_data *ar;
const char *err;
- int dp_error;
int idp_ret;
};
@@ -536,15 +526,15 @@ static void idp_handle_acct_req_done(struct tevent_req *subreq)
switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
case BE_REQ_USER: /* user */
err = "User lookup failed";
- ret = idp_users_get_recv(subreq, &state->dp_error, &state->idp_ret);
+ ret = idp_users_get_recv(subreq, &state->idp_ret);
break;
case BE_REQ_GROUP: /* group */
err = "Group lookup failed";
- ret = idp_groups_get_recv(subreq, &state->dp_error, &state->idp_ret);
+ ret = idp_groups_get_recv(subreq, &state->idp_ret);
break;
case BE_REQ_INITGROUPS: /* init groups for user */
err = "Init group lookup failed";
- ret = idp_groups_by_user_recv(subreq, &state->dp_error, &state->idp_ret);
+ ret = idp_groups_by_user_recv(subreq, &state->idp_ret);
break;
default: /* fail */
ret = EINVAL;
@@ -564,17 +554,13 @@ static void idp_handle_acct_req_done(struct tevent_req *subreq)
static errno_t
idp_handle_acct_req_recv(struct tevent_req *req,
- int *_dp_error, const char **_err,
+ const char **_err,
int *idp_ret)
{
struct idp_handle_acct_req_state *state;
state = tevent_req_data(req, struct idp_handle_acct_req_state);
- if (_dp_error) {
- *_dp_error = state->dp_error;
- }
-
if (_err) {
*_err = state->err;
}
@@ -624,7 +610,7 @@ idp_account_info_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -638,17 +624,16 @@ static void idp_account_info_handler_done(struct tevent_req *subreq)
struct idp_account_info_handler_state *state;
struct tevent_req *req;
const char *error_msg = NULL;
- int dp_error = DP_ERR_FATAL;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct idp_account_info_handler_state);
- ret = idp_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL);
+ ret = idp_handle_acct_req_recv(subreq, &error_msg, NULL);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, error_msg);
+ dp_reply_std_set(&state->reply, ret, error_msg);
tevent_req_done(req);
}
diff --git a/src/providers/idp/idp_online_check.c b/src/providers/idp/idp_online_check.c
index 683ed949842..c9089335e32 100644
--- a/src/providers/idp/idp_online_check.c
+++ b/src/providers/idp/idp_online_check.c
@@ -49,7 +49,7 @@ idp_online_check_handler_send(TALLOC_CTX *mem_ctx,
/* TODO: evaluate if proper online check is needed */
ret = ENOTSUP;
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c
index 205ebe351cd..fdd576dd58f 100644
--- a/src/providers/ipa/ipa_access.c
+++ b/src/providers/ipa/ipa_access.c
@@ -217,18 +217,19 @@ static errno_t ipa_fetch_hbac_retry(struct tevent_req *req)
static void ipa_fetch_hbac_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = NULL;
- int dp_error;
+ struct ipa_fetch_hbac_state *state = NULL;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ipa_fetch_hbac_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
goto done;
}
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->be_ctx)) {
ret = EOK;
goto done;
}
@@ -293,7 +294,6 @@ static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq)
struct ipa_fetch_hbac_state *state = NULL;
struct tevent_req *req = NULL;
errno_t ret;
- int dp_error;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_fetch_hbac_state);
@@ -313,8 +313,8 @@ static void ipa_fetch_hbac_hostinfo_done(struct tevent_req *subreq)
* so that all searches are in another sub-request so that we can
* error out at any step and the parent request can call
* sdap_id_op_done just once. */
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ ret = sdap_id_op_done(state->sdap_op, ret);
+ if (ret != EOK) {
/* retry */
ret = ipa_fetch_hbac_retry(req);
if (ret != EAGAIN) {
@@ -405,7 +405,6 @@ static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq)
{
struct ipa_fetch_hbac_state *state = NULL;
struct tevent_req *req = NULL;
- int dp_error;
errno_t ret;
bool found;
@@ -427,8 +426,8 @@ static void ipa_fetch_hbac_rules_done(struct tevent_req *subreq)
goto done;
}
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ ret = sdap_id_op_done(state->sdap_op, ret);
+ if (ret != EOK) {
/* retry */
ret = ipa_fetch_hbac_retry(req);
if (ret != EAGAIN) {
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
index 3bbee7d85a8..3399d82d448 100644
--- a/src/providers/ipa/ipa_auth.c
+++ b/src/providers/ipa/ipa_auth.c
@@ -101,12 +101,12 @@ static void get_password_migration_flag_auth_done(struct tevent_req *subreq)
struct get_password_migration_flag_state *state = tevent_req_data(req,
struct get_password_migration_flag_state);
static const char *attrs[] = {IPA_CONFIG_MIGRATION_ENABLED, NULL};
- int ret, dp_error;
+ int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret) {
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->sdap_id_ctx->be)) {
DEBUG(SSSDBG_MINOR_FAILURE,
"No IPA server is available, cannot get the "
"migration flag while offline\n");
@@ -246,7 +246,6 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq)
{
struct ipa_pam_auth_handler_state *state;
struct tevent_req *req;
- int dp_err;
char *realm;
errno_t ret;
@@ -254,7 +253,7 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq)
state = tevent_req_data(req, struct ipa_pam_auth_handler_state);
state->pd->pam_status = PAM_SYSTEM_ERR;
- ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status);
talloc_free(subreq);
if (ret != EOK && state->pd->pam_status != PAM_CRED_ERR) {
DEBUG(SSSDBG_OP_FAILURE, "KRB5 auth failed [%d]: %s\n",
@@ -262,9 +261,6 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq)
goto done;
}
- if (dp_err != DP_ERR_OK) {
- goto done;
- }
if (state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM
&& state->pd->pam_status == PAM_TRY_AGAIN) {
/* Reset this to fork a new krb5_child in handle_child_send() */
@@ -468,13 +464,12 @@ static void ipa_pam_auth_handler_retry_done(struct tevent_req *subreq)
{
struct ipa_pam_auth_handler_state *state;
struct tevent_req *req;
- int dp_err;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_pam_auth_handler_state);
- ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status);
talloc_free(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv request failed.\n");
diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c
index 371a64c2bd3..f3b34754a5c 100644
--- a/src/providers/ipa/ipa_dyndns.c
+++ b/src/providers/ipa/ipa_dyndns.c
@@ -155,7 +155,6 @@ ipa_dyndns_update_send(TALLOC_CTX *mem_ctx,
static void
ipa_dyndns_update_connect_done(struct tevent_req *subreq)
{
- int dp_error;
int ret;
struct ipa_options *ctx;
struct tevent_req *req;
@@ -165,11 +164,14 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_dyndns_update_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
+ ctx = state->ipa_ctx;
+ sdap_ctx = ctx->id_ctx->sdap_id_ctx;
+
if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(sdap_ctx->be)) {
DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, "
"dynamic DNS update is skipped in offline mode.\n");
tevent_req_error(req, ERR_DYNDNS_OFFLINE);
@@ -182,9 +184,6 @@ ipa_dyndns_update_connect_done(struct tevent_req *subreq)
return;
}
- ctx = state->ipa_ctx;
- sdap_ctx = ctx->id_ctx->sdap_id_ctx;
-
/* The following three checks are here to prevent SEGFAULT
* from ticket #3076. */
if (ctx->service == NULL) {
diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c
index bf296577567..600ed95e541 100644
--- a/src/providers/ipa/ipa_id.c
+++ b/src/providers/ipa/ipa_id.c
@@ -59,8 +59,6 @@ struct ipa_resolve_user_list_state {
struct sss_domain_info *domain;
struct sss_domain_info *user_domain;
size_t user_idx;
-
- int dp_error;
};
static errno_t ipa_resolve_user_list_get_user_step(struct tevent_req *req);
@@ -90,13 +88,11 @@ ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
state->domain_name, true);
state->users = users;
state->user_idx = 0;
- state->dp_error = DP_ERR_FATAL;
ret = ipa_resolve_user_list_get_user_step(req);
if (ret == EAGAIN) {
return req;
} else if (ret == EOK) {
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
} else {
DEBUG(SSSDBG_OP_FAILURE,
@@ -166,9 +162,9 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq)
int ret;
if (state->user_domain != state->ipa_ctx->sdap_id_ctx->be->domain) {
- ret = ipa_subdomain_account_recv(subreq, &state->dp_error);
+ ret = ipa_subdomain_account_recv(subreq);
} else {
- ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
+ ret = ipa_id_get_account_info_recv(subreq);
}
talloc_zfree(subreq);
if (ret != EOK) {
@@ -189,26 +185,15 @@ static void ipa_resolve_user_list_get_user_done(struct tevent_req *subreq)
done:
if (ret == EOK) {
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
} else {
- if (state->dp_error == DP_ERR_OK) {
- state->dp_error = DP_ERR_FATAL;
- }
tevent_req_error(req, ret);
}
return;
}
-int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error)
+int ipa_resolve_user_list_recv(struct tevent_req *req)
{
- struct ipa_resolve_user_list_state *state = tevent_req_data(req,
- struct ipa_resolve_user_list_state);
-
- if (dp_error) {
- *dp_error = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -225,8 +210,6 @@ struct ipa_initgr_get_overrides_state {
const char *groups_id_attr;
size_t group_idx;
struct dp_id_data *ar;
-
- int dp_error;
};
static int ipa_initgr_get_overrides_step(struct tevent_req *req);
@@ -361,7 +344,7 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
int ret;
struct sysdb_attrs *override_attrs = NULL;
- ret = ipa_get_trusted_override_recv(subreq, &state->dp_error, state,
+ ret = ipa_get_trusted_override_recv(subreq, state,
&override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -421,15 +404,8 @@ static void ipa_initgr_get_overrides_override_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error)
+int ipa_initgr_get_overrides_recv(struct tevent_req *req)
{
- struct ipa_initgr_get_overrides_state *state = tevent_req_data(req,
- struct ipa_initgr_get_overrides_state);
-
- if (dp_error) {
- *dp_error = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
@@ -518,7 +494,6 @@ struct ipa_id_get_account_info_state {
struct ldb_result *res;
size_t res_index;
- int dp_error;
};
static void ipa_id_get_account_info_connected(struct tevent_req *subreq);
@@ -549,7 +524,6 @@ ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
state->ev = ev;
state->ipa_ctx = ipa_ctx;
state->ctx = ipa_ctx->sdap_id_ctx;
- state->dp_error = DP_ERR_FATAL;
state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
if (state->op == NULL) {
@@ -616,10 +590,9 @@ static void ipa_id_get_account_info_connected(struct tevent_req *subreq)
struct tevent_req);
struct ipa_id_get_account_info_state *state = tevent_req_data(req,
struct ipa_id_get_account_info_state);
- int dp_error = DP_ERR_FATAL;
int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n");
@@ -640,7 +613,6 @@ static void ipa_id_get_account_info_connected(struct tevent_req *subreq)
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -651,20 +623,19 @@ static void ipa_id_get_account_info_got_override(struct tevent_req *subreq)
struct tevent_req);
struct ipa_id_get_account_info_state *state = tevent_req_data(req,
struct ipa_id_get_account_info_state);
- int dp_error = DP_ERR_FATAL;
int ret;
const char *anchor = NULL;
char *anchor_domain;
char *ipa_uuid;
- ret = ipa_get_trusted_override_recv(subreq, &dp_error, state,
+ ret = ipa_get_trusted_override_recv(subreq, state,
&state->override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
- ret = sdap_id_op_done(state->op, ret, &dp_error);
+ ret = sdap_id_op_done(state->op, ret);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ if (ret == EAGAIN) {
/* retry */
subreq = sdap_id_op_connect_send(state->op, state, &ret);
if (subreq == NULL) {
@@ -736,7 +707,6 @@ static void ipa_id_get_account_info_got_override(struct tevent_req *subreq)
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -770,7 +740,6 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_id_get_account_info_state *state = tevent_req_data(req,
struct ipa_id_get_account_info_state);
- int dp_error = DP_ERR_FATAL;
int ret;
const char *attrs[] = { SYSDB_NAME,
SYSDB_UIDNUM,
@@ -781,7 +750,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
SYSDB_HOMEDIR,
NULL };
- ret = sdap_handle_acct_req_recv(subreq, &dp_error, NULL, NULL);
+ ret = sdap_handle_acct_req_recv(subreq, NULL);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_handle_acct request failed: %d\n", ret);
@@ -790,8 +759,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
if (! is_object_overridable(state->ar)) {
DEBUG(SSSDBG_FUNC_DATA, "Object not overridable, ending request\n");
- state->dp_error = DP_ERR_OK;
- tevent_req_done(req);
+ tevent_req_done(req);
return;
}
@@ -825,8 +793,7 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
&state->obj_msg);
if (ret == ENOENT) {
DEBUG(SSSDBG_MINOR_FAILURE, "Object not found, ending request\n");
- state->dp_error = DP_ERR_OK;
- tevent_req_done(req);
+ tevent_req_done(req);
return;
} else if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "get_object_from_cache failed.\n");
@@ -842,12 +809,10 @@ static void ipa_id_get_account_info_orig_done(struct tevent_req *subreq)
goto fail;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -999,12 +964,11 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_id_get_account_info_state *state = tevent_req_data(req,
struct ipa_id_get_account_info_state);
- int dp_error = DP_ERR_FATAL;
int ret;
const char *class;
enum sysdb_member_type type;
- ret = ipa_get_trusted_override_recv(subreq, &dp_error, state,
+ ret = ipa_get_trusted_override_recv(subreq, state,
&state->override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -1089,12 +1053,10 @@ static void ipa_id_get_account_info_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -1105,10 +1067,9 @@ static void ipa_id_get_user_list_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_id_get_account_info_state *state = tevent_req_data(req,
struct ipa_id_get_account_info_state);
- int dp_error = DP_ERR_FATAL;
int ret;
- ret = ipa_resolve_user_list_recv(subreq, &dp_error);
+ ret = ipa_resolve_user_list_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user list %d\n", ret);
@@ -1127,12 +1088,10 @@ static void ipa_id_get_user_list_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -1143,10 +1102,9 @@ static void ipa_id_get_user_groups_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_id_get_account_info_state *state = tevent_req_data(req,
struct ipa_id_get_account_info_state);
- int dp_error = DP_ERR_FATAL;
int ret;
- ret = ipa_initgr_get_overrides_recv(subreq, &dp_error);
+ ret = ipa_initgr_get_overrides_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "IPA resolve user groups %d\n", ret);
@@ -1165,25 +1123,16 @@ static void ipa_id_get_user_groups_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
-int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error)
+int ipa_id_get_account_info_recv(struct tevent_req *req)
{
- struct ipa_id_get_account_info_state *state = tevent_req_data(req,
- struct ipa_id_get_account_info_state);
-
- if (dp_error) {
- *dp_error = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -1207,8 +1156,6 @@ struct ipa_id_get_netgroup_state {
size_t count;
struct sysdb_attrs **netgroups;
-
- int dp_error;
};
static void ipa_id_get_netgroup_connected(struct tevent_req *subreq);
@@ -1233,7 +1180,6 @@ static struct tevent_req *ipa_id_get_netgroup_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ipa_ctx;
- state->dp_error = DP_ERR_FATAL;
state->op = sdap_id_op_create(state, ctx->conn->conn_cache);
if (!state->op) {
@@ -1288,15 +1234,13 @@ static void ipa_id_get_netgroup_connected(struct tevent_req *subreq)
tevent_req_callback_data(subreq, struct tevent_req);
struct ipa_id_get_netgroup_state *state =
tevent_req_data(req, struct ipa_id_get_netgroup_state);
- int dp_error = DP_ERR_FATAL;
int ret;
struct sdap_id_ctx *sdap_ctx = state->ctx->sdap_id_ctx;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -1322,15 +1266,14 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq)
tevent_req_callback_data(subreq, struct tevent_req);
struct ipa_id_get_netgroup_state *state =
tevent_req_data(req, struct ipa_id_get_netgroup_state);
- int dp_error = DP_ERR_FATAL;
int ret;
ret = ipa_get_netgroups_recv(subreq, state,
&state->count, &state->netgroups);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
+ ret = sdap_id_op_done(state->op, ret);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ if (ret == EAGAIN) {
/* retry */
subreq = sdap_id_op_connect_send(state->op, state, &ret);
if (!subreq) {
@@ -1342,7 +1285,6 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq)
}
if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -1363,20 +1305,12 @@ static void ipa_id_get_netgroup_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
}
-static int ipa_id_get_netgroup_recv(struct tevent_req *req, int *dp_error)
+static int ipa_id_get_netgroup_recv(struct tevent_req *req)
{
- struct ipa_id_get_netgroup_state *state =
- tevent_req_data(req, struct ipa_id_get_netgroup_state);
-
- if (dp_error) {
- *dp_error = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -1404,7 +1338,6 @@ struct ipa_account_info_state {
enum ipa_account_info_type type;
const char *err_msg;
- int dp_error;
};
static void ipa_account_info_done(struct tevent_req *subreq);
@@ -1472,13 +1405,13 @@ static void ipa_account_info_done(struct tevent_req *subreq)
switch (state->type) {
case IPA_ACCOUNT_INFO_SUBDOMAIN:
- ret = ipa_subdomain_account_recv(subreq, &state->dp_error);
+ ret = ipa_subdomain_account_recv(subreq);
break;
case IPA_ACCOUNT_INFO_NETGROUP:
- ret = ipa_id_get_netgroup_recv(subreq, &state->dp_error);
+ ret = ipa_id_get_netgroup_recv(subreq);
break;
case IPA_ACCOUNT_INFO_OTHER:
- ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
+ ret = ipa_id_get_account_info_recv(subreq);
break;
default:
ret = EINVAL;
@@ -1494,18 +1427,8 @@ static void ipa_account_info_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-errno_t ipa_account_info_recv(struct tevent_req *req,
- int *_dp_error)
+errno_t ipa_account_info_recv(struct tevent_req *req)
{
- struct ipa_account_info_state *state = NULL;
-
- state = tevent_req_data(req, struct ipa_account_info_state);
-
- /* Fail the request after collecting the dp_error */
- if (_dp_error) {
- *_dp_error = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
@@ -1550,7 +1473,7 @@ ipa_account_info_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -1563,17 +1486,16 @@ static void ipa_account_info_handler_done(struct tevent_req *subreq)
{
struct ipa_account_info_handler_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret = ERR_INTERNAL;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_account_info_handler_state);
- ret = ipa_account_info_recv(subreq, &dp_error);
+ ret = ipa_account_info_recv(subreq);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h
index 2c641130293..9e22dae301c 100644
--- a/src/providers/ipa/ipa_id.h
+++ b/src/providers/ipa/ipa_id.h
@@ -38,8 +38,7 @@ ipa_account_info_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct ipa_id_ctx *id_ctx,
struct dp_id_data *data);
-errno_t ipa_account_info_recv(struct tevent_req *req,
- int *_dp_error);
+errno_t ipa_account_info_recv(struct tevent_req *req);
struct tevent_req *
ipa_account_info_handler_send(TALLOC_CTX *mem_ctx,
@@ -83,7 +82,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
struct ipa_id_ctx *ipa_ctx,
struct sysdb_attrs *override_attrs,
struct dp_id_data *ar);
-int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out);
+int ipa_get_subdom_acct_recv(struct tevent_req *req);
errno_t get_dp_id_data_for_sid(TALLOC_CTX *mem_ctx, const char *sid,
const char *domain_name,
@@ -106,7 +105,7 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx,
const char *view_name,
struct dp_id_data *ar);
-errno_t ipa_get_trusted_override_recv(struct tevent_req *req, int *dp_error_out,
+errno_t ipa_get_trusted_override_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct sysdb_attrs **override_attrs);
@@ -115,7 +114,7 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx,
struct ipa_id_ctx *ipa_ctx,
struct dp_id_data *ar);
-errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out);
+errno_t ipa_subdomain_account_recv(struct tevent_req *req);
errno_t split_ipa_anchor(TALLOC_CTX *mem_ctx, const char *anchor,
char **_anchor_domain, char **_ipa_uuid);
@@ -133,7 +132,7 @@ ipa_initgr_get_overrides_send(TALLOC_CTX *memctx,
size_t groups_count,
struct ldb_message **groups,
const char *groups_id_attr);
-int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error);
+int ipa_initgr_get_overrides_recv(struct tevent_req *req);
struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -149,11 +148,11 @@ ipa_resolve_user_list_send(TALLOC_CTX *memctx, struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
const char *domain_name,
struct ldb_message_element *users);
-int ipa_resolve_user_list_recv(struct tevent_req *req, int *dp_error);
+int ipa_resolve_user_list_recv(struct tevent_req *req);
struct tevent_req *
ipa_id_get_account_info_send(TALLOC_CTX *memctx, struct tevent_context *ev,
struct ipa_id_ctx *ipa_ctx,
struct dp_id_data *ar);
-int ipa_id_get_account_info_recv(struct tevent_req *req, int *dp_error);
+int ipa_id_get_account_info_recv(struct tevent_req *req);
#endif
diff --git a/src/providers/ipa/ipa_refresh.c b/src/providers/ipa/ipa_refresh.c
index 64f8db81225..8106d75c651 100644
--- a/src/providers/ipa/ipa_refresh.c
+++ b/src/providers/ipa/ipa_refresh.c
@@ -134,18 +134,17 @@ static void ipa_refresh_done(struct tevent_req *subreq)
{
struct ipa_refresh_state *state = NULL;
struct tevent_req *req = NULL;
- errno_t dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_refresh_state);
- ret = ipa_account_info_recv(subreq, &dp_error);
+ ret = ipa_account_info_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, "
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s, "
"errno: %d]\n", be_req2str(state->account_req->entry_type),
- dp_error, ret);
+ ret);
goto done;
}
diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c
index 4ca814654a5..cf70031650c 100644
--- a/src/providers/ipa/ipa_s2n_exop.c
+++ b/src/providers/ipa/ipa_s2n_exop.c
@@ -1542,17 +1542,15 @@ static void ipa_s2n_get_list_next(struct tevent_req *subreq)
static void ipa_s2n_get_list_ipa_next(struct tevent_req *subreq)
{
int ret;
- int dp_error;
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct ipa_s2n_get_list_state *state = tevent_req_data(req,
struct ipa_s2n_get_list_state);
- ret = ipa_id_get_account_info_recv(subreq, &dp_error);
+ ret = ipa_id_get_account_info_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d %d\n", ret,
- dp_error);
+ DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d\n", ret);
goto done;
}
@@ -1583,7 +1581,7 @@ static void ipa_s2n_get_list_get_override_done(struct tevent_req *subreq)
struct ipa_s2n_get_list_state *state = tevent_req_data(req,
struct ipa_s2n_get_list_state);
- ret = ipa_get_trusted_override_recv(subreq, NULL, state, &state->override_attrs);
+ ret = ipa_get_trusted_override_recv(subreq, state, &state->override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
@@ -3068,7 +3066,7 @@ static void ipa_s2n_get_user_get_override_done(struct tevent_req *subreq)
struct ipa_s2n_get_user_state);
struct sysdb_attrs *override_attrs = NULL;
- ret = ipa_get_trusted_override_recv(subreq, NULL, state, &override_attrs);
+ ret = ipa_get_trusted_override_recv(subreq, state, &override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "IPA override lookup failed: %d\n", ret);
diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
index f2db640f9e4..9d902c781c3 100644
--- a/src/providers/ipa/ipa_selinux.c
+++ b/src/providers/ipa/ipa_selinux.c
@@ -809,17 +809,16 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_get_selinux_state *state = tevent_req_data(req,
struct ipa_get_selinux_state);
- int dp_error = DP_ERR_FATAL;
int ret;
struct ipa_id_ctx *id_ctx = state->selinux_ctx->id_ctx;
struct dp_module *access_mod;
struct dp_module *selinux_mod;
const char *hostname;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->be_ctx)) {
talloc_zfree(state->op);
ret = ipa_get_selinux_maps_offline(req);
if (ret == EOK) {
diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c
index 47c10b6d277..2fef7cb94f1 100644
--- a/src/providers/ipa/ipa_session.c
+++ b/src/providers/ipa/ipa_session.c
@@ -208,12 +208,11 @@ static void
ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = NULL;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
goto done;
@@ -355,7 +354,6 @@ ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct ipa_fetch_deskprofile_state *state;
- int dp_error;
errno_t ret;
bool found;
@@ -378,15 +376,8 @@ ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq)
goto done;
}
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = ipa_fetch_deskprofile_retry(req);
- if (ret != EAGAIN) {
- tevent_req_error(req, ret);
- }
- return;
- } else if (ret != EOK) {
+ ret = sdap_id_op_done(state->sdap_op, ret);
+ if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c
index 6c93c847689..0144b521e09 100644
--- a/src/providers/ipa/ipa_subdomains.c
+++ b/src/providers/ipa/ipa_subdomains.c
@@ -2957,19 +2957,18 @@ static void ipa_subdomains_refresh_connect_done(struct tevent_req *subreq)
{
struct ipa_subdomains_refresh_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_subdomains_refresh_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to LDAP "
"[%d]: %s\n", ret, sss_strerror(ret));
- if (dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->sd_ctx->be_ctx)) {
DEBUG(SSSDBG_MINOR_FAILURE, "No IPA server is available, "
"cannot get the subdomain list while offline\n");
ret = ERR_OFFLINE;
@@ -3201,7 +3200,6 @@ ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq)
{
struct ipa_subdomains_refresh_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
@@ -3216,14 +3214,7 @@ ipa_domain_refresh_resolution_order_done(struct tevent_req *subreq)
/* Not good, but let's try to continue with other server side options */
}
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = ipa_subdomains_refresh_retry(req);
- } else if (dp_error == DP_ERR_OFFLINE) {
- ret = ERR_OFFLINE;
- }
-
+ ret = sdap_id_op_done(state->sdap_op, ret);
if (ret != EOK) {
DEBUG(SSSDBG_TRACE_FUNC, "Unable to refresh subdomains [%d]: %s\n",
ret, sss_strerror(ret));
@@ -3313,7 +3304,7 @@ ipa_subdomains_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -3339,7 +3330,7 @@ static void ipa_subdomains_handler_done(struct tevent_req *subreq)
}
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h
index 13e82464376..110dc6f4691 100644
--- a/src/providers/ipa/ipa_subdomains.h
+++ b/src/providers/ipa/ipa_subdomains.h
@@ -172,7 +172,7 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx,
struct sdap_id_ctx *sdap_id_ctx,
const char *domain);
-errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req, int *dp_error_out);
+errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req);
struct tevent_req *ipa_ext_group_member_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c
index 50b95bb3791..0297a3398f1 100644
--- a/src/providers/ipa/ipa_subdomains_ext_groups.c
+++ b/src/providers/ipa/ipa_subdomains_ext_groups.c
@@ -525,7 +525,6 @@ struct get_trusted_membership_state {
char *user_name;
struct sss_domain_info *user_dom;
- int dp_error;
const char *domain;
size_t reply_count;
struct sysdb_attrs **reply;
@@ -534,8 +533,7 @@ struct get_trusted_membership_state {
static void ipa_get_trusted_memberships_connect_done(struct tevent_req *subreq);
static void ipa_get_ext_groups_done(struct tevent_req *subreq);
static errno_t ipa_add_ext_groups_step(struct tevent_req *req);
-static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req,
- int *dp_error_out);
+static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req);
struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -561,7 +559,6 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx,
state->sdap_id_ctx = sdap_id_ctx;
state->srv = NULL;
state->domain = domain;
- state->dp_error = -1;
if (((ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_INITGROUPS
&& (ar->entry_type & BE_REQ_TYPE_MASK) != BE_REQ_USER)
@@ -624,10 +621,8 @@ struct tevent_req *ipa_get_trusted_memberships_send(TALLOC_CTX *mem_ctx,
done:
if (ret != EOK) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
} else {
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
tevent_req_post(req, state->ev);
@@ -643,10 +638,10 @@ static void ipa_get_trusted_memberships_connect_done(struct tevent_req *subreq)
struct get_trusted_membership_state);
int ret;
- ret = sdap_id_op_connect_recv(subreq, &state->dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (state->dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->sdap_id_ctx->be)) {
DEBUG(SSSDBG_MINOR_FAILURE,
"No IPA server is available, going offline\n");
} else {
@@ -755,7 +750,6 @@ static errno_t ipa_add_ext_groups_step(struct tevent_req *req)
if (user_dn == NULL) {
DEBUG(SSSDBG_TRACE_ALL, "User [%s] not found in cache.\n",
state->user_name);
- state->dp_error = DP_ERR_OK;
return EOK;
}
@@ -780,11 +774,9 @@ static void ipa_add_trusted_memberships_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
- struct get_trusted_membership_state *state = tevent_req_data(req,
- struct get_trusted_membership_state);
int ret;
- ret = ipa_add_trusted_memberships_recv(subreq, &state->dp_error);
+ ret = ipa_add_trusted_memberships_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_add_ad_memberships request failed.\n");
@@ -792,22 +784,14 @@ static void ipa_add_trusted_memberships_done(struct tevent_req *subreq)
return;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
}
-errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req, int *dp_error_out)
+errno_t ipa_get_trusted_memberships_recv(struct tevent_req *req)
{
- struct get_trusted_membership_state *state = tevent_req_data(req,
- struct get_trusted_membership_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
return EOK;
}
@@ -873,7 +857,6 @@ struct add_trusted_membership_state {
char **orig_groups; /* a superset of `groups`, memory is shared */
char **groups;
char **missing_groups;
- int dp_error;
size_t iter;
struct sdap_domain *group_sdom;
};
@@ -929,7 +912,6 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx,
goto done;
}
- state->dp_error = -1;
state->iter = 0;
state->group_sdom = sdap_domain_get(sdap_id_ctx->opts, group_dom);
if (state->group_sdom == NULL) {
@@ -971,10 +953,8 @@ static struct tevent_req *ipa_add_trusted_memberships_send(TALLOC_CTX *mem_ctx,
done:
if (ret != EOK) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
} else {
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
tevent_req_post(req, state->ev);
@@ -990,10 +970,10 @@ static void ipa_add_trusted_memberships_connect_done(struct tevent_req *subreq)
struct add_trusted_membership_state);
int ret;
- ret = sdap_id_op_connect_recv(subreq, &state->dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (state->dp_error == DP_ERR_OFFLINE) {
+ if (be_is_offline(state->sdap_id_ctx->be)) {
DEBUG(SSSDBG_MINOR_FAILURE,
"No IPA server is available, going offline\n");
} else {
@@ -1073,10 +1053,10 @@ static void ipa_add_trusted_memberships_get_next(struct tevent_req *req)
* directly fetch the group with the corresponding DN. */
subreq = groups_get_send(state, state->ev,
state->sdap_id_ctx, state->group_sdom,
- state->sdap_id_ctx->conn,
fq_name,
BE_FILTER_NAME,
- false, false, false);
+ false, false, false,
+ state->sdap_id_ctx->conn->no_mpg_user_fallback);
if (subreq == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n");
ret = ENOMEM;
@@ -1098,7 +1078,7 @@ static void ipa_add_trusted_memberships_get_group_done(struct tevent_req *subreq
struct add_trusted_membership_state);
int ret;
- ret = groups_get_recv(subreq, &state->dp_error, NULL);
+ ret = groups_get_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Failed to read group [%s] from LDAP [%d](%s)\n",
@@ -1112,18 +1092,10 @@ static void ipa_add_trusted_memberships_get_group_done(struct tevent_req *subreq
ipa_add_trusted_memberships_get_next(req);
}
-static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req,
- int *dp_error_out)
+static errno_t ipa_add_trusted_memberships_recv(struct tevent_req *req)
{
- struct add_trusted_membership_state *state = tevent_req_data(req,
- struct add_trusted_membership_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
return EOK;
}
@@ -1346,10 +1318,10 @@ static void ipa_ext_group_member_done(struct tevent_req *subreq)
DEBUG(SSSDBG_OP_FAILURE, "dp_req_recv failed\n");
tevent_req_error(req, ret);
return;
- } else if (reply->dp_error != DP_ERR_OK) {
+ } else if (reply->error != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
- "Cannot refresh data from DP: %u,%u: %s\n",
- reply->dp_error, reply->error, reply->message);
+ "Cannot refresh data from DP: %u: %s\n",
+ reply->error, reply->message);
tevent_req_error(req, EIO);
return;
}
diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c
index 4647aa85901..5312af8f53e 100644
--- a/src/providers/ipa/ipa_subdomains_id.c
+++ b/src/providers/ipa/ipa_subdomains_id.c
@@ -45,7 +45,7 @@ ipa_srv_acct_send(TALLOC_CTX *mem_ctx,
struct sysdb_attrs *override_attrs,
struct dp_id_data *ar);
static errno_t
-ipa_srv_acct_recv(struct tevent_req *req, int *dp_error_out);
+ipa_srv_acct_recv(struct tevent_req *req);
struct ipa_subdomain_account_state {
struct tevent_context *ev;
@@ -64,8 +64,6 @@ struct ipa_subdomain_account_state {
struct sysdb_attrs *override_attrs;
struct sysdb_attrs *mapped_attrs;
char *object_sid;
-
- int dp_error;
};
static void ipa_subdomain_account_connected(struct tevent_req *subreq);
@@ -93,7 +91,6 @@ struct tevent_req *ipa_subdomain_account_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ipa_ctx = ipa_ctx;
state->ctx = ipa_ctx->sdap_id_ctx;
- state->dp_error = DP_ERR_FATAL;
state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
if (!state->op) {
@@ -161,10 +158,9 @@ static void ipa_subdomain_account_connected(struct tevent_req *subreq)
struct tevent_req);
struct ipa_subdomain_account_state *state = tevent_req_data(req,
struct ipa_subdomain_account_state);
- int dp_error = DP_ERR_FATAL;
int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect request failed.\n");
@@ -187,7 +183,6 @@ static void ipa_subdomain_account_connected(struct tevent_req *subreq)
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -201,18 +196,17 @@ static void ipa_subdomain_account_got_override(struct tevent_req *subreq)
struct tevent_req);
struct ipa_subdomain_account_state *state = tevent_req_data(req,
struct ipa_subdomain_account_state);
- int dp_error = DP_ERR_FATAL;
int ret;
const char *anchor = NULL;
struct dp_id_data *ar;
- ret = ipa_get_trusted_override_recv(subreq, &dp_error, state,
+ ret = ipa_get_trusted_override_recv(subreq, state,
&state->override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
- ret = sdap_id_op_done(state->op, ret, &dp_error);
+ ret = sdap_id_op_done(state->op, ret);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ if (ret == EAGAIN) {
/* retry */
subreq = sdap_id_op_connect_send(state->op, state, &ret);
if (subreq == NULL) {
@@ -326,7 +320,6 @@ static void ipa_subdomain_account_got_override(struct tevent_req *subreq)
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -363,21 +356,19 @@ static void ipa_subdomain_account_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_subdomain_account_state *state = tevent_req_data(req,
struct ipa_subdomain_account_state);
- int dp_error = DP_ERR_FATAL;
int ret;
struct ldb_result *res;
struct sss_domain_info *object_dom;
if (state->ipa_server_mode) {
- ret = ipa_srv_acct_recv(subreq, &dp_error);
+ ret = ipa_srv_acct_recv(subreq);
} else {
- ret = ipa_get_subdom_acct_recv(subreq, &dp_error);
+ ret = ipa_get_subdom_acct_recv(subreq);
}
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_get_*_acct request failed: [%d]: %s.\n",
ret, sss_strerror(ret));
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -406,20 +397,12 @@ static void ipa_subdomain_account_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
}
-errno_t ipa_subdomain_account_recv(struct tevent_req *req, int *dp_error_out)
+errno_t ipa_subdomain_account_recv(struct tevent_req *req)
{
- struct ipa_subdomain_account_state *state = tevent_req_data(req,
- struct ipa_subdomain_account_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -440,8 +423,6 @@ struct ipa_get_subdom_acct {
const char *extra_value;
bool use_pac;
struct ldb_message *user_msg;
-
- int dp_error;
};
static void ipa_get_subdom_acct_connected(struct tevent_req *subreq);
@@ -464,7 +445,6 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ipa_ctx = ipa_ctx;
state->ctx = ipa_ctx->sdap_id_ctx;
- state->dp_error = DP_ERR_FATAL;
state->override_attrs = override_attrs;
state->use_pac = false;
@@ -538,16 +518,14 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq)
struct tevent_req);
struct ipa_get_subdom_acct *state = tevent_req_data(req,
struct ipa_get_subdom_acct);
- int dp_error = DP_ERR_FATAL;
int ret;
char *endptr;
struct req_input *req_input;
char *shortname;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -659,14 +637,12 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq)
} else {
DEBUG(SSSDBG_OP_FAILURE,
"Lookup by certificate not supported by the server.\n");
- state->dp_error = DP_ERR_OK;
tevent_req_error(req, EINVAL);
return;
}
break;
default:
DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain filter type.\n");
- state->dp_error = dp_error;
tevent_req_error(req, EINVAL);
return;
}
@@ -695,14 +671,13 @@ static void ipa_get_subdom_acct_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_get_subdom_acct *state = tevent_req_data(req,
struct ipa_get_subdom_acct);
- int dp_error = DP_ERR_FATAL;
int ret;
ret = ipa_s2n_get_acct_info_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
+ ret = sdap_id_op_done(state->op, ret);
+ if (ret != EOK) {
/* retry */
subreq = sdap_id_op_connect_send(state->op, state, &ret);
if (!subreq) {
@@ -714,26 +689,17 @@ static void ipa_get_subdom_acct_done(struct tevent_req *subreq)
}
if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
/* FIXME: do we need some special handling of ENOENT */
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
-int ipa_get_subdom_acct_recv(struct tevent_req *req, int *dp_error_out)
+int ipa_get_subdom_acct_recv(struct tevent_req *req)
{
- struct ipa_get_subdom_acct *state = tevent_req_data(req,
- struct ipa_get_subdom_acct);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -787,7 +753,6 @@ ipa_ad_gc_conn_list(TALLOC_CTX *mem_ctx, struct ipa_id_ctx *ipa_ctx,
/* IPA lookup for server mode. AD or IPA subdomain */
struct ipa_get_acct_state {
- int dp_error;
struct tevent_context *ev;
struct ipa_id_ctx *ipa_ctx;
struct dp_id_data *ar;
@@ -828,7 +793,6 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
req = tevent_req_create(mem_ctx, &state, struct ipa_get_acct_state);
if (req == NULL) return NULL;
- state->dp_error = -1;
state->ev = ev;
state->ipa_ctx = ipa_ctx;
state->ar = ar;
@@ -891,7 +855,6 @@ ipa_get_ad_acct_send(TALLOC_CTX *mem_ctx,
return req;
fail:
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
tevent_req_post(req, ev);
return req;
@@ -958,7 +921,6 @@ ipa_get_ipa_acct_send(TALLOC_CTX *mem_ctx,
req = tevent_req_create(mem_ctx, &state, struct ipa_get_acct_state);
if (req == NULL) return NULL;
- state->dp_error = -1;
state->ev = ev;
state->ipa_ctx = ipa_ctx;
state->ar = ar;
@@ -999,7 +961,6 @@ ipa_get_ipa_acct_send(TALLOC_CTX *mem_ctx,
return req;
fail:
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
tevent_req_post(req, ev);
return req;
@@ -1365,7 +1326,6 @@ errno_t get_object_from_cache(TALLOC_CTX *mem_ctx,
static void ipa_get_sid_ipa_next(struct tevent_req *subreq)
{
int ret;
- int dp_error = DP_ERR_FATAL;
const char *sid;
const char *user;
struct ldb_message *user_msg;
@@ -1376,11 +1336,10 @@ static void ipa_get_sid_ipa_next(struct tevent_req *subreq)
struct ipa_get_acct_state *state = tevent_req_data(req,
struct ipa_get_acct_state);
- ret = ipa_subdomain_account_recv(subreq, &state->dp_error);
+ ret = ipa_subdomain_account_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d %d\n", ret,
- dp_error);
+ DEBUG(SSSDBG_OP_FAILURE, "ipa_id_get_account_info failed: %d \n", ret);
goto done;
}
@@ -1472,9 +1431,9 @@ ipa_get_trusted_acct_part_done(struct tevent_req *subreq)
struct dp_id_data *user_ar;
if (state->type == IPA_TRUST_AD) {
- ret = ad_handle_acct_info_recv(subreq, &state->dp_error, NULL);
+ ret = ad_handle_acct_info_recv(subreq, NULL);
} else if (state->type == IPA_TRUST_IPA) {
- ret = ipa_id_get_account_info_recv(subreq, &state->dp_error);
+ ret = ipa_id_get_account_info_recv(subreq);
} else {
ret = EINVAL;
}
@@ -1591,7 +1550,6 @@ ipa_get_trusted_acct_part_done(struct tevent_req *subreq)
return;
fail:
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -1606,7 +1564,7 @@ ipa_get_trusted_override_done(struct tevent_req *subreq)
struct ipa_get_acct_state);
errno_t ret;
- ret = ipa_get_trusted_override_recv(subreq, &state->dp_error, state,
+ ret = ipa_get_trusted_override_recv(subreq, state,
&state->override_attrs);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -1625,7 +1583,6 @@ ipa_get_trusted_override_done(struct tevent_req *subreq)
return;
fail:
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -1678,7 +1635,7 @@ static void ipa_check_ghost_members_done(struct tevent_req *subreq)
struct tevent_req);
int ret;
- ret = ipa_resolve_user_list_recv(subreq, NULL);
+ ret = ipa_resolve_user_list_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "ipa_resolve_user_list request failed [%d]\n",
@@ -1825,7 +1782,7 @@ static void ipa_id_get_groups_overrides_done(struct tevent_req *subreq)
struct tevent_req);
errno_t ret;
- ret = ipa_initgr_get_overrides_recv(subreq, NULL);
+ ret = ipa_initgr_get_overrides_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
@@ -1872,11 +1829,9 @@ ipa_get_trusted_acct_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
- struct ipa_get_acct_state *state = tevent_req_data(req,
- struct ipa_get_acct_state);
errno_t ret;
- ret = ipa_get_trusted_memberships_recv(subreq, &state->dp_error);
+ ret = ipa_get_trusted_memberships_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "IPA external groups lookup failed: %d\n",
@@ -1890,15 +1845,8 @@ ipa_get_trusted_acct_done(struct tevent_req *subreq)
}
static errno_t
-ipa_get_acct_recv(struct tevent_req *req, int *dp_error_out)
+ipa_get_acct_recv(struct tevent_req *req)
{
- struct ipa_get_acct_state *state = tevent_req_data(req,
- struct ipa_get_acct_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -1914,8 +1862,6 @@ struct ipa_srv_acct_state {
struct be_ctx *be_ctx;
enum ipa_trust_type type;
bool retry;
-
- int dp_error;
};
static int ipa_srv_acct_lookup_step(struct tevent_req *req);
@@ -1943,7 +1889,6 @@ ipa_srv_acct_send(TALLOC_CTX *mem_ctx,
state->override_attrs = override_attrs;
state->ar = ar;
state->retry = true;
- state->dp_error = DP_ERR_FATAL;
state->be_ctx = ipa_ctx->sdap_id_ctx->be;
state->obj_dom = find_domain_by_name(
@@ -2002,13 +1947,12 @@ static int ipa_srv_acct_lookup_step(struct tevent_req *req)
static void ipa_srv_acct_lookup_done(struct tevent_req *subreq)
{
errno_t ret;
- int dp_error = DP_ERR_FATAL;
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct ipa_srv_acct_state *state = tevent_req_data(req,
struct ipa_srv_acct_state);
- ret = ipa_get_acct_recv(subreq, &dp_error);
+ ret = ipa_get_acct_recv(subreq);
talloc_free(subreq);
if (ret == ERR_SUBDOM_INACTIVE && state->retry == true) {
@@ -2033,12 +1977,10 @@ static void ipa_srv_acct_lookup_done(struct tevent_req *subreq)
goto fail;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
fail:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
}
@@ -2056,7 +1998,6 @@ static void ipa_srv_acct_retried(struct tevent_req *subreq)
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Failed to re-set subdomain [%d]: %s\n", ret, sss_strerror(ret));
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -2065,7 +2006,6 @@ static void ipa_srv_acct_retried(struct tevent_req *subreq)
ad_id_ctx = ipa_get_ad_id_ctx(state->ipa_ctx, state->obj_dom);
if (ad_id_ctx == NULL || ad_id_ctx->ad_options == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "No AD ID ctx or no ID CTX options?\n");
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, EINVAL);
return;
}
@@ -2076,22 +2016,14 @@ static void ipa_srv_acct_retried(struct tevent_req *subreq)
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
"Failed to look up AD acct [%d]: %s\n", ret, sss_strerror(ret));
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
}
static errno_t
-ipa_srv_acct_recv(struct tevent_req *req, int *dp_error_out)
+ipa_srv_acct_recv(struct tevent_req *req)
{
- struct ipa_srv_acct_state *state = tevent_req_data(req,
- struct ipa_srv_acct_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
diff --git a/src/providers/ipa/ipa_sudo.c b/src/providers/ipa/ipa_sudo.c
index 32ff1ceced1..2d3a7f5e61f 100644
--- a/src/providers/ipa/ipa_sudo.c
+++ b/src/providers/ipa/ipa_sudo.c
@@ -80,7 +80,7 @@ ipa_sudo_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -93,7 +93,6 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq)
{
struct ipa_sudo_handler_state *state;
struct tevent_req *req;
- int dp_error;
bool deleted;
errno_t ret;
@@ -102,17 +101,17 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq)
switch (state->type) {
case BE_REQ_SUDO_FULL:
- ret = ipa_sudo_full_refresh_recv(subreq, &dp_error);
+ ret = ipa_sudo_full_refresh_recv(subreq);
talloc_zfree(subreq);
/* Postpone the periodic task since the refresh was just finished
* per user request. */
- if (ret == EOK && dp_error == DP_ERR_OK) {
+ if (ret == EOK) {
be_ptask_postpone(state->sudo_ctx->full_refresh);
}
break;
case BE_REQ_SUDO_RULES:
- ret = ipa_sudo_rules_refresh_recv(subreq, &dp_error, &deleted);
+ ret = ipa_sudo_rules_refresh_recv(subreq, &deleted);
talloc_zfree(subreq);
if (ret == EOK && deleted == true) {
ret = ENOENT;
@@ -120,13 +119,12 @@ static void ipa_sudo_handler_done(struct tevent_req *subreq)
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", state->type);
- dp_error = DP_ERR_FATAL;
ret = ERR_INTERNAL;
break;
}
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ipa/ipa_sudo.h b/src/providers/ipa/ipa_sudo.h
index 026fc290d9f..7c86814b695 100644
--- a/src/providers/ipa/ipa_sudo.h
+++ b/src/providers/ipa/ipa_sudo.h
@@ -47,12 +47,10 @@ ipa_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
struct ipa_sudo_ctx *sudo_ctx);
int
-ipa_sudo_full_refresh_recv(struct tevent_req *req,
- int *dp_error);
+ipa_sudo_full_refresh_recv(struct tevent_req *req);
int
ipa_sudo_rules_refresh_recv(struct tevent_req *req,
- int *dp_error,
bool *deleted);
struct tevent_req *
@@ -72,7 +70,6 @@ ipa_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
errno_t
ipa_sudo_refresh_recv(struct tevent_req *req,
- int *dp_error,
size_t *_num_rules);
struct ipa_sudo_conv;
diff --git a/src/providers/ipa/ipa_sudo_async.c b/src/providers/ipa/ipa_sudo_async.c
index c531ecbf9e8..a903422351f 100644
--- a/src/providers/ipa/ipa_sudo_async.c
+++ b/src/providers/ipa/ipa_sudo_async.c
@@ -851,7 +851,6 @@ struct ipa_sudo_refresh_state {
struct sdap_id_op *sdap_op;
struct sdap_handle *sh;
- int dp_error;
struct sysdb_attrs **rules;
size_t num_rules;
@@ -887,7 +886,6 @@ ipa_sudo_refresh_send(TALLOC_CTX *mem_ctx,
state->sudo_ctx = sudo_ctx;
state->ipa_opts = sudo_ctx->ipa_opts;
state->sdap_opts = sudo_ctx->sdap_opts;
- state->dp_error = DP_ERR_FATAL;
state->update_usn = update_usn;
state->sdap_op = sdap_id_op_create(state,
@@ -960,19 +958,17 @@ ipa_sudo_refresh_connect_done(struct tevent_req *subreq)
struct ipa_sudo_refresh_state *state;
const char *hostname;
struct tevent_req *req;
- int dp_error;
int ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_sudo_refresh_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "SUDO LDAP connection failed "
"[%d]: %s\n", ret, strerror(ret));
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -991,7 +987,6 @@ ipa_sudo_refresh_connect_done(struct tevent_req *subreq)
state->ipa_opts->hostgroup_map,
state->ipa_opts->id->sdom->host_search_bases);
if (subreq == NULL) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
@@ -1012,7 +1007,6 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq)
host = talloc_zero(state, struct ipa_hostinfo);
if (host == NULL) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
@@ -1023,7 +1017,6 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq)
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve host information "
"[%d]: %s\n", ret, sss_strerror(ret));
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -1036,7 +1029,6 @@ ipa_sudo_refresh_host_done(struct tevent_req *subreq)
state->ipa_opts->hostgroup_map, state->sh,
state->cmdgroups_filter, state->search_filter);
if (subreq == NULL) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
@@ -1061,8 +1053,8 @@ ipa_sudo_refresh_done(struct tevent_req *subreq)
&state->num_rules, &usn);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error);
- if (state->dp_error == DP_ERR_OK && ret != EOK) {
+ ret = sdap_id_op_done(state->sdap_op, ret);
+ if (ret == EAGAIN) {
/* retry */
ret = ipa_sudo_refresh_retry(req);
if (ret != EOK) {
@@ -1123,7 +1115,6 @@ ipa_sudo_refresh_done(struct tevent_req *subreq)
errno_t
ipa_sudo_refresh_recv(struct tevent_req *req,
- int *dp_error,
size_t *_num_rules)
{
struct ipa_sudo_refresh_state *state = NULL;
@@ -1131,8 +1122,6 @@ ipa_sudo_refresh_recv(struct tevent_req *req,
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
if (_num_rules != NULL) {
*_num_rules = state->num_rules;
}
diff --git a/src/providers/ipa/ipa_sudo_refresh.c b/src/providers/ipa/ipa_sudo_refresh.c
index 7386a01f2c4..e7e7ae5b028 100644
--- a/src/providers/ipa/ipa_sudo_refresh.c
+++ b/src/providers/ipa/ipa_sudo_refresh.c
@@ -31,7 +31,6 @@
struct ipa_sudo_full_refresh_state {
struct ipa_sudo_ctx *sudo_ctx;
struct sss_domain_info *domain;
- int dp_error;
};
static void ipa_sudo_full_refresh_done(struct tevent_req *subreq);
@@ -95,9 +94,9 @@ ipa_sudo_full_refresh_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_sudo_full_refresh_state);
- ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, NULL);
+ ret = ipa_sudo_refresh_recv(subreq, NULL);
talloc_zfree(subreq);
- if (ret != EOK || state->dp_error != DP_ERR_OK) {
+ if (ret != EOK) {
goto done;
}
@@ -122,21 +121,14 @@ ipa_sudo_full_refresh_done(struct tevent_req *subreq)
}
int
-ipa_sudo_full_refresh_recv(struct tevent_req *req,
- int *dp_error)
+ipa_sudo_full_refresh_recv(struct tevent_req *req)
{
- struct ipa_sudo_full_refresh_state *state;
- state = tevent_req_data(req, struct ipa_sudo_full_refresh_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
return EOK;
}
struct ipa_sudo_smart_refresh_state {
- int dp_error;
};
static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq);
@@ -165,7 +157,6 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
if (be_ptask_running(sudo_ctx->full_refresh)) {
DEBUG(SSSDBG_TRACE_FUNC, "Skipping smart refresh because "
"there is ongoing full refresh.\n");
- state->dp_error = DP_ERR_OK;
ret = EOK;
goto immediately;
}
@@ -223,15 +214,13 @@ ipa_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq)
{
struct tevent_req *req = NULL;
- struct ipa_sudo_smart_refresh_state *state = NULL;
int ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct ipa_sudo_smart_refresh_state);
- ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, NULL);
+ ret = ipa_sudo_refresh_recv(subreq, NULL);
talloc_zfree(subreq);
- if (ret != EOK || state->dp_error != DP_ERR_OK) {
+ if (ret != EOK) {
goto done;
}
@@ -246,22 +235,15 @@ static void ipa_sudo_smart_refresh_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int ipa_sudo_smart_refresh_recv(struct tevent_req *req,
- int *dp_error)
+int ipa_sudo_smart_refresh_recv(struct tevent_req *req)
{
- struct ipa_sudo_smart_refresh_state *state = NULL;
- state = tevent_req_data(req, struct ipa_sudo_smart_refresh_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
return EOK;
}
struct ipa_sudo_rules_refresh_state {
size_t num_rules;
- int dp_error;
bool deleted;
};
@@ -297,7 +279,6 @@ ipa_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
}
if (rules == NULL || rules[0] == NULL) {
- state->dp_error = DP_ERR_OK;
state->num_rules = 0;
state->deleted = false;
ret = EOK;
@@ -381,9 +362,9 @@ ipa_sudo_rules_refresh_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct ipa_sudo_rules_refresh_state);
- ret = ipa_sudo_refresh_recv(subreq, &state->dp_error, &downloaded_rules_num);
+ ret = ipa_sudo_refresh_recv(subreq, &downloaded_rules_num);
talloc_zfree(subreq);
- if (ret != EOK || state->dp_error != DP_ERR_OK) {
+ if (ret != EOK) {
goto done;
}
@@ -400,7 +381,6 @@ ipa_sudo_rules_refresh_done(struct tevent_req *subreq)
int
ipa_sudo_rules_refresh_recv(struct tevent_req *req,
- int *dp_error,
bool *deleted)
{
struct ipa_sudo_rules_refresh_state *state;
@@ -408,7 +388,6 @@ ipa_sudo_rules_refresh_recv(struct tevent_req *req,
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
*deleted = state->deleted;
return EOK;
@@ -430,9 +409,7 @@ ipa_sudo_ptask_full_refresh_send(TALLOC_CTX *mem_ctx,
static errno_t
ipa_sudo_ptask_full_refresh_recv(struct tevent_req *req)
{
- int dp_error;
-
- return ipa_sudo_full_refresh_recv(req, &dp_error);
+ return ipa_sudo_full_refresh_recv(req);
}
static struct tevent_req *
@@ -451,9 +428,7 @@ ipa_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx,
static errno_t
ipa_sudo_ptask_smart_refresh_recv(struct tevent_req *req)
{
- int dp_error;
-
- return ipa_sudo_smart_refresh_recv(req, &dp_error);
+ return ipa_sudo_smart_refresh_recv(req);
}
errno_t
diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c
index c22cb10a562..e2fff877d9b 100644
--- a/src/providers/ipa/ipa_views.c
+++ b/src/providers/ipa/ipa_views.c
@@ -389,7 +389,6 @@ struct ipa_get_trusted_override_state {
struct sss_domain_info *dom;
struct sdap_id_op *sdap_op;
- int dp_error;
struct sysdb_attrs *override_attrs;
char *filter;
bool login_override_checked;
@@ -424,7 +423,6 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx,
state->ipa_options = ipa_options;
state->ipa_realm = ipa_realm;
state->ar = ar;
- state->dp_error = -1;
state->override_attrs = NULL;
state->filter = NULL;
@@ -469,10 +467,8 @@ struct tevent_req *ipa_get_trusted_override_send(TALLOC_CTX *mem_ctx,
done:
if (ret != EOK) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
} else {
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
tevent_req_post(req, state->ev);
@@ -491,10 +487,10 @@ static void ipa_get_trusted_override_connect_done(struct tevent_req *subreq)
char *search_base;
struct ipa_options *ipa_opts = state->ipa_options;
- ret = sdap_id_op_connect_recv(subreq, &state->dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- if (state->dp_error == DP_ERR_OFFLINE) {
+ if (ret == ERR_OFFLINE) {
DEBUG(SSSDBG_MINOR_FAILURE,
"No IPA server is available, going offline\n");
} else {
@@ -550,7 +546,6 @@ static void ipa_get_trusted_override_connect_done(struct tevent_req *subreq)
return;
fail:
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -603,7 +598,6 @@ static void ipa_get_trusted_override_done(struct tevent_req *subreq)
state->ar->entry_type = BE_REQ_GROUP;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
} else if (reply_count == MAX_USER_AND_GROUP_REPLIES &&
@@ -634,12 +628,10 @@ static void ipa_get_trusted_override_done(struct tevent_req *subreq)
goto fail;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
fail:
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
return;
}
@@ -671,17 +663,13 @@ static errno_t ipa_get_trusted_override_qualify_name(
return EOK;
}
-errno_t ipa_get_trusted_override_recv(struct tevent_req *req, int *dp_error_out,
+errno_t ipa_get_trusted_override_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
struct sysdb_attrs **override_attrs)
{
struct ipa_get_trusted_override_state *state = tevent_req_data(req,
struct ipa_get_trusted_override_state);
- if (dp_error_out != NULL) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
if (override_attrs != NULL) {
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 0eacb552360..06bc770720f 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -250,7 +250,7 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
struct sss_domain_info *domain,
struct confdb_ctx *cdb,
struct pam_data *pd, uid_t uid,
- int *pam_status, int *dp_err)
+ int *pam_status)
{
const char *password = NULL;
errno_t ret;
@@ -262,7 +262,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
"available for password authentication (single factor).\n",
ret, strerror(ret));
*pam_status = PAM_SYSTEM_ERR;
- *dp_err = DP_ERR_OK;
return;
}
@@ -271,7 +270,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Offline authentication failed\n");
*pam_status = cached_login_pam_status(ret);
- *dp_err = DP_ERR_OK;
return;
}
@@ -285,7 +283,6 @@ static void krb5_auth_cache_creds(struct krb5_ctx *krb5_ctx,
"add_user_to_delayed_online_authentication failed.\n");
}
*pam_status = PAM_AUTHINFO_UNAVAIL;
- *dp_err = DP_ERR_OFFLINE;
}
static errno_t krb5_auth_prepare_ccache_name(struct krb5child_req *kr,
@@ -499,7 +496,6 @@ struct krb5_auth_state {
bool search_kpasswd;
int pam_status;
- int dp_err;
};
static void krb5_auth_resolve_done(struct tevent_req *subreq);
@@ -534,7 +530,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
state->krb5_ctx = krb5_ctx;
state->kr = NULL;
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_FATAL;
ret = get_domain_or_subdomain(be_ctx, pd->domain, &state->domain);
if (ret != EOK) {
@@ -565,7 +560,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
"Illegal empty authtok for user [%s]\n",
pd->user);
state->pam_status = PAM_AUTH_ERR;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -576,7 +570,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
SSS_AUTHTOK_TYPE_PASSWORD,
authtok_type);
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_FATAL;
ret = EINVAL;
goto done;
}
@@ -587,7 +580,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_MINOR_FAILURE,
"Password reset by root is not supported.\n");
state->pam_status = PAM_PERM_DENIED;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -598,7 +590,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
if (pd->child_pid != 0) {
soft_terminate_krb5_child(state, pd, krb5_ctx);
state->pam_status = PAM_TRY_AGAIN;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -612,7 +603,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
SSS_AUTHTOK_TYPE_CCFILE,
authtok_type);
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_FATAL;
ret = EINVAL;
goto done;
}
@@ -622,7 +612,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
default:
DEBUG(SSSDBG_CONF_SETTINGS, "Unexpected pam task %d.\n", pd->cmd);
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_FATAL;
ret = EINVAL;
goto done;
}
@@ -634,7 +623,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
"Password changes and ticket renewal are not possible "
"while offline.\n");
state->pam_status = PAM_AUTHINFO_UNAVAIL;
- state->dp_err = DP_ERR_OFFLINE;
ret = EOK;
goto done;
}
@@ -668,7 +656,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_FUNC_DATA,
"sysdb search for upn of user [%s] failed.\n", pd->user);
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_OK;
goto done;
}
@@ -752,7 +739,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_FUNC,
"Skipping password checks for OTP-enabled user\n");
state->pam_status = PAM_SUCCESS;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -806,7 +792,6 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
* authentication is. We return an PAM error here, but do not
* mark the backend offline. */
state->pam_status = PAM_AUTHTOK_LOCK_BUSY;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -824,7 +809,6 @@ static void krb5_auth_resolve_done(struct tevent_req *subreq)
DEBUG(SSSDBG_TRACE_FUNC,
"No KDC suitable for password change is available\n");
state->pam_status = PAM_AUTHTOK_LOCK_BUSY;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -925,7 +909,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
}
case SSS_PAM_PREAUTH:
state->pam_status = PAM_CRED_UNAVAIL;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
default:
@@ -1021,7 +1004,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
* change password request just return success. */
if (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM) {
state->pam_status = PAM_SUCCESS;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -1093,49 +1075,41 @@ static void krb5_auth_done(struct tevent_req *subreq)
}
state->pam_status = PAM_NEW_AUTHTOK_REQD;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_CREDS_INVALID:
state->pam_status = PAM_CRED_ERR;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_ACCOUNT_EXPIRED:
state->pam_status = PAM_ACCT_EXPIRED;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_ACCOUNT_LOCKED:
state->pam_status = PAM_PERM_DENIED;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_NO_CREDS:
state->pam_status = PAM_CRED_UNAVAIL;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_AUTH_FAILED:
state->pam_status = PAM_AUTH_ERR;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_CHPASS_FAILED:
state->pam_status = PAM_AUTHTOK_ERR;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
case ERR_NO_AUTH_METHOD_AVAILABLE:
state->pam_status = PAM_NO_MODULE_DATA;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
@@ -1144,7 +1118,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
"The krb5_child process returned an error. Please inspect the "
"krb5_child.log file or the journal for more information\n");
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -1164,7 +1137,6 @@ static void krb5_auth_done(struct tevent_req *subreq)
if (pd->cmd == SSS_PAM_PREAUTH) {
state->pam_status = PAM_SUCCESS;
- state->dp_err = DP_ERR_OK;
ret = EOK;
goto done;
}
@@ -1220,12 +1192,11 @@ static void krb5_auth_done(struct tevent_req *subreq)
state->domain,
state->be_ctx->cdb,
state->pd, state->kr->uid,
- &state->pam_status, &state->dp_err);
+ &state->pam_status);
} else {
DEBUG(SSSDBG_CONF_SETTINGS,
"Backend is marked offline, retry later!\n");
state->pam_status = PAM_AUTHINFO_UNAVAIL;
- state->dp_err = DP_ERR_OFFLINE;
}
ret = EOK;
goto done;
@@ -1252,13 +1223,11 @@ static void krb5_auth_done(struct tevent_req *subreq)
"pam_add_response failed: %d (%s).\n",
ret, sss_strerror(ret));
state->pam_status = PAM_SYSTEM_ERR;
- state->dp_err = DP_ERR_OK;
goto done;
}
}
state->pam_status = PAM_SUCCESS;
- state->dp_err = DP_ERR_OK;
ret = EOK;
done:
@@ -1270,11 +1239,10 @@ static void krb5_auth_done(struct tevent_req *subreq)
}
-int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err)
+int krb5_auth_recv(struct tevent_req *req, int *pam_status)
{
struct krb5_auth_state *state = tevent_req_data(req, struct krb5_auth_state);
*pam_status = state->pam_status;
- *dp_err = state->dp_err;
TEVENT_REQ_RETURN_ON_ERROR(req);
@@ -1373,7 +1341,7 @@ static void krb5_pam_handler_auth_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct krb5_pam_handler_state);
- ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, NULL);
+ ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status);
talloc_zfree(subreq);
if (ret != EOK) {
state->pd->pam_status = PAM_SYSTEM_ERR;
@@ -1415,7 +1383,7 @@ static void krb5_pam_handler_auth_retry_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct krb5_pam_handler_state);
- ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status, NULL);
+ ret = krb5_auth_queue_recv(subreq, &state->pd->pam_status);
talloc_free(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv request failed.\n");
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index c2d802d87a0..4f908443c2d 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -97,7 +97,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct pam_data *pd,
struct krb5_ctx *krb5_ctx);
-int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err);
+int krb5_auth_recv(struct tevent_req *req, int *pam_status);
struct tevent_req *handle_child_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
@@ -148,7 +148,6 @@ struct tevent_req *krb5_auth_queue_send(TALLOC_CTX *mem_ctx,
struct krb5_ctx *krb5_ctx);
int krb5_auth_queue_recv(struct tevent_req *req,
- int *_pam_status,
- int *_dp_err);
+ int *_pam_status);
#endif /* __KRB5_AUTH_H__ */
diff --git a/src/providers/krb5/krb5_delayed_online_authentication.c b/src/providers/krb5/krb5_delayed_online_authentication.c
index 1fac986a620..29a5a14667a 100644
--- a/src/providers/krb5/krb5_delayed_online_authentication.c
+++ b/src/providers/krb5/krb5_delayed_online_authentication.c
@@ -118,9 +118,8 @@ static void authenticate_user_done(struct tevent_req *req)
struct auth_data);
int ret;
int pam_status = PAM_SYSTEM_ERR;
- int dp_err = DP_ERR_OK;
- ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(req, &pam_status);
talloc_free(req);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth request failed.\n");
diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c
index 7d8f0e4347a..90ac52c00e0 100644
--- a/src/providers/krb5/krb5_renew_tgt.c
+++ b/src/providers/krb5/krb5_renew_tgt.c
@@ -85,10 +85,9 @@ static void renew_tgt_done(struct tevent_req *req)
struct auth_data);
int ret;
int pam_status = PAM_SYSTEM_ERR;
- int dp_err;
hash_value_t value;
- ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(req, &pam_status);
talloc_free(req);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE, "krb5_auth request failed.\n");
diff --git a/src/providers/krb5/krb5_wait_queue.c b/src/providers/krb5/krb5_wait_queue.c
index 06d7a981cd9..b8929109501 100644
--- a/src/providers/krb5/krb5_wait_queue.c
+++ b/src/providers/krb5/krb5_wait_queue.c
@@ -43,7 +43,7 @@ struct queue_entry {
static void wait_queue_auth_done(struct tevent_req *req);
static void krb5_auth_queue_finish(struct tevent_req *req, errno_t ret,
- int pam_status, int dp_err);
+ int pam_status);
static void wait_queue_auth(struct tevent_context *ev, struct tevent_timer *te,
struct timeval current_time, void *private_data)
@@ -68,16 +68,15 @@ static void wait_queue_auth_done(struct tevent_req *req)
struct tevent_req *parent_req = \
tevent_req_callback_data(req, struct tevent_req);
int pam_status;
- int dp_err;
errno_t ret;
- ret = krb5_auth_recv(req, &pam_status, &dp_err);
+ ret = krb5_auth_recv(req, &pam_status);
talloc_zfree(req);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "krb5_auth_recv failed: %d\n", ret);
}
- krb5_auth_queue_finish(parent_req, ret, pam_status, dp_err);
+ krb5_auth_queue_finish(parent_req, ret, pam_status);
}
static void wait_queue_del_cb(hash_entry_t *entry, hash_destroy_enum type,
@@ -242,7 +241,6 @@ struct krb5_auth_queue_state {
struct pam_data *pd;
int pam_status;
- int dp_err;
};
static void krb5_auth_queue_done(struct tevent_req *subreq);
@@ -309,7 +307,7 @@ static void krb5_auth_queue_done(struct tevent_req *subreq)
tevent_req_data(req, struct krb5_auth_queue_state);
errno_t ret;
- ret = krb5_auth_recv(subreq, &state->pam_status, &state->dp_err);
+ ret = krb5_auth_recv(subreq, &state->pam_status);
talloc_zfree(subreq);
check_wait_queue(state->krb5_ctx, state->pd->user);
@@ -331,8 +329,7 @@ static void krb5_auth_queue_done(struct tevent_req *subreq)
*/
static void krb5_auth_queue_finish(struct tevent_req *req,
errno_t ret,
- int pam_status,
- int dp_err)
+ int pam_status)
{
struct krb5_auth_queue_state *state = \
tevent_req_data(req, struct krb5_auth_queue_state);
@@ -340,7 +337,6 @@ static void krb5_auth_queue_finish(struct tevent_req *req,
check_wait_queue(state->krb5_ctx, state->pd->user);
state->pam_status = pam_status;
- state->dp_err = dp_err;
if (ret != EOK) {
tevent_req_error(req, ret);
} else {
@@ -350,8 +346,7 @@ static void krb5_auth_queue_finish(struct tevent_req *req,
}
int krb5_auth_queue_recv(struct tevent_req *req,
- int *_pam_status,
- int *_dp_err)
+ int *_pam_status)
{
struct krb5_auth_queue_state *state = \
tevent_req_data(req, struct krb5_auth_queue_state);
@@ -363,10 +358,6 @@ int krb5_auth_queue_recv(struct tevent_req *req,
*_pam_status = state->pam_status;
}
- if (_dp_err) {
- *_dp_err = state->dp_err;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 6f7486278a4..3549aeea3ba 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -30,6 +30,7 @@
#include "providers/fail_over.h"
#include "providers/krb5/krb5_common.h"
#include "lib/idmap/sss_idmap.h"
+#include "providers/failover/failover.h"
#define PWD_POL_OPT_NONE "none"
#define PWD_POL_OPT_SHADOW "shadow"
@@ -78,6 +79,9 @@ struct sdap_id_ctx {
struct sdap_server_opts *srv_opts;
+ /* New failover context */
+ struct sss_failover_ctx *fctx;
+
/* Enumeration/cleanup periodic task. Only the enumeration or the cleanup
* task is started depending on the value of the domain's enumeration
* setting, this is why there is only one task pointer for both tasks. */
@@ -108,6 +112,14 @@ struct sdap_resolver_ctx {
struct timeval last_purge;
};
+struct ldap_init_ctx {
+ struct sdap_options *options;
+ struct sdap_id_ctx *id_ctx;
+ struct sdap_auth_ctx *auth_ctx;
+ struct sdap_resolver_ctx *resolver_ctx;
+ struct sss_failover_ctx *fctx;
+};
+
struct tevent_req *
sdap_online_check_handler_send(TALLOC_CTX *mem_ctx,
struct sdap_id_ctx *id_ctx,
@@ -127,7 +139,7 @@ errno_t sdap_reinit_cleanup_recv(struct tevent_req *req);
/* id */
struct tevent_req *
sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
- struct sdap_id_ctx *id_ctx,
+ struct ldap_init_ctx *init_ctx,
struct dp_id_data *data,
struct dp_req_params *params);
@@ -157,8 +169,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
bool noexist_delete);
errno_t
sdap_handle_acct_req_recv(struct tevent_req *req,
- int *_dp_error, const char **_err,
- int *sdap_ret);
+ const char **_err);
struct tevent_req *
sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx,
@@ -296,19 +307,18 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *name,
int filter_type,
bool noexist_delete,
bool no_members,
- bool set_non_posix);
-int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret);
+ bool set_non_posix,
+ bool no_mpg_user_fallback);
+int groups_get_recv(struct tevent_req *req);
struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
struct sdap_search_base **search_bases,
const char *filter_value,
int filter_type,
@@ -318,30 +328,28 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
bool noexist_delete,
bool set_non_posix);
-int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret);
+int groups_by_user_recv(struct tevent_req *req);
struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *name,
bool noexist_delete);
-int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret);
+int ldap_netgroup_get_recv(struct tevent_req *req);
struct tevent_req *
services_get_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *name,
const char *protocol,
int filter_type,
bool noexist_delete);
errno_t
-services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret);
+services_get_recv(struct tevent_req *req);
struct tevent_req *
sdap_iphost_handler_send(TALLOC_CTX *mem_ctx,
@@ -488,11 +496,9 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char* filter_value);
-int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out,
- int *sdap_ret);
+int subid_ranges_get_recv(struct tevent_req *req);
#endif
#endif /* _LDAP_COMMON_H_ */
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index bdde2a6c230..34643d0c245 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -35,6 +35,8 @@
#include "providers/ldap/sdap_async.h"
#include "providers/ldap/sdap_idmap.h"
#include "providers/ldap/sdap_users.h"
+#include "providers/failover/ldap/failover_ldap.h"
+#include "providers/failover/failover_transaction.h"
errno_t users_get_handle_no_user(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
@@ -131,7 +133,7 @@ struct users_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
@@ -146,13 +148,10 @@ struct users_get_state {
bool use_id_mapping;
bool non_posix;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
struct sysdb_attrs *extra_attrs;
};
-static int users_get_retry(struct tevent_req *req);
static void users_get_connect_done(struct tevent_req *subreq);
static void users_get_search(struct tevent_req *req);
static void users_get_done(struct tevent_req *subreq);
@@ -161,7 +160,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *filter_value,
int filter_type,
const char *extra_value,
@@ -187,18 +185,9 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->noexist_delete = noexist_delete;
state->extra_attrs = NULL;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto done;
- }
-
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
state->filter_value = filter_value;
@@ -377,8 +366,6 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
}
ret = EOK;
- state->sdap_ret = ENOENT;
- state->dp_error = DP_ERR_OK;
goto done;
}
@@ -459,7 +446,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
NULL, &state->attrs, NULL);
if (ret != EOK) goto done;
- ret = users_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ users_get_connect_done);
if (ret != EOK) {
goto done;
}
@@ -475,37 +463,20 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
return tevent_req_post(req, ev);
}
-static int users_get_retry(struct tevent_req *req)
-{
- struct users_get_state *state = tevent_req_data(req,
- struct users_get_state);
- struct tevent_req *subreq;
- int ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, users_get_connect_done, req);
- return EOK;
-}
-
static void users_get_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct users_get_state *state = tevent_req_data(req,
struct users_get_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -529,7 +500,7 @@ static void users_get_search(struct tevent_req *req)
state->domain, state->sysdb,
state->ctx->opts,
state->sdom->user_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -549,24 +520,11 @@ static void users_get_done(struct tevent_req *subreq)
struct users_get_state);
char *endptr;
uid_t uid = 0;
- int dp_error = DP_ERR_FATAL;
int ret;
ret = sdap_get_users_recv(subreq, NULL, NULL);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = users_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- return;
- }
-
if ((ret == ENOENT) &&
(state->ctx->opts->schema_type == SDAP_SCHEMA_RFC2307) &&
(dp_opt_get_bool(state->ctx->opts->basic,
@@ -601,10 +559,8 @@ static void users_get_done(struct tevent_req *subreq)
}
}
}
- state->sdap_ret = ret;
if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -618,24 +574,12 @@ static void users_get_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
/* FIXME - return sdap error so that we know the user was not found */
tevent_req_done(req);
}
-int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
+int users_get_recv(struct tevent_req *req)
{
- struct users_get_state *state = tevent_req_data(req,
- struct users_get_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -647,7 +591,7 @@ struct groups_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
@@ -660,13 +604,11 @@ struct groups_get_state {
bool use_id_mapping;
bool non_posix;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
bool no_members;
+ bool no_mpg_user_fallback;
};
-static int groups_get_retry(struct tevent_req *req);
static void groups_get_connect_done(struct tevent_req *subreq);
static void groups_get_mpg_done(struct tevent_req *subreq);
static void groups_get_search(struct tevent_req *req);
@@ -676,12 +618,12 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *filter_value,
int filter_type,
bool noexist_delete,
bool no_members,
- bool set_non_posix)
+ bool set_non_posix,
+ bool no_mpg_user_fallback)
{
struct tevent_req *req;
struct groups_get_state *state;
@@ -702,17 +644,9 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->noexist_delete = noexist_delete;
state->no_members = no_members;
-
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto done;
- }
+ state->no_mpg_user_fallback = no_mpg_user_fallback;
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
@@ -879,7 +813,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
if (ret != EOK) goto done;
- ret = groups_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ groups_get_connect_done);
if (ret != EOK) {
goto done;
}
@@ -895,37 +830,19 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
return tevent_req_post(req, ev);
}
-static int groups_get_retry(struct tevent_req *req)
-{
- struct groups_get_state *state = tevent_req_data(req,
- struct groups_get_state);
- struct tevent_req *subreq;
- int ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, groups_get_connect_done, req);
- return EOK;
-}
-
static void groups_get_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct groups_get_state *state = tevent_req_data(req,
struct groups_get_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
-
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -948,7 +865,7 @@ static void groups_get_search(struct tevent_req *req)
subreq = sdap_get_groups_send(state, state->ev,
state->sdom,
state->ctx->opts,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -967,34 +884,14 @@ static void groups_get_done(struct tevent_req *subreq)
struct tevent_req);
struct groups_get_state *state = tevent_req_data(req,
struct groups_get_state);
- int dp_error = DP_ERR_FATAL;
int ret;
ret = sdap_get_groups_recv(subreq, NULL, NULL);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
-
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = groups_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- return;
- }
- state->sdap_ret = ret;
-
- if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
if (ret == ENOENT
&& sss_domain_is_mpg(state->domain) == true
- && !state->conn->no_mpg_user_fallback) {
+ && !state->no_mpg_user_fallback) {
/* The requested filter did not find a group. Before giving up, we must
* also check if the GID can be resolved through a primary group of a
* user
@@ -1003,7 +900,6 @@ static void groups_get_done(struct tevent_req *subreq)
state->ev,
state->ctx,
state->sdom,
- state->conn,
state->filter_value,
state->filter_type,
NULL,
@@ -1027,7 +923,6 @@ static void groups_get_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
@@ -1039,7 +934,7 @@ static void groups_get_mpg_done(struct tevent_req *subreq)
struct groups_get_state *state = tevent_req_data(req,
struct groups_get_state);
- ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = users_get_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -1047,7 +942,7 @@ static void groups_get_mpg_done(struct tevent_req *subreq)
return;
}
- if (state->sdap_ret == ENOENT && state->noexist_delete == true) {
+ if (ret == ENOENT && state->noexist_delete == true) {
ret = groups_get_handle_no_group(state, state->domain,
state->filter_type,
state->filter_value);
@@ -1123,19 +1018,8 @@ errno_t groups_get_handle_no_group(TALLOC_CTX *mem_ctx,
return ret;
}
-int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
+int groups_get_recv(struct tevent_req *req)
{
- struct groups_get_state *state = tevent_req_data(req,
- struct groups_get_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -1148,7 +1032,7 @@ struct groups_by_user_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
@@ -1162,12 +1046,9 @@ struct groups_by_user_state {
const char **attrs;
bool non_posix;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
};
-static int groups_by_user_retry(struct tevent_req *req);
static void groups_by_user_connect_done(struct tevent_req *subreq);
static void groups_by_user_done(struct tevent_req *subreq);
@@ -1175,7 +1056,6 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
struct sdap_search_base **search_bases,
const char *filter_value,
int filter_type,
@@ -1194,18 +1074,9 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
- state->dp_error = DP_ERR_FATAL;
- state->conn = conn;
state->sdom = sdom;
state->noexist_delete = noexist_delete;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
-
state->filter_value = filter_value;
state->filter_type = filter_type;
state->extra_value = extra_value;
@@ -1223,7 +1094,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
NULL, &state->attrs, NULL);
if (ret != EOK) goto fail;
- ret = groups_by_user_retry(req);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ groups_by_user_connect_done);
if (ret != EOK) {
goto fail;
}
@@ -1236,44 +1108,26 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
return req;
}
-static int groups_by_user_retry(struct tevent_req *req)
-{
- struct groups_by_user_state *state = tevent_req_data(req,
- struct groups_by_user_state);
- struct tevent_req *subreq;
- int ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, groups_by_user_connect_done, req);
- return EOK;
-}
-
static void groups_by_user_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct groups_by_user_state *state = tevent_req_data(req,
struct groups_by_user_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
-
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = sdap_get_initgr_send(state,
state->ev,
state->sdom,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->ctx,
state->user_map,
state->user_map_cnt,
@@ -1297,26 +1151,11 @@ static void groups_by_user_done(struct tevent_req *subreq)
struct tevent_req);
struct groups_by_user_state *state = tevent_req_data(req,
struct groups_by_user_state);
- int dp_error = DP_ERR_FATAL;
int ret;
ret = sdap_get_initgr_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
-
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = groups_by_user_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- return;
- }
- state->sdap_ret = ret;
-
- switch (state->sdap_ret) {
+ switch (ret) {
case ENOENT:
if (state->noexist_delete == true) {
const char *cname;
@@ -1345,28 +1184,15 @@ static void groups_by_user_done(struct tevent_req *subreq)
case EOK:
break;
default:
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
-int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
+int groups_by_user_recv(struct tevent_req *req)
{
- struct groups_by_user_state *state = tevent_req_data(req,
- struct groups_by_user_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -1381,13 +1207,11 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *filter_value,
int filter_type,
bool noexist_delete);
-errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
- int *dp_error_out, int *sdap_ret);
+errno_t sdap_get_user_and_group_recv(struct tevent_req *req);
bool sdap_is_enum_request(struct dp_id_data *ar)
{
@@ -1407,8 +1231,6 @@ bool sdap_is_enum_request(struct dp_id_data *ar)
struct sdap_handle_acct_req_state {
struct dp_id_data *ar;
const char *err;
- int dp_error;
- int sdap_ret;
};
static void sdap_handle_acct_req_done(struct tevent_req *subreq);
@@ -1448,7 +1270,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
switch (ar->entry_type & BE_REQ_TYPE_MASK) {
case BE_REQ_USER: /* user */
subreq = users_get_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->filter_type,
ar->extra_value,
@@ -1458,10 +1280,11 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
case BE_REQ_GROUP: /* group */
subreq = groups_get_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->filter_type,
- noexist_delete, false, false);
+ noexist_delete, false, false,
+ conn->no_mpg_user_fallback);
break;
case BE_REQ_INITGROUPS: /* init groups for user */
@@ -1474,7 +1297,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
}
subreq = groups_by_user_send(state, be_ctx->ev, id_ctx,
- sdom, conn, NULL,
+ sdom, NULL,
ar->filter_value,
ar->filter_type,
ar->extra_value,
@@ -1493,7 +1316,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
goto done;
}
subreq = subid_ranges_get_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value);
#else
ret = ERR_GET_ACCT_SUBID_RANGES_NOT_SUPPORTED;
@@ -1510,7 +1333,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
}
subreq = ldap_netgroup_get_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
noexist_delete);
break;
@@ -1524,7 +1347,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
}
subreq = services_get_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->extra_value,
ar->filter_type,
@@ -1539,7 +1362,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
}
subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->filter_type,
noexist_delete);
@@ -1553,7 +1376,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
}
subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->filter_type,
noexist_delete);
@@ -1568,7 +1391,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
}
subreq = get_user_and_group_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->filter_type,
noexist_delete);
@@ -1576,7 +1399,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx,
case BE_REQ_BY_CERT:
subreq = users_get_send(state, be_ctx->ev, id_ctx,
- sdom, conn,
+ sdom,
ar->filter_value,
ar->filter_type,
ar->extra_value,
@@ -1627,31 +1450,31 @@ sdap_handle_acct_req_done(struct tevent_req *subreq)
switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
case BE_REQ_USER: /* user */
err = "User lookup failed";
- ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = users_get_recv(subreq);
break;
case BE_REQ_GROUP: /* group */
err = "Group lookup failed";
- ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = groups_get_recv(subreq);
break;
case BE_REQ_INITGROUPS: /* init groups for user */
err = "Init group lookup failed";
- ret = groups_by_user_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = groups_by_user_recv(subreq);
break;
case BE_REQ_SUBID_RANGES:
err = "Subid ranges lookup failed";
#ifdef BUILD_SUBID
- ret = subid_ranges_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = subid_ranges_get_recv(subreq);
#else
ret = EINVAL;
#endif
break;
case BE_REQ_NETGROUP:
err = "Netgroup lookup failed";
- ret = ldap_netgroup_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = ldap_netgroup_get_recv(subreq);
break;
case BE_REQ_SERVICES:
err = "Service lookup failed";
- ret = services_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = services_get_recv(subreq);
break;
case BE_REQ_BY_SECID:
/* Fall through */
@@ -1659,12 +1482,11 @@ sdap_handle_acct_req_done(struct tevent_req *subreq)
/* Fall through */
case BE_REQ_USER_AND_GROUP:
err = "Lookup by SID failed";
- ret = sdap_get_user_and_group_recv(subreq, &state->dp_error,
- &state->sdap_ret);
+ ret = sdap_get_user_and_group_recv(subreq);
break;
case BE_REQ_BY_CERT:
err = "User lookup by certificate failed";
- ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = users_get_recv(subreq);
break;
default: /* fail */
ret = EINVAL;
@@ -1684,8 +1506,7 @@ sdap_handle_acct_req_done(struct tevent_req *subreq)
errno_t
sdap_handle_acct_req_recv(struct tevent_req *req,
- int *_dp_error, const char **_err,
- int *sdap_ret)
+ const char **_err)
{
struct sdap_handle_acct_req_state *state;
@@ -1696,18 +1517,10 @@ sdap_handle_acct_req_recv(struct tevent_req *req,
state->ar->filter_type, state->ar->filter_value,
PROBE_SAFE_STR(state->ar->extra_value));
- if (_dp_error) {
- *_dp_error = state->dp_error;
- }
-
if (_err) {
*_err = state->err;
}
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
@@ -1727,8 +1540,6 @@ struct get_user_and_group_state {
char *filter;
const char **attrs;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
};
@@ -1739,7 +1550,6 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *filter_val,
int filter_type,
bool noexist_delete)
@@ -1758,26 +1568,18 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx,
state->ev = ev;
state->id_ctx = id_ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->noexist_delete = noexist_delete;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
-
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
state->filter_val = filter_val;
state->filter_type = filter_type;
subreq = groups_get_send(req, state->ev, state->id_ctx,
- state->sdom, state->conn,
+ state->sdom,
state->filter_val, state->filter_type,
- state->noexist_delete, false, false);
+ state->noexist_delete, false, false,
+ state->id_ctx->conn->no_mpg_user_fallback);
if (subreq == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n");
ret = ENOMEM;
@@ -1803,7 +1605,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq)
int ret;
struct sdap_id_conn_ctx *user_conn;
- ret = groups_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = groups_get_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) { /* Fatal error while looking up group */
@@ -1811,10 +1613,10 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq)
return;
}
- if (state->sdap_ret == EOK) { /* Matching group found */
+ if (ret == EOK) { /* Matching group found */
tevent_req_done(req);
return;
- } else if (state->sdap_ret != ENOENT) {
+ } else if (ret != ENOENT) {
tevent_req_error(req, EIO);
return;
}
@@ -1829,7 +1631,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq)
}
subreq = users_get_send(req, state->ev, state->id_ctx,
- state->sdom, user_conn,
+ state->sdom,
state->filter_val, state->filter_type, NULL,
state->noexist_delete, false);
if (subreq == NULL) {
@@ -1849,14 +1651,10 @@ static void get_user_and_group_users_done(struct tevent_req *subreq)
struct get_user_and_group_state);
int ret;
- ret = users_get_recv(subreq, &state->dp_error, &state->sdap_ret);
+ ret = users_get_recv(subreq);
talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- if (state->sdap_ret == ENOENT) {
+ if (ret == ENOENT) {
if (state->noexist_delete == true) {
/* The search ran to completion, but nothing was found.
* Delete the existing entry, if any. */
@@ -1868,30 +1666,18 @@ static void get_user_and_group_users_done(struct tevent_req *subreq)
return;
}
}
- } else if (state->sdap_ret != EOK) {
+ } else if (ret != EOK) {
tevent_req_error(req, EIO);
return;
}
- /* Both ret and sdap->ret are EOK. Matching user found */
+ /* Matching user found */
tevent_req_done(req);
return;
}
-errno_t sdap_get_user_and_group_recv(struct tevent_req *req,
- int *dp_error_out, int *sdap_ret)
+errno_t sdap_get_user_and_group_recv(struct tevent_req *req)
{
- struct get_user_and_group_state *state = tevent_req_data(req,
- struct get_user_and_group_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -1905,15 +1691,18 @@ static void sdap_account_info_handler_done(struct tevent_req *subreq);
struct tevent_req *
sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
- struct sdap_id_ctx *id_ctx,
+ struct ldap_init_ctx *init_ctx,
struct dp_id_data *data,
struct dp_req_params *params)
{
struct sdap_account_info_handler_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
+ struct sdap_id_ctx *id_ctx;
errno_t ret;
+ id_ctx = init_ctx->id_ctx;
+
req = tevent_req_create(mem_ctx, &state,
struct sdap_account_info_handler_state);
if (req == NULL) {
@@ -1939,7 +1728,7 @@ sdap_account_info_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -1953,17 +1742,16 @@ static void sdap_account_info_handler_done(struct tevent_req *subreq)
struct sdap_account_info_handler_state *state;
struct tevent_req *req;
const char *error_msg;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_account_info_handler_state);
- ret = sdap_handle_acct_req_recv(subreq, &dp_error, &error_msg, NULL);
+ ret = sdap_handle_acct_req_recv(subreq, &error_msg);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, error_msg);
+ dp_reply_std_set(&state->reply, ret, error_msg);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 684dc70d8e5..685baf73151 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -166,8 +166,7 @@ ldap_id_enumeration_send(TALLOC_CTX *mem_ctx,
state->dom = ectx->sdom->dom;
state->id_ctx = talloc_get_type_abort(ectx->pvt, struct sdap_id_ctx);
- subreq = sdap_dom_enum_send(state, ev, state->id_ctx, ectx->sdom,
- state->id_ctx->conn);
+ subreq = sdap_dom_enum_send(state, ev, state->id_ctx, ectx->sdom);
if (subreq == NULL) {
/* The ptask API will reschedule the enumeration on its own on
* failure */
diff --git a/src/providers/ldap/ldap_id_netgroup.c b/src/providers/ldap/ldap_id_netgroup.c
index 1fb01cf1fb3..23fa6123af9 100644
--- a/src/providers/ldap/ldap_id_netgroup.c
+++ b/src/providers/ldap/ldap_id_netgroup.c
@@ -35,7 +35,7 @@ struct ldap_netgroup_get_state {
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
struct sdap_id_op *op;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
@@ -48,12 +48,9 @@ struct ldap_netgroup_get_state {
size_t count;
struct sysdb_attrs **netgroups;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
};
-static int ldap_netgroup_get_retry(struct tevent_req *req);
static void ldap_netgroup_get_connect_done(struct tevent_req *subreq);
static void ldap_netgroup_get_done(struct tevent_req *subreq);
@@ -61,7 +58,6 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *name,
bool noexist_delete)
{
@@ -76,17 +72,8 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->noexist_delete = noexist_delete;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
-
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
state->name = name;
@@ -112,7 +99,8 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
NULL, &state->attrs, NULL);
if (ret != EOK) goto fail;
- ret = ldap_netgroup_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ ldap_netgroup_get_connect_done);
if (ret != EOK) {
goto fail;
}
@@ -125,37 +113,19 @@ struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx,
return req;
}
-static int ldap_netgroup_get_retry(struct tevent_req *req)
-{
- struct ldap_netgroup_get_state *state = tevent_req_data(req,
- struct ldap_netgroup_get_state);
- struct tevent_req *subreq;
- int ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, ldap_netgroup_get_connect_done, req);
- return EOK;
-}
-
static void ldap_netgroup_get_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct ldap_netgroup_get_state *state = tevent_req_data(req,
struct ldap_netgroup_get_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
-
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -163,7 +133,7 @@ static void ldap_netgroup_get_connect_done(struct tevent_req *subreq)
state->domain, state->sysdb,
state->ctx->opts,
state->sdom->netgroup_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
state->timeout);
if (!subreq) {
@@ -181,32 +151,11 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq)
struct tevent_req);
struct ldap_netgroup_get_state *state = tevent_req_data(req,
struct ldap_netgroup_get_state);
- int dp_error = DP_ERR_FATAL;
int ret;
ret = sdap_get_netgroups_recv(subreq, state, NULL, &state->count,
&state->netgroups);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
-
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = ldap_netgroup_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- return;
- }
- state->sdap_ret = ret;
-
- if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
-
if (ret == EOK && state->count > 1) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Found more than one netgroup with the name [%s].\n",
@@ -223,24 +172,12 @@ static void ldap_netgroup_get_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
}
-int ldap_netgroup_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
+int ldap_netgroup_get_recv(struct tevent_req *req)
{
- struct ldap_netgroup_get_state *state = tevent_req_data(req,
- struct ldap_netgroup_get_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
diff --git a/src/providers/ldap/ldap_id_services.c b/src/providers/ldap/ldap_id_services.c
index 52a15631842..1d3e1ad8230 100644
--- a/src/providers/ldap/ldap_id_services.c
+++ b/src/providers/ldap/ldap_id_services.c
@@ -29,15 +29,16 @@
#include "db/sysdb_services.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async.h"
+#include "providers/failover/ldap/failover_ldap.h"
+#include "providers/failover/failover_transaction.h"
struct sdap_services_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
struct sdap_domain *sdom;
- struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
const char *name;
const char *protocol;
@@ -47,13 +48,9 @@ struct sdap_services_get_state {
int filter_type;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
};
-static errno_t
-services_get_retry(struct tevent_req *req);
static void
services_get_connect_done(struct tevent_req *subreq);
static void
@@ -64,7 +61,6 @@ services_get_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *name,
const char *protocol,
int filter_type,
@@ -83,8 +79,6 @@ services_get_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->id_ctx = id_ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
state->name = name;
@@ -92,13 +86,6 @@ services_get_send(TALLOC_CTX *mem_ctx,
state->filter_type = filter_type;
state->noexist_delete = noexist_delete;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_MINOR_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto error;
- }
-
switch(filter_type) {
case BE_FILTER_NAME:
attr_name = id_ctx->opts->service_map[SDAP_AT_SERVICE_NAME].name;
@@ -149,7 +136,8 @@ services_get_send(TALLOC_CTX *mem_ctx,
&state->attrs, NULL);
if (ret != EOK) goto error;
- ret = services_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req,
+ services_get_connect_done);
if (ret != EOK) goto error;
return req;
@@ -160,39 +148,21 @@ services_get_send(TALLOC_CTX *mem_ctx,
return req;
}
-static errno_t
-services_get_retry(struct tevent_req *req)
-{
- errno_t ret;
- struct sdap_services_get_state *state =
- tevent_req_data(req, struct sdap_services_get_state);
- struct tevent_req *subreq;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, services_get_connect_done, req);
- return EOK;
-}
-
static void
services_get_connect_done(struct tevent_req *subreq)
{
- errno_t ret;
struct tevent_req *req =
tevent_req_callback_data(subreq, struct tevent_req);
struct sdap_services_get_state *state =
tevent_req_data(req, struct sdap_services_get_state);
- int dp_error = DP_ERR_FATAL;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -200,7 +170,7 @@ services_get_connect_done(struct tevent_req *subreq)
state->domain, state->sysdb,
state->id_ctx->opts,
state->sdom->service_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -222,35 +192,10 @@ services_get_done(struct tevent_req *subreq)
tevent_req_callback_data(subreq, struct tevent_req);
struct sdap_services_get_state *state =
tevent_req_data(req, struct sdap_services_get_state);
- int dp_error = DP_ERR_FATAL;
ret = sdap_get_services_recv(NULL, subreq, NULL);
talloc_zfree(subreq);
- /* Check whether we need to try again with another
- * failover server.
- */
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = services_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- /* Return to the mainloop to retry */
- return;
- }
- state->sdap_ret = ret;
-
- /* An error occurred. */
- if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
-
if (ret == ENOENT && state->noexist_delete == true) {
/* Ensure that this entry is removed from the sysdb */
switch(state->filter_type) {
@@ -284,24 +229,12 @@ services_get_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
errno_t
-services_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret)
+services_get_recv(struct tevent_req *req)
{
- struct sdap_services_get_state *state =
- tevent_req_data(req, struct sdap_services_get_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
diff --git a/src/providers/ldap/ldap_id_subid.c b/src/providers/ldap/ldap_id_subid.c
index f6353d75c10..9ff013650b1 100644
--- a/src/providers/ldap/ldap_id_subid.c
+++ b/src/providers/ldap/ldap_id_subid.c
@@ -30,15 +30,13 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *filter_value,
int filter_type,
const char *extra_value,
bool noexist_delete,
bool set_non_posix);
-int users_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret);
+int users_get_recv(struct tevent_req *req);
-static int subid_ranges_get_retry(struct tevent_req *req);
static void subid_ranges_get_connect_done(struct tevent_req *subreq);
static void subid_ranges_resolve_owner(struct tevent_req *req);
static void subid_ranges_resolve_owner_done(struct tevent_req *subreq);
@@ -50,7 +48,7 @@ struct subid_ranges_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
struct sdap_id_op *op;
struct sss_domain_info *domain;
@@ -58,16 +56,12 @@ struct subid_ranges_get_state {
char *owner_name;
char *owner_dn;
const char **attrs;
-
- int dp_error;
- int sdap_ret;
};
struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
const char *filter_value)
{
struct tevent_req *req;
@@ -82,8 +76,6 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->owner_name = talloc_strdup(state, filter_value);
if (!state->owner_name) {
DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed\n");
@@ -91,16 +83,10 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx,
goto done;
}
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto done;
- }
-
state->domain = sdom->dom;
- ret = subid_ranges_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ subid_ranges_get_connect_done);
if (ret != EOK) {
goto done;
}
@@ -116,37 +102,20 @@ struct tevent_req *subid_ranges_get_send(TALLOC_CTX *memctx,
return tevent_req_post(req, ev);
}
-static int subid_ranges_get_retry(struct tevent_req *req)
-{
- struct subid_ranges_get_state *state = tevent_req_data(req,
- struct subid_ranges_get_state);
- struct tevent_req *subreq;
- int ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, subid_ranges_get_connect_done, req);
- return EOK;
-}
-
static void subid_ranges_get_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct subid_ranges_get_state *state = tevent_req_data(req,
struct subid_ranges_get_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -201,7 +170,7 @@ static void subid_ranges_resolve_owner(struct tevent_req *req)
DEBUG(SSSDBG_TRACE_FUNC, "'%s' needs to be looked up online\n",
state->owner_name);
subreq = users_get_send(state, state->ev, state->ctx,
- state->sdom, state->conn,
+ state->sdom,
state->owner_name,
BE_FILTER_NAME,
NULL, false, false);
@@ -218,23 +187,14 @@ static void subid_ranges_resolve_owner_done(struct tevent_req *subreq)
struct tevent_req);
struct subid_ranges_get_state *state = tevent_req_data(req,
struct subid_ranges_get_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
- ret = users_get_recv(subreq, &dp_error, NULL);
+ users_get_recv(subreq);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
-
state->owner_dn = get_user_dn(req, state->domain, state->owner_name);
if (state->owner_dn == NULL) {
DEBUG(SSSDBG_TRACE_FUNC,
"Online lookup didn't find range owner '%s'\n", state->owner_name);
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
}
@@ -269,7 +229,7 @@ static void subid_ranges_get_search(struct tevent_req *req)
}
subreq = sdap_search_bases_send(state, state->ev, state->ctx->opts,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->sdom->subid_ranges_search_bases,
state->ctx->opts->subid_map,
false, /* allow_paging */
@@ -292,7 +252,6 @@ static void subid_ranges_get_done(struct tevent_req *subreq)
struct tevent_req);
struct subid_ranges_get_state *state = tevent_req_data(req,
struct subid_ranges_get_state);
- int dp_error = DP_ERR_FATAL;
int ret;
struct sysdb_attrs **results;
size_t num_results;
@@ -304,21 +263,8 @@ static void subid_ranges_get_done(struct tevent_req *subreq)
return;
}
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = subid_ranges_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- }
- state->sdap_ret = ret;
-
if (ret && ret != ENOENT) {
DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve subid ranges.\n");
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -339,24 +285,11 @@ static void subid_ranges_get_done(struct tevent_req *subreq)
results[0]);
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
-int subid_ranges_get_recv(struct tevent_req *req, int *dp_error_out,
- int *sdap_ret)
+int subid_ranges_get_recv(struct tevent_req *req)
{
- struct subid_ranges_get_state *state = tevent_req_data(req,
- struct subid_ranges_get_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index a22654da409..6cbd2e0ff0c 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -33,13 +33,9 @@
#include "providers/ldap/ldap_resolver_enum.h"
#include "providers/fail_over_srv.h"
#include "providers/be_refresh.h"
-
-struct ldap_init_ctx {
- struct sdap_options *options;
- struct sdap_id_ctx *id_ctx;
- struct sdap_auth_ctx *auth_ctx;
- struct sdap_resolver_ctx *resolver_ctx;
-};
+#include "providers/failover/failover.h"
+#include "providers/failover/failover_vtable.h"
+#include "providers/failover/ldap/failover_ldap.h"
static errno_t ldap_init_auth_ctx(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
@@ -238,6 +234,88 @@ static errno_t ldap_init_misc(struct be_ctx *be_ctx,
return EOK;
}
+static struct sss_failover_ctx *
+sssm_ldap_init_failover(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_options *opts)
+{
+ struct sss_failover_ctx *fctx;
+ struct sss_failover_group *group;
+ struct sss_failover_server *server;
+ errno_t ret;
+
+ /* Setup new failover. */
+ fctx = sss_failover_init(mem_ctx, be_ctx->ev, "LDAP",
+ be_ctx->be_res->resolv,
+ be_ctx->be_res->family_order);
+ if (fctx == NULL) {
+ return NULL;
+ }
+
+ /* Add primary servers */
+ group = sss_failover_group_new(fctx, "primary");
+ if (group == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_setup_dns_discovery(group);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ server = sss_failover_server_new(fctx, "fake_1.ldap.test",
+ "ldap://fake_1.ldap.test", 389, 1, 1);
+ if (server == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_add_server(group, server);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ server = sss_failover_server_new(fctx, "fake_2.ldap.test",
+ "ldap://fake_2.ldap.test", 389, 1, 1);
+ if (server == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_add_server(group, server);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ server = sss_failover_server_new(fctx, "master.ldap.test",
+ "ldap://master.ldap.test", 389, 1, 1);
+ if (server == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_add_server(group, server);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ sss_failover_vtable_set_connect(fctx,
+ sss_failover_ldap_connect_send,
+ sss_failover_ldap_connect_recv,
+ opts);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(fctx);
+ return NULL;
+ }
+
+ return fctx;
+}
+
errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct data_provider *provider,
@@ -299,6 +377,16 @@ errno_t sssm_ldap_init(TALLOC_CTX *mem_ctx,
}
}
+ /* Setup new failover. */
+ init_ctx->fctx = sssm_ldap_init_failover(init_ctx, be_ctx, init_ctx->id_ctx->opts);
+ if (init_ctx->fctx == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ init_ctx->id_ctx->fctx = init_ctx->fctx;
+
*_module_data = init_ctx;
ret = EOK;
@@ -317,18 +405,12 @@ errno_t sssm_ldap_id_init(TALLOC_CTX *mem_ctx,
struct dp_method *dp_methods)
{
struct ldap_init_ctx *init_ctx;
- struct sdap_id_ctx *id_ctx;
init_ctx = talloc_get_type(module_data, struct ldap_init_ctx);
- id_ctx = init_ctx->id_ctx;
dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER,
- sdap_account_info_handler_send, sdap_account_info_handler_recv, id_ctx,
- struct sdap_id_ctx, struct dp_id_data, struct dp_reply_std);
-
- dp_set_method(dp_methods, DPM_CHECK_ONLINE,
- sdap_online_check_handler_send, sdap_online_check_handler_recv, id_ctx,
- struct sdap_id_ctx, void, struct dp_reply_std);
+ sdap_account_info_handler_send, sdap_account_info_handler_recv, init_ctx,
+ struct ldap_init_ctx, struct dp_id_data, struct dp_reply_std);
dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER,
default_account_domain_send, default_account_domain_recv, NULL,
diff --git a/src/providers/ldap/ldap_resolver_enum.c b/src/providers/ldap/ldap_resolver_enum.c
index 3098255b5d9..74ba366cfe7 100644
--- a/src/providers/ldap/ldap_resolver_enum.c
+++ b/src/providers/ldap/ldap_resolver_enum.c
@@ -252,8 +252,7 @@ ldap_resolver_enumeration_send(TALLOC_CTX *mem_ctx,
subreq = sdap_dom_resolver_enum_send(state, ev, state->resolver_ctx,
state->resolver_ctx->id_ctx,
- state->resolver_ctx->id_ctx->opts->sdom,
- state->resolver_ctx->id_ctx->conn);
+ state->resolver_ctx->id_ctx->opts->sdom);
if (subreq == NULL) {
/* The ptask API will reschedule the enumeration on its own on
* failure */
diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c
index bbfa2620d04..2c058c52720 100644
--- a/src/providers/ldap/sdap_access.c
+++ b/src/providers/ldap/sdap_access.c
@@ -72,7 +72,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct sss_domain_info *domain,
struct sdap_access_ctx *access_ctx,
- struct sdap_id_conn_ctx *conn,
const char *username,
struct ldb_message *user_entry,
enum sdap_pwpolicy_mode pwpol_mod);
@@ -82,7 +81,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct sss_domain_info *domain,
struct sdap_access_ctx *access_ctx,
- struct sdap_id_conn_ctx *conn,
const char *username,
struct ldb_message *user_entry);
@@ -225,7 +223,6 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state,
subreq = sdap_access_ppolicy_send(state, state->ev, state->be_ctx,
state->domain,
state->access_ctx,
- state->conn,
state->pd->user,
state->user_entry,
PWP_LOCKOUT_ONLY);
@@ -244,7 +241,6 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state,
subreq = sdap_access_ppolicy_send(state, state->ev, state->be_ctx,
state->domain,
state->access_ctx,
- state->conn,
state->pd->user,
state->user_entry,
PWP_LOCKOUT_EXPIRE);
@@ -263,7 +259,6 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state,
subreq = sdap_access_filter_send(state, state->ev, state->be_ctx,
state->domain,
state->access_ctx,
- state->conn,
state->pd->user,
state->user_entry);
if (subreq == NULL) {
@@ -825,8 +820,7 @@ struct sdap_access_filter_req_ctx {
struct tevent_context *ev;
struct sdap_access_ctx *access_ctx;
struct sdap_options *opts;
- struct sdap_id_conn_ctx *conn;
- struct sdap_id_op *sdap_op;
+ struct sss_failover_ldap_connection *conn;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
/* cached result of access control checks */
@@ -835,7 +829,6 @@ struct sdap_access_filter_req_ctx {
};
static errno_t sdap_access_decide_offline(bool cached_ac);
-static int sdap_access_filter_retry(struct tevent_req *req);
static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq);
static errno_t sdap_access_ppolicy_get_lockout_step(struct tevent_req *req);
static void sdap_access_filter_connect_done(struct tevent_req *subreq);
@@ -845,7 +838,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct sss_domain_info *domain,
struct sdap_access_ctx *access_ctx,
- struct sdap_id_conn_ctx *conn,
const char *username,
struct ldb_message *user_entry)
{
@@ -870,7 +862,6 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
state->filter = NULL;
state->username = username;
state->opts = access_ctx->id_ctx->opts;
- state->conn = conn;
state->ev = ev;
state->access_ctx = access_ctx;
state->domain = domain;
@@ -925,15 +916,8 @@ static struct tevent_req *sdap_access_filter_send(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_FUNC, "Checking filter against LDAP\n");
- state->sdap_op = sdap_id_op_create(state,
- state->conn->conn_cache);
- if (!state->sdap_op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto done;
- }
-
- ret = sdap_access_filter_retry(req);
+ ret = sss_failover_transaction_send(state, ev, access_ctx->id_ctx->fctx, req,
+ sdap_access_filter_connect_done);
if (ret != EOK) {
goto done;
}
@@ -965,45 +949,20 @@ static errno_t sdap_access_decide_offline(bool cached_ac)
}
}
-static int sdap_access_filter_retry(struct tevent_req *req)
-{
- struct sdap_access_filter_req_ctx *state =
- tevent_req_data(req, struct sdap_access_filter_req_ctx);
- struct tevent_req *subreq;
- int ret;
-
- subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
- if (!subreq) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sdap_id_op_connect_send failed: %d (%s)\n", ret, strerror(ret));
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_access_filter_connect_done, req);
- return EOK;
-}
-
static void sdap_access_filter_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
struct sdap_access_filter_req_ctx *state =
tevent_req_data(req, struct sdap_access_filter_req_ctx);
- int ret, dp_error;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
- ret = sdap_access_decide_offline(state->cached_access);
- if (ret == EOK) {
- tevent_req_done(req);
- return;
- }
- }
-
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -1013,7 +972,7 @@ static void sdap_access_filter_connect_done(struct tevent_req *subreq)
subreq = sdap_get_generic_send(state,
state->ev,
state->opts,
- sdap_id_op_handle(state->sdap_op),
+ state->conn->sh,
state->basedn,
LDAP_SCOPE_BASE,
state->filter, NULL,
@@ -1032,7 +991,7 @@ static void sdap_access_filter_connect_done(struct tevent_req *subreq)
static void sdap_access_filter_done(struct tevent_req *subreq)
{
- int ret, tret, dp_error;
+ int ret, tret;
size_t num_results;
bool found = false;
struct sysdb_attrs **results;
@@ -1045,29 +1004,6 @@ static void sdap_access_filter_done(struct tevent_req *subreq)
&num_results, &results);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (ret != EOK) {
- if (dp_error == DP_ERR_OK) {
- /* retry */
- tret = sdap_access_filter_retry(req);
- if (tret == EOK) {
- return;
- }
- } else if (dp_error == DP_ERR_OFFLINE) {
- ret = sdap_access_decide_offline(state->cached_access);
- } else if (ret == ERR_INVALID_FILTER) {
- sss_log(SSS_LOG_ERR, MALFORMED_FILTER, state->filter);
- DEBUG(SSSDBG_CRIT_FAILURE, MALFORMED_FILTER, state->filter);
- ret = ERR_ACCESS_DENIED;
- } else {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_get_generic_send() returned error [%d][%s]\n",
- ret, sss_strerror(ret));
- }
-
- goto done;
- }
-
/* Check the number of responses we got
* If it's exactly 1, we passed the check
* If it's < 1, we failed the check
@@ -1412,7 +1348,6 @@ errno_t sdap_access_rhost(struct ldb_message *user_entry, char *pam_rhost)
}
static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq);
-static int sdap_access_ppolicy_retry(struct tevent_req *req);
static errno_t sdap_access_ppolicy_step(struct tevent_req *req);
static void sdap_access_ppolicy_step_done(struct tevent_req *subreq);
@@ -1422,8 +1357,7 @@ struct sdap_access_ppolicy_req_ctx {
struct tevent_context *ev;
struct sdap_access_ctx *access_ctx;
struct sdap_options *opts;
- struct sdap_id_conn_ctx *conn;
- struct sdap_id_op *sdap_op;
+ struct sss_failover_ldap_connection *conn;
struct sysdb_handle *handle;
struct sss_domain_info *domain;
/* cached results of access control checks */
@@ -1441,7 +1375,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
struct be_ctx *be_ctx,
struct sss_domain_info *domain,
struct sdap_access_ctx *access_ctx,
- struct sdap_id_conn_ctx *conn,
const char *username,
struct ldb_message *user_entry,
enum sdap_pwpolicy_mode pwpol_mode)
@@ -1459,7 +1392,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
state->filter = NULL;
state->username = username;
state->opts = access_ctx->id_ctx->opts;
- state->conn = conn;
state->ev = ev;
state->access_ctx = access_ctx;
state->domain = domain;
@@ -1487,15 +1419,8 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_TRACE_FUNC, "Checking ppolicy against LDAP\n");
- state->sdap_op = sdap_id_op_create(state,
- state->conn->conn_cache);
- if (!state->sdap_op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto done;
- }
-
- ret = sdap_access_ppolicy_retry(req);
+ ret = sss_failover_transaction_send(state, ev, access_ctx->id_ctx->fctx,
+ req, sdap_access_ppolicy_connect_done);
if (ret != EOK) {
goto done;
}
@@ -1512,25 +1437,6 @@ sdap_access_ppolicy_send(TALLOC_CTX *mem_ctx,
return req;
}
-static int sdap_access_ppolicy_retry(struct tevent_req *req)
-{
- struct sdap_access_ppolicy_req_ctx *state;
- struct tevent_req *subreq;
- int ret;
-
- state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
- subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
- if (!subreq) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sdap_id_op_connect_send failed: %d (%s)\n",
- ret, sss_strerror(ret));
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_access_ppolicy_connect_done, req);
- return EOK;
-}
-
static const char**
get_default_ppolicy_dns(TALLOC_CTX *mem_ctx, struct sdap_domain *sdom)
{
@@ -1558,25 +1464,19 @@ static void sdap_access_ppolicy_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct sdap_access_ppolicy_req_ctx *state;
- int ret, dp_error;
+ int ret;
const char *ppolicy_dn;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_access_ppolicy_req_ctx);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
- ret = sdap_access_decide_offline(state->cached_access);
- if (ret == EOK) {
- tevent_req_done(req);
- return;
- }
- }
-
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -1648,7 +1548,7 @@ sdap_access_ppolicy_get_lockout_step(struct tevent_req *req)
subreq = sdap_get_generic_send(state,
state->ev,
state->opts,
- sdap_id_op_handle(state->sdap_op),
+ state->conn->sh,
state->ppolicy_dns[state->ppolicy_dns_index],
LDAP_SCOPE_BASE,
NULL, attrs,
@@ -1674,7 +1574,7 @@ sdap_access_ppolicy_get_lockout_step(struct tevent_req *req)
static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq)
{
- int ret, tret, dp_error;
+ int ret, tret;
size_t num_results;
bool pwdLockout = false;
struct sysdb_attrs **results;
@@ -1772,14 +1672,6 @@ static void sdap_access_ppolicy_get_lockout_done(struct tevent_req *subreq)
done:
if (ret != EAGAIN) {
- /* release connection */
- tret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (tret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_get_generic_send() returned error [%d][%s]\n",
- ret, sss_strerror(ret));
- }
-
if (ret == EOK) {
tevent_req_done(req);
} else {
@@ -1802,7 +1694,7 @@ errno_t sdap_access_ppolicy_step(struct tevent_req *req)
subreq = sdap_get_generic_send(state,
state->ev,
state->opts,
- sdap_id_op_handle(state->sdap_op),
+ state->conn->sh,
state->basedn,
LDAP_SCOPE_BASE,
NULL, attrs,
@@ -1911,7 +1803,7 @@ is_account_locked(const char *pwdAccountLockedTime,
static void sdap_access_ppolicy_step_done(struct tevent_req *subreq)
{
- int ret, tret, dp_error;
+ int ret, tret;
size_t num_results;
bool locked = false;
const char *pwdAccountLockedTime;
@@ -1926,25 +1818,6 @@ static void sdap_access_ppolicy_step_done(struct tevent_req *subreq)
ret = sdap_get_generic_recv(subreq, state, &num_results, &results);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (ret != EOK) {
- if (dp_error == DP_ERR_OK) {
- /* retry */
- tret = sdap_access_ppolicy_retry(req);
- if (tret == EOK) {
- return;
- }
- } else if (dp_error == DP_ERR_OFFLINE) {
- ret = sdap_access_decide_offline(state->cached_access);
- } else {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_id_op_done() returned error [%d][%s]\n",
- ret, sss_strerror(ret));
- }
-
- goto done;
- }
-
/* Check the number of responses we got
* If it's exactly 1, we passed the check
* If it's < 1, we failed the check
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index d342b5d9d28..809628efab6 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -30,6 +30,9 @@
#include "providers/ldap/sdap.h"
#include "providers/ldap/sdap_id_op.h"
#include "providers/fail_over.h"
+#include "providers/failover/failover.h"
+#include "providers/failover/ldap/failover_ldap.h"
+#include "providers/failover/failover_transaction.h"
#define AD_TOKENGROUPS_ATTR "tokenGroups"
@@ -161,7 +164,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
struct sdap_id_ctx *id_ctx,
struct sdap_attr_map *user_map,
size_t user_map_cnt,
- struct sdap_id_conn_ctx *conn,
+ struct sss_failover_ldap_connection *conn,
struct sdap_search_base **search_bases,
const char *name,
int filter_type,
@@ -411,7 +414,7 @@ struct tevent_req *
enum_services_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge);
errno_t
@@ -438,7 +441,7 @@ struct tevent_req *
enum_iphosts_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge);
errno_t
@@ -466,7 +469,7 @@ struct tevent_req *
enum_ipnetworks_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge);
errno_t
diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c
index 8a542f971c9..1cd1b880ad0 100644
--- a/src/providers/ldap/sdap_async_autofs.c
+++ b/src/providers/ldap/sdap_async_autofs.c
@@ -640,15 +640,12 @@ struct sdap_autofs_setautomntent_state {
struct sdap_options *opts;
struct sdap_handle *sh;
struct sysdb_ctx *sysdb;
- struct sdap_id_op *sdap_op;
struct sss_domain_info *dom;
const char *mapname;
struct sysdb_attrs *map;
struct sysdb_attrs **entries;
size_t entries_count;
-
- int dp_error;
};
static void
@@ -660,7 +657,6 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct sysdb_ctx *sysdb,
struct sdap_handle *sh,
- struct sdap_id_op *op,
struct sdap_options *opts,
const char *mapname)
{
@@ -683,7 +679,6 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx,
state->sh = sh;
state->sysdb = sysdb;
state->opts = opts;
- state->sdap_op = op;
state->dom = dom;
state->mapname = mapname;
@@ -767,7 +762,6 @@ sdap_autofs_setautomntent_done(struct tevent_req *subreq)
return;
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
return;
}
@@ -968,13 +962,11 @@ sdap_autofs_setautomntent_recv(struct tevent_req *req)
struct sdap_autofs_get_map_state {
struct sdap_id_ctx *id_ctx;
+ struct sss_failover_ldap_connection *conn;
struct sdap_options *opts;
- struct sdap_id_op *sdap_op;
const char *mapname;
- int dp_error;
};
-static errno_t sdap_autofs_get_map_retry(struct tevent_req *req);
static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq);
static void sdap_autofs_get_map_done(struct tevent_req *subreq);
@@ -994,52 +986,16 @@ struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx,
state->id_ctx = id_ctx;
state->opts = id_ctx->opts;
state->mapname = mapname;
- state->dp_error = DP_ERR_FATAL;
-
- state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache);
- if (!state->sdap_op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
- ret = ENOMEM;
- goto done;
- }
- ret = sdap_autofs_get_map_retry(req);
- if (ret == EAGAIN) {
- /* asynchronous processing */
- return req;
- }
-
-done:
- if (ret == EOK) {
- tevent_req_done(req);
- } else {
+ ret = sss_failover_transaction_send(state, id_ctx->be->ev, id_ctx->fctx, req,
+ sdap_autofs_get_map_connect_done);
+ if (ret != EOK) {
tevent_req_error(req, ret);
}
- tevent_req_post(req, id_ctx->be->ev);
return req;
}
-static errno_t sdap_autofs_get_map_retry(struct tevent_req *req)
-{
- struct sdap_autofs_get_map_state *state;
- struct tevent_req *subreq;
- int ret;
-
- state = tevent_req_data(req, struct sdap_autofs_get_map_state);
-
- subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
- if (subreq == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: "
- "%d(%s)\n", ret, strerror(ret));
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_autofs_get_map_connect_done, req);
-
- return EAGAIN;
-}
-
static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
@@ -1047,25 +1003,21 @@ static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq)
char *filter;
char *safe_mapname;
const char **attrs;
- int dp_error;
int ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_autofs_get_map_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed "
- "[%d]: %s\n", ret, strerror(ret));
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
- DEBUG(SSSDBG_TRACE_FUNC, "LDAP connection successful\n");
-
ret = sss_filter_sanitize(state, state->mapname, &safe_mapname);
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -1091,13 +1043,12 @@ static void sdap_autofs_get_map_connect_done(struct tevent_req *subreq)
}
subreq = sdap_search_bases_return_first_send(state, state->id_ctx->be->ev,
- state->opts, sdap_id_op_handle(state->sdap_op),
+ state->opts, state->conn->sh,
state->opts->sdom->autofs_search_bases,
state->opts->autofs_mobject_map, false,
dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT),
filter, attrs, NULL);
if (subreq == NULL) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
@@ -1120,19 +1071,6 @@ static void sdap_autofs_get_map_done(struct tevent_req *subreq)
&reply);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error);
- if (state->dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_autofs_get_map_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- }
- return;
- } else if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
if (reply_count == 0) {
ret = sysdb_delete_autofsmap(state->id_ctx->be->domain, state->mapname);
if (ret != EOK && ret != ENOENT) {
@@ -1159,30 +1097,21 @@ static void sdap_autofs_get_map_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-errno_t sdap_autofs_get_map_recv(struct tevent_req *req,
- int *dp_error)
+errno_t sdap_autofs_get_map_recv(struct tevent_req *req)
{
- struct sdap_autofs_get_map_state *state;
-
- state = tevent_req_data(req, struct sdap_autofs_get_map_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
return EOK;
}
struct sdap_autofs_get_entry_state {
struct sdap_id_ctx *id_ctx;
struct sdap_options *opts;
- struct sdap_id_op *sdap_op;
+ struct sss_failover_ldap_connection *conn;
const char *mapname;
const char *entryname;
- int dp_error;
};
-static errno_t sdap_autofs_get_entry_retry(struct tevent_req *req);
static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq);
static void sdap_autofs_get_entry_done(struct tevent_req *subreq);
@@ -1204,52 +1133,17 @@ struct tevent_req *sdap_autofs_get_entry_send(TALLOC_CTX *mem_ctx,
state->opts = id_ctx->opts;
state->mapname = mapname;
state->entryname = entryname;
- state->dp_error = DP_ERR_FATAL;
- state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache);
- if (!state->sdap_op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
- ret = ENOMEM;
- goto done;
- }
+ ret = sss_failover_transaction_send(state, id_ctx->be->ev, id_ctx->fctx, req,
+ sdap_autofs_get_entry_connect_done);
- ret = sdap_autofs_get_entry_retry(req);
- if (ret == EAGAIN) {
- /* asynchronous processing */
- return req;
- }
-
-done:
- if (ret == EOK) {
- tevent_req_done(req);
- } else {
+ if (ret != EOK) {
tevent_req_error(req, ret);
}
- tevent_req_post(req, id_ctx->be->ev);
return req;
}
-static errno_t sdap_autofs_get_entry_retry(struct tevent_req *req)
-{
- struct sdap_autofs_get_entry_state *state;
- struct tevent_req *subreq;
- int ret;
-
- state = tevent_req_data(req, struct sdap_autofs_get_entry_state);
-
- subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
- if (subreq == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: "
- "%d(%s)\n", ret, strerror(ret));
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_autofs_get_entry_connect_done, req);
-
- return EAGAIN;
-}
-
static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
@@ -1259,20 +1153,18 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq)
char *safe_entryname;
const char **attrs;
const char *base_dn;
- int dp_error;
int ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_autofs_get_entry_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "LDAP connection failed "
- "[%d]: %s\n", ret, strerror(ret));
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -1323,13 +1215,12 @@ static void sdap_autofs_get_entry_connect_done(struct tevent_req *subreq)
}
subreq = sdap_search_bases_return_first_send(state, state->id_ctx->be->ev,
- state->opts, sdap_id_op_handle(state->sdap_op),
+ state->opts, state->conn->sh,
state->opts->sdom->autofs_search_bases,
state->opts->autofs_entry_map, false,
dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT),
filter, attrs, base_dn);
if (subreq == NULL) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
@@ -1359,19 +1250,6 @@ static void sdap_autofs_get_entry_done(struct tevent_req *subreq)
&reply);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &state->dp_error);
- if (state->dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_autofs_get_entry_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- }
- return;
- } else if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
/* This will delete the entry if it already exist. */
if (reply_count == 0) {
ret = sdap_autofs_save_entry(state->id_ctx->be->domain, state->opts,
@@ -1402,17 +1280,10 @@ static void sdap_autofs_get_entry_done(struct tevent_req *subreq)
return;
}
-errno_t sdap_autofs_get_entry_recv(struct tevent_req *req,
- int *dp_error)
+errno_t sdap_autofs_get_entry_recv(struct tevent_req *req)
{
- struct sdap_autofs_get_entry_state *state;
-
- state = tevent_req_data(req, struct sdap_autofs_get_entry_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
return EOK;
}
diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c
index 44cec84adb7..98df7971035 100644
--- a/src/providers/ldap/sdap_async_enum.c
+++ b/src/providers/ldap/sdap_async_enum.c
@@ -36,7 +36,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge);
static errno_t enum_users_recv(struct tevent_req *req);
@@ -44,7 +44,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge);
static errno_t enum_groups_recv(struct tevent_req *req);
@@ -54,20 +54,13 @@ struct sdap_dom_enum_ex_state {
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_conn_ctx *user_conn;
- struct sdap_id_conn_ctx *group_conn;
- struct sdap_id_conn_ctx *svc_conn;
- struct sdap_id_op *user_op;
- struct sdap_id_op *group_op;
- struct sdap_id_op *svc_op;
+ struct sss_failover_ldap_connection *conn;
+ struct sss_failover_ldap_connection *group_conn;
+ struct sss_failover_ldap_connection *svc_conn;
bool purge;
};
-static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
- struct sdap_id_op *op,
- tevent_req_fn tcb);
-static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq);
static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq);
static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq);
static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq);
@@ -79,10 +72,7 @@ struct tevent_req *
sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
- struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *user_conn,
- struct sdap_id_conn_ctx *group_conn,
- struct sdap_id_conn_ctx *svc_conn)
+ struct sdap_domain *sdom)
{
struct tevent_req *req;
struct sdap_dom_enum_ex_state *state;
@@ -95,9 +85,6 @@ sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
state->ev = ev;
state->ctx = ctx;
state->sdom = sdom;
- state->user_conn = user_conn;
- state->group_conn = group_conn;
- state->svc_conn = svc_conn;
ctx->last_enum = tevent_timeval_current();
t = dp_opt_get_int(ctx->opts->basic, SDAP_PURGE_CACHE_TIMEOUT);
@@ -105,17 +92,10 @@ sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
state->purge = true;
}
- state->user_op = sdap_id_op_create(state, user_conn->conn_cache);
- if (state->user_op == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for users\n");
- ret = EIO;
- goto fail;
- }
-
- ret = sdap_dom_enum_ex_retry(req, state->user_op,
- sdap_dom_enum_ex_get_users);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ sdap_dom_enum_ex_get_users);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_dom_enum_ex_retry failed\n");
+ DEBUG(SSSDBG_OP_FAILURE, "sss_failover_transaction_send failed\n");
goto fail;
}
@@ -127,52 +107,6 @@ sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
return req;
}
-static errno_t sdap_dom_enum_ex_retry(struct tevent_req *req,
- struct sdap_id_op *op,
- tevent_req_fn tcb)
-{
- struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
- struct sdap_dom_enum_ex_state);
- struct tevent_req *subreq;
- errno_t ret;
-
- subreq = sdap_id_op_connect_send(op, state, &ret);
- if (subreq == NULL) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sdap_id_op_connect_send failed: %d\n", ret);
- return ret;
- }
-
- tevent_req_set_callback(subreq, tcb, req);
- return EOK;
-}
-
-static bool sdap_dom_enum_ex_connected(struct tevent_req *subreq)
-{
- errno_t ret;
- int dp_error;
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
-
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
- talloc_zfree(subreq);
- if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC,
- "Backend is marked offline, retry later!\n");
- tevent_req_done(req);
- } else {
- DEBUG(SSSDBG_MINOR_FAILURE,
- "Domain enumeration failed to connect to " \
- "LDAP server: (%d)[%s]\n", ret, strerror(ret));
- tevent_req_error(req, ret);
- }
- return false;
- }
-
- return true;
-}
-
static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -180,13 +114,19 @@ static void sdap_dom_enum_ex_get_users(struct tevent_req *subreq)
struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
struct sdap_dom_enum_ex_state);
- if (sdap_dom_enum_ex_connected(subreq) == false) {
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = enum_users_send(state, state->ev,
state->ctx, state->sdom,
- state->user_op, state->purge);
+ state->conn, state->purge);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
return;
@@ -201,25 +141,10 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq)
struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
struct sdap_dom_enum_ex_state);
errno_t ret;
- int dp_error;
ret = enum_users_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->user_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_dom_enum_ex_retry(req, state->user_op,
- sdap_dom_enum_ex_get_users);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
- tevent_req_done(req);
- return;
- } else if (ret != EOK && ret != ENOENT) {
+ if (ret != EOK && ret != ENOENT) {
/* Non-recoverable error */
DEBUG(SSSDBG_OP_FAILURE,
"User enumeration failed: %d: %s\n", ret, sss_strerror(ret));
@@ -227,15 +152,8 @@ static void sdap_dom_enum_ex_users_done(struct tevent_req *subreq)
return;
}
- state->group_op = sdap_id_op_create(state, state->group_conn->conn_cache);
- if (state->group_op == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for groups\n");
- tevent_req_error(req, EIO);
- return;
- }
-
- ret = sdap_dom_enum_ex_retry(req, state->group_op,
- sdap_dom_enum_ex_get_groups);
+ ret = sss_failover_transaction_send(state, state->ev, state->ctx->fctx, req,
+ sdap_dom_enum_ex_get_groups);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -251,13 +169,19 @@ static void sdap_dom_enum_ex_get_groups(struct tevent_req *subreq)
struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
struct sdap_dom_enum_ex_state);
- if (sdap_dom_enum_ex_connected(subreq) == false) {
+ state->group_conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->group_conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = enum_groups_send(state, state->ev, state->ctx,
state->sdom,
- state->group_op, state->purge);
+ state->group_conn, state->purge);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
return;
@@ -272,25 +196,10 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq)
struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
struct sdap_dom_enum_ex_state);
int ret;
- int dp_error;
ret = enum_groups_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->group_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_dom_enum_ex_retry(req, state->group_op,
- sdap_dom_enum_ex_get_groups);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
- tevent_req_done(req);
- return;
- } else if (ret != EOK && ret != ENOENT) {
+ if (ret != EOK && ret != ENOENT) {
/* Non-recoverable error */
DEBUG(SSSDBG_OP_FAILURE,
"Group enumeration failed: %d: %s\n", ret, sss_strerror(ret));
@@ -298,16 +207,9 @@ static void sdap_dom_enum_ex_groups_done(struct tevent_req *subreq)
return;
}
+ ret = sss_failover_transaction_send(state, state->ev, state->ctx->fctx, req,
+ sdap_dom_enum_ex_get_svcs);
- state->svc_op = sdap_id_op_create(state, state->svc_conn->conn_cache);
- if (state->svc_op == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for svcs\n");
- tevent_req_error(req, EIO);
- return;
- }
-
- ret = sdap_dom_enum_ex_retry(req, state->svc_op,
- sdap_dom_enum_ex_get_svcs);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -321,12 +223,18 @@ static void sdap_dom_enum_ex_get_svcs(struct tevent_req *subreq)
struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
struct sdap_dom_enum_ex_state);
- if (sdap_dom_enum_ex_connected(subreq) == false) {
+ state->svc_conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->svc_conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = enum_services_send(state, state->ev, state->ctx,
- state->svc_op, state->purge);
+ state->svc_conn, state->purge);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
@@ -341,25 +249,10 @@ static void sdap_dom_enum_ex_svcs_done(struct tevent_req *subreq)
struct sdap_dom_enum_ex_state *state = tevent_req_data(req,
struct sdap_dom_enum_ex_state);
int ret;
- int dp_error;
ret = enum_services_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->svc_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_dom_enum_ex_retry(req, state->user_op,
- sdap_dom_enum_ex_get_svcs);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
- tevent_req_done(req);
- return;
- } else if (ret != EOK && ret != ENOENT) {
+ if (ret != EOK && ret != ENOENT) {
/* Non-recoverable error */
DEBUG(SSSDBG_OP_FAILURE,
"Service enumeration failed: %d: %s\n", ret, sss_strerror(ret));
@@ -406,10 +299,9 @@ struct tevent_req *
sdap_dom_enum_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
- struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn)
+ struct sdap_domain *sdom)
{
- return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom, conn, conn, conn);
+ return sdap_dom_enum_ex_send(memctx, ev, ctx, sdom);
}
errno_t sdap_dom_enum_recv(struct tevent_req *req)
@@ -422,7 +314,7 @@ struct enum_users_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_op *op;
+ struct sss_failover_ldap_connection *conn;
char *filter;
const char **attrs;
@@ -434,7 +326,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge)
{
struct tevent_req *req, *subreq;
@@ -448,7 +340,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
state->ev = ev;
state->sdom = sdom;
state->ctx = ctx;
- state->op = op;
+ state->conn = conn;
use_mapping = sdap_idmap_domain_has_algorithmic_mapping(
ctx->opts->idmap_ctx,
@@ -488,7 +380,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
goto fail;
}
- if (ctx->srv_opts && ctx->srv_opts->max_user_value && !purge) {
+ if (conn->srv_opts && conn->srv_opts->max_user_value && !purge) {
/* If we have lastUSN available and we're not doing a full
* refresh, limit to changes with a higher entryUSN value.
*/
@@ -496,9 +388,9 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
state->filter,
"(%s>=%s)(!(%s=%s))",
ctx->opts->user_map[SDAP_AT_USER_USN].name,
- ctx->srv_opts->max_user_value,
+ conn->srv_opts->max_user_value,
ctx->opts->user_map[SDAP_AT_USER_USN].name,
- ctx->srv_opts->max_user_value);
+ conn->srv_opts->max_user_value);
if (!state->filter) {
DEBUG(SSSDBG_MINOR_FAILURE,
@@ -530,7 +422,7 @@ static struct tevent_req *enum_users_send(TALLOC_CTX *memctx,
state->sdom->dom->sysdb,
state->ctx->opts,
state->sdom->user_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->ctx->opts->basic,
SDAP_ENUM_SEARCH_TIMEOUT),
@@ -568,19 +460,19 @@ static void enum_users_done(struct tevent_req *subreq)
}
if (usn_value) {
- talloc_zfree(state->ctx->srv_opts->max_user_value);
- state->ctx->srv_opts->max_user_value =
+ talloc_zfree(state->conn->srv_opts->max_user_value);
+ state->conn->srv_opts->max_user_value =
talloc_steal(state->ctx, usn_value);
errno = 0;
usn_number = strtoul(usn_value, &endptr, 10);
if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
- && (usn_number > state->ctx->srv_opts->last_usn)) {
- state->ctx->srv_opts->last_usn = usn_number;
+ && (usn_number > state->conn->srv_opts->last_usn)) {
+ state->conn->srv_opts->last_usn = usn_number;
}
}
DEBUG(SSSDBG_CONF_SETTINGS, "Users higher USN value: [%s]\n",
- state->ctx->srv_opts->max_user_value);
+ state->conn->srv_opts->max_user_value);
tevent_req_done(req);
}
@@ -597,7 +489,7 @@ struct enum_groups_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
struct sdap_domain *sdom;
- struct sdap_id_op *op;
+ struct sss_failover_ldap_connection *conn;
char *filter;
const char **attrs;
@@ -609,7 +501,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
struct sdap_domain *sdom,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge)
{
struct tevent_req *req, *subreq;
@@ -625,7 +517,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
state->ev = ev;
state->sdom = sdom;
state->ctx = ctx;
- state->op = op;
+ state->conn = conn;
if (sdom->dom->type == DOM_TYPE_APPLICATION) {
non_posix = true;
@@ -674,14 +566,14 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
goto fail;
}
- if (ctx->srv_opts && ctx->srv_opts->max_group_value && !purge) {
+ if (state->conn->srv_opts && state->conn->srv_opts->max_group_value && !purge) {
state->filter = talloc_asprintf_append_buffer(
state->filter,
"(%s>=%s)(!(%s=%s))",
ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
- ctx->srv_opts->max_group_value,
+ state->conn->srv_opts->max_group_value,
ctx->opts->group_map[SDAP_AT_GROUP_USN].name,
- ctx->srv_opts->max_group_value);
+ state->conn->srv_opts->max_group_value);
if (!state->filter) {
DEBUG(SSSDBG_MINOR_FAILURE,
"Failed to build base filter\n");
@@ -710,7 +602,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx,
subreq = sdap_get_groups_send(state, state->ev,
state->sdom,
state->ctx->opts,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->ctx->opts->basic,
SDAP_ENUM_SEARCH_TIMEOUT),
@@ -748,19 +640,19 @@ static void enum_groups_done(struct tevent_req *subreq)
}
if (usn_value) {
- talloc_zfree(state->ctx->srv_opts->max_group_value);
- state->ctx->srv_opts->max_group_value =
+ talloc_zfree(state->conn->srv_opts->max_group_value);
+ state->conn->srv_opts->max_group_value =
talloc_steal(state->ctx, usn_value);
errno = 0;
usn_number = strtoul(usn_value, &endptr, 10);
if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
- && (usn_number > state->ctx->srv_opts->last_usn)) {
- state->ctx->srv_opts->last_usn = usn_number;
+ && (usn_number > state->conn->srv_opts->last_usn)) {
+ state->conn->srv_opts->last_usn = usn_number;
}
}
DEBUG(SSSDBG_CONF_SETTINGS, "Groups higher USN value: [%s]\n",
- state->ctx->srv_opts->max_group_value);
+ state->conn->srv_opts->max_group_value);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_async_enum.h b/src/providers/ldap/sdap_async_enum.h
index 2da38f98891..9e728213397 100644
--- a/src/providers/ldap/sdap_async_enum.h
+++ b/src/providers/ldap/sdap_async_enum.h
@@ -30,10 +30,7 @@ struct tevent_req *
sdap_dom_enum_ex_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
- struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *user_conn,
- struct sdap_id_conn_ctx *group_conn,
- struct sdap_id_conn_ctx *svc_conn);
+ struct sdap_domain *sdom);
errno_t sdap_dom_enum_ex_recv(struct tevent_req *req);
@@ -41,8 +38,7 @@ struct tevent_req *
sdap_dom_enum_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *ctx,
- struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn);
+ struct sdap_domain *sdom);
errno_t sdap_dom_enum_recv(struct tevent_req *req);
diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c
index b0df2080b11..5ece72f9988 100644
--- a/src/providers/ldap/sdap_async_groups.c
+++ b/src/providers/ldap/sdap_async_groups.c
@@ -1815,12 +1815,11 @@ static void sdap_get_groups_ldap_connect_done(struct tevent_req *subreq)
struct tevent_req *req;
struct sdap_get_groups_state *state;
int ret;
- int dp_error;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_get_groups_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c
index 3d1137f6638..18c556422e2 100644
--- a/src/providers/ldap/sdap_async_initgroups.c
+++ b/src/providers/ldap/sdap_async_initgroups.c
@@ -2651,7 +2651,7 @@ struct sdap_get_initgr_state {
struct sdap_domain *sdom;
struct sdap_handle *sh;
struct sdap_id_ctx *id_ctx;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
struct sdap_id_op *user_op;
const char *filter_value;
const char **grp_attrs;
@@ -2671,7 +2671,6 @@ struct sdap_get_initgr_state {
};
static errno_t sdap_get_initgr_next_base(struct tevent_req *req);
-static errno_t sdap_get_initgr_user_connect(struct tevent_req *req);
static void sdap_get_initgr_user_connect_done(struct tevent_req *subreq);
static void sdap_get_initgr_user(struct tevent_req *subreq);
static void sdap_get_initgr_done(struct tevent_req *subreq);
@@ -2683,7 +2682,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
struct sdap_id_ctx *id_ctx,
struct sdap_attr_map *user_map,
size_t user_map_cnt,
- struct sdap_id_conn_ctx *conn,
+ struct sss_failover_ldap_connection *conn,
struct sdap_search_base **search_bases,
const char *filter_value,
int filter_type,
@@ -2863,7 +2862,9 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
state->dom->name,
state->dom->domain_id);
- ret = sdap_get_initgr_user_connect(req);
+
+ ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req,
+ sdap_get_initgr_user_connect_done);
done:
if (ret != EOK) {
@@ -2874,47 +2875,22 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
return req;
}
-static errno_t sdap_get_initgr_user_connect(struct tevent_req *req)
-{
- struct tevent_req *subreq;
- struct sdap_get_initgr_state *state;
- int ret = EOK;
- struct sdap_id_conn_ctx *user_conn = NULL;
-
- state = tevent_req_data(req, struct sdap_get_initgr_state);
-
- /* Prefer LDAP over GC for users */
- user_conn = get_ldap_conn_from_sdom_pvt(state->id_ctx->opts, state->sdom);
- state->user_op = sdap_id_op_create(state, user_conn == NULL
- ? state->conn->conn_cache
- : user_conn->conn_cache);
- if (state->user_op == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- return ENOMEM;
- }
-
- subreq = sdap_id_op_connect_send(state->user_op, state, &ret);
- if (subreq == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed\n");
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_get_initgr_user_connect_done, req);
- return EOK;
-}
-
static void sdap_get_initgr_user_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
struct tevent_req);
- int dp_error = DP_ERR_FATAL;
int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ struct sdap_get_initgr_state *state =
+ tevent_req_data(req, struct sdap_get_initgr_state);
+
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -2944,7 +2920,7 @@ static errno_t sdap_get_initgr_next_base(struct tevent_req *req)
state->user_search_bases[state->user_base_iter]->basedn);
subreq = sdap_get_generic_send(
- state, state->ev, state->opts, sdap_id_op_handle(state->user_op),
+ state, state->ev, state->opts, state->conn->sh,
state->user_search_bases[state->user_base_iter]->basedn,
state->user_search_bases[state->user_base_iter]->scope,
state->filter, state->user_attrs,
@@ -3112,18 +3088,21 @@ static void sdap_get_initgr_user(struct tevent_req *subreq)
*/
subreq = sdap_ad_tokengroups_initgroups_send(state, state->ev,
state->id_ctx,
- state->conn,
+ /* FIXME: Placeholder to be updated when
+ * AD is moved to new Failover
+ * Set to state->conn */
+ state->id_ctx->conn,
state->opts,
state->sysdb,
state->dom,
- state->sh,
+ state->conn->sh,
cname, orig_dn,
state->timeout,
state->use_id_mapping);
} else {
subreq = sdap_initgr_rfc2307bis_send(
state, state->ev, state->opts,
- state->sdom, state->sh,
+ state->sdom, state->conn->sh,
cname, orig_dn);
}
if (!subreq) {
@@ -3395,9 +3374,10 @@ static void sdap_get_initgr_done(struct tevent_req *subreq)
}
subreq = groups_get_send(req, state->ev, state->id_ctx,
- state->id_ctx->opts->sdom, state->conn,
+ state->id_ctx->opts->sdom,
gid, BE_FILTER_IDNUM, false,
- false, false);
+ false, false,
+ state->id_ctx->conn->no_mpg_user_fallback);
if (!subreq) {
ret = ENOMEM;
goto done;
@@ -3442,7 +3422,7 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq)
tevent_req_callback_data(subreq, struct tevent_req);
errno_t ret;
- ret = groups_get_recv(subreq, NULL, NULL);
+ ret = groups_get_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c
index c8f82d7ed5f..bf042bdb777 100644
--- a/src/providers/ldap/sdap_async_initgroups_ad.c
+++ b/src/providers/ldap/sdap_async_initgroups_ad.c
@@ -345,8 +345,9 @@ static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req)
}
subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain,
- state->conn, state->current_sid,
- BE_FILTER_SECID, false, true, false);
+ state->current_sid, BE_FILTER_SECID, false,
+ true, false,
+ state->conn->no_mpg_user_fallback);
if (subreq == NULL) {
return ENOMEM;
}
@@ -360,27 +361,25 @@ static void sdap_ad_resolve_sids_done(struct tevent_req *subreq)
{
struct sdap_ad_resolve_sids_state *state = NULL;
struct tevent_req *req = NULL;
- int dp_error;
- int sdap_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ad_resolve_sids_state);
- ret = groups_get_recv(subreq, &dp_error, &sdap_error);
+ ret = groups_get_recv(subreq);
talloc_zfree(subreq);
- if (ret == EOK && sdap_error == ENOENT && dp_error == DP_ERR_OK) {
+ if (ret == ENOENT) {
/* Group was not found, we will ignore the error and continue with
* next group. This may happen for example if the group is built-in,
* but a custom search base is provided. */
DEBUG(SSSDBG_MINOR_FAILURE,
"Unable to resolve SID %s - will try next sid.\n",
state->current_sid);
- } else if (ret != EOK || sdap_error != EOK || dp_error != DP_ERR_OK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s [dp_error: %d, "
- "sdap_error: %d, ret: %d]: %s\n", state->current_sid, dp_error,
- sdap_error, ret, strerror(ret));
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to resolve SID %s, "
+ "ret: %d]: %s\n", state->current_sid,
+ ret, strerror(ret));
goto done;
}
@@ -524,14 +523,13 @@ sdap_ad_tokengroups_initgr_mapping_connect_done(struct tevent_req *subreq)
struct sdap_ad_tokengroups_initgr_mapping_state *state = NULL;
struct tevent_req *req = NULL;
int ret;
- int dp_error = DP_ERR_FATAL;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req,
struct sdap_ad_tokengroups_initgr_mapping_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -871,14 +869,13 @@ sdap_ad_tokengroups_initgr_posix_sids_connect_done(struct tevent_req *subreq)
struct sdap_ad_tokengroups_initgr_posix_state *state = NULL;
struct tevent_req *req = NULL;
int ret;
- int dp_error = DP_ERR_FATAL;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req,
struct sdap_ad_tokengroups_initgr_posix_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
@@ -1161,7 +1158,6 @@ struct sdap_ad_get_domain_local_groups_state {
struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *dom;
- int dp_error;
struct sdap_search_base **search_bases;
struct sysdb_attrs **groups;
@@ -1244,14 +1240,12 @@ sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq)
struct tevent_req);
struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req,
struct sdap_ad_get_domain_local_groups_state);
- int dp_error = DP_ERR_FATAL;
int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ ret = sdap_id_op_connect_recv(subreq);
talloc_zfree(subreq);
if (ret != EOK) {
- state->dp_error = dp_error;
tevent_req_error(req, ret);
return;
}
@@ -1263,7 +1257,6 @@ sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq)
state->group_hash, 0);
if (subreq == NULL) {
DEBUG(SSSDBG_OP_FAILURE, "rfc2307bis_nested_groups_send failed.\n");
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
diff --git a/src/providers/ldap/sdap_async_iphost.c b/src/providers/ldap/sdap_async_iphost.c
index 4b4dcadbe5f..cdb24ba6759 100644
--- a/src/providers/ldap/sdap_async_iphost.c
+++ b/src/providers/ldap/sdap_async_iphost.c
@@ -507,7 +507,7 @@ sdap_get_iphost_recv(TALLOC_CTX *mem_ctx,
struct enum_iphosts_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
- struct sdap_id_op *op;
+ struct sss_failover_ldap_connection *conn;
struct sss_domain_info *domain;
struct sysdb_ctx *sysdb;
@@ -522,7 +522,7 @@ struct tevent_req *
enum_iphosts_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge)
{
errno_t ret;
@@ -537,7 +537,7 @@ enum_iphosts_send(TALLOC_CTX *memctx,
state->id_ctx = id_ctx;
state->domain = id_ctx->be->domain;
state->sysdb = id_ctx->be->domain->sysdb;
- state->op = op;
+ state->conn = conn;
if (id_ctx->srv_opts && id_ctx->srv_opts->max_iphost_value && !purge) {
state->filter = talloc_asprintf(
@@ -575,7 +575,7 @@ enum_iphosts_send(TALLOC_CTX *memctx,
state->domain, state->sysdb,
state->id_ctx->opts,
state->id_ctx->opts->sdom->iphost_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
diff --git a/src/providers/ldap/sdap_async_ipnetwork.c b/src/providers/ldap/sdap_async_ipnetwork.c
index 5e5b18158c0..ff1fec89bb5 100644
--- a/src/providers/ldap/sdap_async_ipnetwork.c
+++ b/src/providers/ldap/sdap_async_ipnetwork.c
@@ -493,6 +493,7 @@ sdap_get_ipnetwork_recv(TALLOC_CTX *mem_ctx,
struct enum_ipnetworks_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
+ struct sss_failover_ldap_connection *conn;
struct sdap_id_op *op;
struct sss_domain_info *domain;
struct sysdb_ctx *sysdb;
@@ -508,7 +509,7 @@ struct tevent_req *
enum_ipnetworks_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge)
{
errno_t ret;
@@ -523,9 +524,9 @@ enum_ipnetworks_send(TALLOC_CTX *memctx,
state->id_ctx = id_ctx;
state->domain = id_ctx->be->domain;
state->sysdb = id_ctx->be->domain->sysdb;
- state->op = op;
+ state->conn = conn;
- if (id_ctx->srv_opts && id_ctx->srv_opts->max_ipnetwork_value && !purge) {
+ if (conn->srv_opts && conn->srv_opts->max_ipnetwork_value && !purge) {
state->filter = talloc_asprintf(
state,
"(&(objectclass=%s)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))",
@@ -533,9 +534,9 @@ enum_ipnetworks_send(TALLOC_CTX *memctx,
id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_NAME].name,
id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_NUMBER].name,
id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_USN].name,
- id_ctx->srv_opts->max_ipnetwork_value,
+ conn->srv_opts->max_ipnetwork_value,
id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_USN].name,
- id_ctx->srv_opts->max_ipnetwork_value);
+ conn->srv_opts->max_ipnetwork_value);
} else {
state->filter = talloc_asprintf(
state,
@@ -560,7 +561,7 @@ enum_ipnetworks_send(TALLOC_CTX *memctx,
subreq = sdap_get_ipnetwork_send(state, state->ev,
state->domain, state->sysdb, state->id_ctx->opts,
state->id_ctx->opts->sdom->ipnetwork_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -599,19 +600,19 @@ enum_ipnetworks_op_done(struct tevent_req *subreq)
}
if (usn_value) {
- talloc_zfree(state->id_ctx->srv_opts->max_ipnetwork_value);
- state->id_ctx->srv_opts->max_ipnetwork_value =
+ talloc_zfree(state->conn->srv_opts->max_ipnetwork_value);
+ state->conn->srv_opts->max_ipnetwork_value =
talloc_steal(state->id_ctx, usn_value);
errno = 0;
usn_number = strtoul(usn_value, &endptr, 10);
if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
- && (usn_number > state->id_ctx->srv_opts->last_usn)) {
- state->id_ctx->srv_opts->last_usn = usn_number;
+ && (usn_number > state->conn->srv_opts->last_usn)) {
+ state->conn->srv_opts->last_usn = usn_number;
}
}
DEBUG(SSSDBG_FUNC_DATA, "IP network higher USN value: [%s]\n",
- state->id_ctx->srv_opts->max_ipnetwork_value);
+ state->conn->srv_opts->max_ipnetwork_value);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_async_resolver_enum.c b/src/providers/ldap/sdap_async_resolver_enum.c
index 8c92260b7d1..db7533e1d94 100644
--- a/src/providers/ldap/sdap_async_resolver_enum.c
+++ b/src/providers/ldap/sdap_async_resolver_enum.c
@@ -25,10 +25,6 @@
#include "providers/ldap/ldap_resolver_enum.h"
#include "providers/ldap/sdap_async_resolver_enum.h"
-static errno_t sdap_dom_resolver_enum_retry(struct tevent_req *req,
- struct sdap_id_op *op,
- tevent_req_fn tcb);
-static bool sdap_dom_resolver_enum_connected(struct tevent_req *subreq);
static void sdap_dom_resolver_enum_get_iphost(struct tevent_req *subreq);
static void sdap_dom_resolver_enum_iphost_done(struct tevent_req *subreq);
static void sdap_dom_resolver_enum_get_ipnetwork(struct tevent_req *subreq);
@@ -40,9 +36,8 @@ struct sdap_dom_resolver_enum_state {
struct sdap_id_ctx *id_ctx;
struct sdap_domain *sdom;
- struct sdap_id_conn_ctx *conn;
- struct sdap_id_op *iphost_op;
- struct sdap_id_op *ipnetwork_op;
+ struct sss_failover_ldap_connection *iphost_conn;
+ struct sss_failover_ldap_connection *ipnetwork_conn;
bool purge;
};
@@ -52,8 +47,7 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_resolver_ctx *resolver_ctx,
struct sdap_id_ctx *id_ctx,
- struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn)
+ struct sdap_domain *sdom)
{
struct tevent_req *req;
struct sdap_dom_resolver_enum_state *state;
@@ -67,7 +61,6 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx,
state->resolver_ctx = resolver_ctx;
state->id_ctx = id_ctx;
state->sdom = sdom;
- state->conn = conn;
state->resolver_ctx->last_enum = tevent_timeval_current();
t = dp_opt_get_int(resolver_ctx->id_ctx->opts->basic, SDAP_PURGE_CACHE_TIMEOUT);
@@ -75,17 +68,10 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx,
state->purge = true;
}
- state->iphost_op = sdap_id_op_create(state, conn->conn_cache);
- if (state->iphost_op == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_create failed for iphosts\n");
- ret = EIO;
- goto fail;
- }
-
- ret = sdap_dom_resolver_enum_retry(req, state->iphost_op,
- sdap_dom_resolver_enum_get_iphost);
+ ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req,
+ sdap_dom_resolver_enum_get_iphost);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_dom_enum_retry failed\n");
+ DEBUG(SSSDBG_OP_FAILURE, "sss_failover_transaction_send failed\n");
goto fail;
}
@@ -97,54 +83,6 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx,
return req;
}
-static errno_t
-sdap_dom_resolver_enum_retry(struct tevent_req *req,
- struct sdap_id_op *op,
- tevent_req_fn tcb)
-{
- struct sdap_dom_resolver_enum_state *state;
- struct tevent_req *subreq;
- errno_t ret;
-
- state = tevent_req_data(req, struct sdap_dom_resolver_enum_state);
- subreq = sdap_id_op_connect_send(op, state, &ret);
- if (subreq == NULL) {
- DEBUG(SSSDBG_OP_FAILURE,
- "sdap_id_op_connect_send failed: %d\n", ret);
- return ret;
- }
-
- tevent_req_set_callback(subreq, tcb, req);
- return EOK;
-}
-
-static bool sdap_dom_resolver_enum_connected(struct tevent_req *subreq)
-{
- errno_t ret;
- int dp_error;
- struct tevent_req *req = tevent_req_callback_data(subreq,
- struct tevent_req);
-
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
- talloc_zfree(subreq);
-
- if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC,
- "Backend is marked offline, retry later!\n");
- tevent_req_done(req);
- } else {
- DEBUG(SSSDBG_MINOR_FAILURE,
- "Domain enumeration failed to connect to " \
- "LDAP server: (%d)[%s]\n", ret, strerror(ret));
- tevent_req_error(req, ret);
- }
- return false;
- }
-
- return true;
-}
-
static void sdap_dom_resolver_enum_get_iphost(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(subreq,
@@ -153,13 +91,19 @@ static void sdap_dom_resolver_enum_get_iphost(struct tevent_req *subreq)
state = tevent_req_data(req, struct sdap_dom_resolver_enum_state);
- if (sdap_dom_resolver_enum_connected(subreq) == false) {
+ state->iphost_conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->iphost_conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = enum_iphosts_send(state, state->ev,
state->id_ctx,
- state->iphost_op,
+ state->iphost_conn,
state->purge);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
@@ -175,45 +119,14 @@ static void sdap_dom_resolver_enum_iphost_done(struct tevent_req *subreq)
struct tevent_req);
struct sdap_dom_resolver_enum_state *state;
errno_t ret;
- int dp_error;
state = tevent_req_data(req, struct sdap_dom_resolver_enum_state);
ret = enum_iphosts_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->iphost_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_dom_resolver_enum_retry(req, state->iphost_op,
- sdap_dom_resolver_enum_get_iphost);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
- tevent_req_done(req);
- return;
- } else if (ret != EOK && ret != ENOENT) {
- /* Non-recoverable error */
- DEBUG(SSSDBG_OP_FAILURE,
- "IP hosts enumeration failed: %d: %s\n", ret, sss_strerror(ret));
- tevent_req_error(req, ret);
- return;
- }
-
- state->ipnetwork_op = sdap_id_op_create(state, state->conn->conn_cache);
- if (state->ipnetwork_op == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "sdap_id_op_create failed for IP networks\n");
- tevent_req_error(req, EIO);
- return;
- }
-
- ret = sdap_dom_resolver_enum_retry(req, state->ipnetwork_op,
- sdap_dom_resolver_enum_get_ipnetwork);
+ ret = sss_failover_transaction_send(state, state->ev, state->id_ctx->fctx, req,
+ sdap_dom_resolver_enum_get_ipnetwork);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -230,13 +143,19 @@ static void sdap_dom_resolver_enum_get_ipnetwork(struct tevent_req *subreq)
state = tevent_req_data(req, struct sdap_dom_resolver_enum_state);
- if (sdap_dom_resolver_enum_connected(subreq) == false) {
+ state->ipnetwork_conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->ipnetwork_conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = enum_ipnetworks_send(state, state->ev,
state->id_ctx,
- state->ipnetwork_op,
+ state->ipnetwork_conn,
state->purge);
if (subreq == NULL) {
tevent_req_error(req, ENOMEM);
@@ -252,36 +171,12 @@ static void sdap_dom_resolver_enum_ipnetwork_done(struct tevent_req *subreq)
struct tevent_req);
struct sdap_dom_resolver_enum_state *state;
errno_t ret;
- int dp_error;
state = tevent_req_data(req, struct sdap_dom_resolver_enum_state);
ret = enum_ipnetworks_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->ipnetwork_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_dom_resolver_enum_retry(req, state->ipnetwork_op,
- sdap_dom_resolver_enum_get_ipnetwork);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- } else if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_TRACE_FUNC, "Backend is offline, retrying later\n");
- tevent_req_done(req);
- return;
- } else if (ret != EOK && ret != ENOENT) {
- /* Non-recoverable error */
- DEBUG(SSSDBG_OP_FAILURE,
- "IP networks enumeration failed: %d: %s\n",
- ret, sss_strerror(ret));
- tevent_req_error(req, ret);
- return;
- }
-
/* Ok, we've completed an enumeration. Save this to the
* sysdb so we can postpone starting up the enumeration
* process on the next SSSD service restart (to avoid
diff --git a/src/providers/ldap/sdap_async_resolver_enum.h b/src/providers/ldap/sdap_async_resolver_enum.h
index e096b7483fd..45496b1f9cc 100644
--- a/src/providers/ldap/sdap_async_resolver_enum.h
+++ b/src/providers/ldap/sdap_async_resolver_enum.h
@@ -28,8 +28,7 @@ sdap_dom_resolver_enum_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_resolver_ctx *resolver_ctx,
struct sdap_id_ctx *id_ctx,
- struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn);
+ struct sdap_domain *sdom);
errno_t sdap_dom_resolver_enum_recv(struct tevent_req *req);
diff --git a/src/providers/ldap/sdap_async_services.c b/src/providers/ldap/sdap_async_services.c
index 5fa3bcad565..687b59e93bc 100644
--- a/src/providers/ldap/sdap_async_services.c
+++ b/src/providers/ldap/sdap_async_services.c
@@ -511,7 +511,7 @@ sdap_get_services_recv(TALLOC_CTX *mem_ctx,
struct enum_services_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
- struct sdap_id_op *op;
+ struct sss_failover_ldap_connection *conn;
struct sss_domain_info *domain;
struct sysdb_ctx *sysdb;
@@ -526,7 +526,7 @@ struct tevent_req *
enum_services_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
- struct sdap_id_op *op,
+ struct sss_failover_ldap_connection *conn,
bool purge)
{
errno_t ret;
@@ -541,9 +541,9 @@ enum_services_send(TALLOC_CTX *memctx,
state->id_ctx = id_ctx;
state->domain = id_ctx->be->domain;
state->sysdb = id_ctx->be->domain->sysdb;
- state->op = op;
+ state->conn = conn;
- if (id_ctx->srv_opts && id_ctx->srv_opts->max_service_value && !purge) {
+ if (state->conn->srv_opts && state->conn->srv_opts->max_service_value && !purge) {
state->filter = talloc_asprintf(
state,
"(&(objectclass=%s)(%s=*)(%s=*)(%s=*)(%s>=%s)(!(%s=%s)))",
@@ -552,9 +552,9 @@ enum_services_send(TALLOC_CTX *memctx,
id_ctx->opts->service_map[SDAP_AT_SERVICE_PORT].name,
id_ctx->opts->service_map[SDAP_AT_SERVICE_PROTOCOL].name,
id_ctx->opts->service_map[SDAP_AT_SERVICE_USN].name,
- id_ctx->srv_opts->max_service_value,
+ state->conn->srv_opts->max_service_value,
id_ctx->opts->service_map[SDAP_AT_SERVICE_USN].name,
- id_ctx->srv_opts->max_service_value);
+ state->conn->srv_opts->max_service_value);
} else {
state->filter = talloc_asprintf(
state,
@@ -579,7 +579,7 @@ enum_services_send(TALLOC_CTX *memctx,
state->domain, state->sysdb,
state->id_ctx->opts,
state->id_ctx->opts->sdom->service_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -618,19 +618,19 @@ enum_services_op_done(struct tevent_req *subreq)
}
if (usn_value) {
- talloc_zfree(state->id_ctx->srv_opts->max_service_value);
- state->id_ctx->srv_opts->max_service_value =
+ talloc_zfree(state->conn->srv_opts->max_service_value);
+ state->conn->srv_opts->max_service_value =
talloc_steal(state->id_ctx, usn_value);
errno = 0;
usn_number = strtoul(usn_value, &endptr, 10);
if (!errno && endptr && (*endptr == '\0') && (endptr != usn_value)
- && (usn_number > state->id_ctx->srv_opts->last_usn)) {
- state->id_ctx->srv_opts->last_usn = usn_number;
+ && (usn_number > state->conn->srv_opts->last_usn)) {
+ state->conn->srv_opts->last_usn = usn_number;
}
}
DEBUG(SSSDBG_FUNC_DATA, "Services higher USN value: [%s]\n",
- state->id_ctx->srv_opts->max_service_value);
+ state->conn->srv_opts->max_service_value);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c
index 28b65b639fe..cd7a9ca9ed4 100644
--- a/src/providers/ldap/sdap_async_sudo.c
+++ b/src/providers/ldap/sdap_async_sudo.c
@@ -33,6 +33,9 @@
#include "providers/ldap/sdap_sudo.h"
#include "providers/ldap/sdap_sudo_shared.h"
#include "db/sysdb_sudo.h"
+#include "providers/failover/ldap/failover_ldap.h"
+#include "providers/failover/failover_transaction.h"
+#include "providers/failover/failover.h"
struct sdap_sudo_load_sudoers_state {
struct sysdb_attrs **rules;
@@ -281,7 +284,7 @@ struct sdap_sudo_refresh_state {
struct sdap_sudo_ctx *sudo_ctx;
struct tevent_context *ev;
struct sdap_options *opts;
- struct sdap_id_op *sdap_op;
+ struct sss_failover_ldap_connection *conn;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
@@ -289,11 +292,9 @@ struct sdap_sudo_refresh_state {
const char *delete_filter;
bool update_usn;
- int dp_error;
size_t num_rules;
};
-static errno_t sdap_sudo_refresh_retry(struct tevent_req *req);
static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq);
static void sdap_sudo_refresh_hostinfo_done(struct tevent_req *subreq);
static errno_t sdap_sudo_refresh_sudoers(struct tevent_req *req);
@@ -326,16 +327,8 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
state->opts = id_ctx->opts;
state->domain = id_ctx->be->domain;
state->sysdb = id_ctx->be->domain->sysdb;
- state->dp_error = DP_ERR_FATAL;
state->update_usn = update_usn;
- state->sdap_op = sdap_id_op_create(state, id_ctx->conn->conn_cache);
- if (!state->sdap_op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n");
- ret = ENOMEM;
- goto immediately;
- }
-
state->search_filter = talloc_strdup(state, search_filter);
if (state->search_filter == NULL) {
ret = ENOMEM;
@@ -348,11 +341,9 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
goto immediately;
}
- ret = sdap_sudo_refresh_retry(req);
- if (ret == EAGAIN) {
- /* asynchronous processing */
- return req;
- }
+ ret = sss_failover_transaction_send(state, state->ev, id_ctx->fctx, req,
+ sdap_sudo_refresh_connect_done);
+ return req;
immediately:
if (ret == EOK) {
@@ -365,44 +356,22 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
return req;
}
-static errno_t sdap_sudo_refresh_retry(struct tevent_req *req)
-{
- struct sdap_sudo_refresh_state *state;
- struct tevent_req *subreq;
- int ret;
-
- state = tevent_req_data(req, struct sdap_sudo_refresh_state);
-
- subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
- if (subreq == NULL) {
- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_id_op_connect_send() failed: "
- "%d(%s)\n", ret, strerror(ret));
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_sudo_refresh_connect_done, req);
-
- return EAGAIN;
-}
-
static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct sdap_sudo_refresh_state *state;
- int dp_error;
int ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_sudo_refresh_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "SUDO LDAP connection failed "
- "[%d]: %s\n", ret, strerror(ret));
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -413,7 +382,6 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq)
subreq = sdap_sudo_get_hostinfo_send(state, state->opts,
state->sudo_ctx->id_ctx->be);
if (subreq == NULL) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ENOMEM);
return;
}
@@ -425,7 +393,6 @@ static void sdap_sudo_refresh_connect_done(struct tevent_req *subreq)
ret = sdap_sudo_refresh_sudoers(req);
if (ret != EAGAIN) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
}
}
@@ -456,7 +423,6 @@ static void sdap_sudo_refresh_hostinfo_done(struct tevent_req *subreq)
ret = sdap_sudo_refresh_sudoers(req);
if (ret != EAGAIN) {
- state->dp_error = DP_ERR_FATAL;
tevent_req_error(req, ret);
}
}
@@ -480,7 +446,7 @@ static errno_t sdap_sudo_refresh_sudoers(struct tevent_req *req)
subreq = sdap_sudo_load_sudoers_send(state, state->ev,
state->opts,
- sdap_id_op_handle(state->sdap_op),
+ state->conn->sh,
filter);
if (subreq == NULL) {
talloc_free(filter);
@@ -584,7 +550,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
struct sysdb_attrs **rules = NULL;
size_t rules_count = 0;
char *usn = NULL;
- int dp_error;
int ret;
errno_t sret;
bool in_transaction = false;
@@ -595,19 +560,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
ret = sdap_sudo_load_sudoers_recv(subreq, state, &rules_count, &rules);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_sudo_refresh_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- }
- return;
- } else if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
DEBUG(SSSDBG_TRACE_FUNC, "Received %zu rules\n", rules_count);
/* Save users and groups fully qualified */
@@ -651,7 +603,7 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
/* remember new usn */
ret = sysdb_get_highest_usn(state, rules, rules_count, &usn);
if (ret == EOK) {
- sdap_sudo_set_usn(state->sudo_ctx->id_ctx->srv_opts, usn);
+ sdap_sudo_set_usn(state->conn->srv_opts, usn);
} else {
DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get highest USN [%d]: %s\n",
ret, sss_strerror(ret));
@@ -669,7 +621,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
}
}
- state->dp_error = dp_error;
if (ret == EOK) {
tevent_req_done(req);
} else {
@@ -679,7 +630,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq)
int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- int *dp_error,
size_t *num_rules)
{
struct sdap_sudo_refresh_state *state;
@@ -688,8 +638,6 @@ int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx,
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
if (num_rules != NULL) {
*num_rules = state->num_rules;
}
diff --git a/src/providers/ldap/sdap_autofs.c b/src/providers/ldap/sdap_autofs.c
index b9517905dff..f33457490d0 100644
--- a/src/providers/ldap/sdap_autofs.c
+++ b/src/providers/ldap/sdap_autofs.c
@@ -58,14 +58,10 @@ sdap_autofs_invalidate_maps(struct sdap_id_ctx *id_ctx,
struct sdap_autofs_enumerate_state {
struct tevent_context *ev;
struct sdap_id_ctx *ctx;
- struct sdap_id_op *op;
+ struct sss_failover_ldap_connection *conn;
const char *map_name;
-
- int dp_error;
};
-static errno_t
-sdap_autofs_enumerate_retry(struct tevent_req *req);
static void
sdap_autofs_enumerate_connect_done(struct tevent_req *subreq);
static void
@@ -86,17 +82,10 @@ sdap_autofs_enumerate_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->ctx = ctx;
- state->dp_error = DP_ERR_FATAL;
state->map_name = map_name;
- state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
-
- ret = sdap_autofs_enumerate_retry(req);
+ ret = sss_failover_transaction_send(state, ev, ctx->fctx, req,
+ sdap_autofs_enumerate_connect_done);
if (ret != EOK) {
goto fail;
}
@@ -109,23 +98,6 @@ sdap_autofs_enumerate_send(TALLOC_CTX *mem_ctx,
return req;
}
-static errno_t
-sdap_autofs_enumerate_retry(struct tevent_req *req)
-{
- struct sdap_autofs_enumerate_state *state =
- tevent_req_data(req, struct sdap_autofs_enumerate_state);
- struct tevent_req *subreq;
- int ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_autofs_enumerate_connect_done, req);
- return EOK;
-}
-
static void
sdap_autofs_enumerate_connect_done(struct tevent_req *subreq)
{
@@ -133,23 +105,21 @@ sdap_autofs_enumerate_connect_done(struct tevent_req *subreq)
struct tevent_req);
struct sdap_autofs_enumerate_state *state =
tevent_req_data(req, struct sdap_autofs_enumerate_state);
- int dp_error = DP_ERR_FATAL;
- int ret;
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = sdap_autofs_setautomntent_send(state, state->ev,
state->ctx->be->domain,
state->ctx->be->domain->sysdb,
- sdap_id_op_handle(state->op),
- state->op,
+ state->conn->sh,
state->ctx->opts,
state->map_name);
if (!subreq) {
@@ -169,29 +139,11 @@ sdap_autofs_enumerate_done(struct tevent_req *subreq)
struct tevent_req);
struct sdap_autofs_enumerate_state *state =
tevent_req_data(req, struct sdap_autofs_enumerate_state);
- int dp_error = DP_ERR_FATAL;
int ret;
ret = sdap_autofs_setautomntent_recv(subreq);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_autofs_enumerate_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
- return;
- }
-
- if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
-
if (ret == ENOENT) {
ret = sysdb_delete_autofsmap(state->ctx->be->domain, state->map_name);
if (ret != EOK && ret != ENOENT) {
@@ -203,20 +155,12 @@ sdap_autofs_enumerate_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
static errno_t
-sdap_autofs_enumerate_recv(struct tevent_req *req, int *dp_error_out)
+sdap_autofs_enumerate_recv(struct tevent_req *req)
{
- struct sdap_autofs_enumerate_state *state =
- tevent_req_data(req, struct sdap_autofs_enumerate_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -275,14 +219,12 @@ sdap_autofs_enumerate_handler_send(TALLOC_CTX *mem_ctx,
static void sdap_autofs_enumerate_handler_done(struct tevent_req *subreq)
{
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- ret = sdap_autofs_enumerate_recv(subreq, &dp_error);
+ ret = sdap_autofs_enumerate_recv(subreq);
talloc_zfree(subreq);
- ret = dp_error_to_ret(ret, dp_error);
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -354,14 +296,12 @@ sdap_autofs_get_map_handler_send(TALLOC_CTX *mem_ctx,
static void sdap_autofs_get_map_handler_done(struct tevent_req *subreq)
{
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- ret = sdap_autofs_get_map_recv(subreq, &dp_error);
+ ret = sdap_autofs_get_map_recv(subreq);
talloc_zfree(subreq);
- ret = dp_error_to_ret(ret, dp_error);
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -433,14 +373,12 @@ sdap_autofs_get_entry_handler_send(TALLOC_CTX *mem_ctx,
static void sdap_autofs_get_entry_handler_done(struct tevent_req *subreq)
{
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- ret = sdap_autofs_get_entry_recv(subreq, &dp_error);
+ ret = sdap_autofs_get_entry_recv(subreq);
talloc_zfree(subreq);
- ret = dp_error_to_ret(ret, dp_error);
if (ret != EOK) {
tevent_req_error(req, ret);
diff --git a/src/providers/ldap/sdap_autofs.h b/src/providers/ldap/sdap_autofs.h
index 4f30fbf1743..ec6bc139982 100644
--- a/src/providers/ldap/sdap_autofs.h
+++ b/src/providers/ldap/sdap_autofs.h
@@ -36,7 +36,6 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx,
struct sss_domain_info *dom,
struct sysdb_ctx *sysdb,
struct sdap_handle *sh,
- struct sdap_id_op *op,
struct sdap_options *opts,
const char *mapname);
@@ -47,15 +46,13 @@ struct tevent_req *sdap_autofs_get_map_send(TALLOC_CTX *mem_ctx,
struct sdap_id_ctx *id_ctx,
const char *mapname);
-errno_t sdap_autofs_get_map_recv(struct tevent_req *req,
- int *dp_error);
+errno_t sdap_autofs_get_map_recv(struct tevent_req *req);
struct tevent_req *sdap_autofs_get_entry_send(TALLOC_CTX *mem_ctx,
struct sdap_id_ctx *id_ctx,
const char *mapname,
const char *entryname);
-errno_t sdap_autofs_get_entry_recv(struct tevent_req *req,
- int *dp_error);
+errno_t sdap_autofs_get_entry_recv(struct tevent_req *req);
#endif /* _SDAP_AUTOFS_H_ */
diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c
index 9a0172bc6df..4a79c8930fa 100644
--- a/src/providers/ldap/sdap_dyndns.c
+++ b/src/providers/ldap/sdap_dyndns.c
@@ -522,6 +522,7 @@ sdap_dyndns_update_recv(struct tevent_req *req)
/* A request to get addresses to update with */
struct sdap_dyndns_get_addrs_state {
struct sdap_id_op* sdap_op;
+ struct sss_failover_ldap_connection *conn;
struct sss_iface_addr *addresses;
const char *network_filter;
};
@@ -579,7 +580,6 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
{
errno_t ret;
struct tevent_req *req;
- struct tevent_req *subreq;
struct sdap_dyndns_get_addrs_state *state;
req = tevent_req_create(mem_ctx, &state,
@@ -600,22 +600,10 @@ sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
}
/* Detect DYNDNS address from LDAP connection */
- state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache);
- if (!state->sdap_op) {
- ret = ENOMEM;
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- goto done;
- }
state->network_filter = network_filter;
- subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
- if (!subreq) {
- ret = EIO;
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n",
- ret, sss_strerror(ret));
- goto done;
- }
- tevent_req_set_callback(subreq, sdap_dyndns_get_addrs_done, req);
+ ret = sss_failover_transaction_send(state, ev, sdap_ctx->fctx, req,
+ sdap_dyndns_get_addrs_done);
ret = EAGAIN;
done:
@@ -635,30 +623,23 @@ static void
sdap_dyndns_get_addrs_done(struct tevent_req *subreq)
{
errno_t ret;
- int dp_error;
struct tevent_req *req;
struct sdap_dyndns_get_addrs_state *state;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_dyndns_get_addrs_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- if (dp_error == DP_ERR_OFFLINE) {
- DEBUG(SSSDBG_MINOR_FAILURE, "No LDAP server is available, "
- "dynamic DNS update is skipped in offline mode.\n");
- ret = ERR_DYNDNS_OFFLINE;
- } else {
- DEBUG(SSSDBG_OP_FAILURE,
- "Failed to connect to LDAP server: [%d](%s)\n",
- ret, sss_strerror(ret));
- }
- tevent_req_error(req, ret);
+
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
- ret = sdap_dyndns_add_ldap_conn(state, sdap_id_op_handle(state->sdap_op));
+ ret = sdap_dyndns_add_ldap_conn(state, state->conn->sh);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses from LDAP connection\n");
tevent_req_error(req, ret);
diff --git a/src/providers/ldap/sdap_hostid.c b/src/providers/ldap/sdap_hostid.c
index ae8caaddb89..2a1f70a69a8 100644
--- a/src/providers/ldap/sdap_hostid.c
+++ b/src/providers/ldap/sdap_hostid.c
@@ -28,18 +28,15 @@
struct hosts_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
- struct sdap_id_op *op;
+ struct sss_failover_ldap_connection *conn;
struct sss_domain_info *domain;
const char *name;
const char *alias;
size_t count;
struct sysdb_attrs **hosts;
- int dp_error;
};
-static errno_t
-hosts_get_retry(struct tevent_req *req);
static void
hosts_get_connect_done(struct tevent_req *subreq);
static void
@@ -61,20 +58,13 @@ hosts_get_send(TALLOC_CTX *memctx,
state->ev = ev;
state->id_ctx = id_ctx;
- state->dp_error = DP_ERR_FATAL;
-
- state->op = sdap_id_op_create(state, id_ctx->conn->conn_cache);
- if (!state->op) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
state->domain = id_ctx->be->domain;
state->name = name;
state->alias = alias;
- ret = hosts_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req,
+ hosts_get_connect_done);
if (ret != EOK) {
goto fail;
}
@@ -87,23 +77,6 @@ hosts_get_send(TALLOC_CTX *memctx,
return req;
}
-static errno_t
-hosts_get_retry(struct tevent_req *req)
-{
- struct hosts_get_state *state = tevent_req_data(req,
- struct hosts_get_state);
- struct tevent_req *subreq;
- errno_t ret = EOK;
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (!subreq) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, hosts_get_connect_done, req);
- return EOK;
-}
-
static void
hosts_get_connect_done(struct tevent_req *subreq)
{
@@ -111,20 +84,18 @@ hosts_get_connect_done(struct tevent_req *subreq)
struct tevent_req);
struct hosts_get_state *state = tevent_req_data(req,
struct hosts_get_state);
- int dp_error = DP_ERR_FATAL;
- errno_t ret;
-
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
subreq = sdap_host_info_send(state, state->ev,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->id_ctx->opts, state->name,
state->id_ctx->opts->host_map,
state->id_ctx->opts->sdom->host_search_bases);
@@ -142,7 +113,6 @@ hosts_get_done(struct tevent_req *subreq)
struct tevent_req);
struct hosts_get_state *state = tevent_req_data(req,
struct hosts_get_state);
- int dp_error = DP_ERR_FATAL;
errno_t ret;
struct sysdb_attrs *attrs;
time_t now = time(NULL);
@@ -151,20 +121,6 @@ hosts_get_done(struct tevent_req *subreq)
&state->count, &state->hosts);
talloc_zfree(subreq);
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = hosts_get_retry(req);
- if (ret != EOK) {
- goto done;
- }
- return;
- }
-
- if (ret != EOK && ret != ENOENT) {
- goto done;
- }
-
if (state->count == 0) {
DEBUG(SSSDBG_FUNC_DATA,
"No host with name [%s] found.\n", state->name);
@@ -203,10 +159,7 @@ hosts_get_done(struct tevent_req *subreq)
goto done;
}
- dp_error = DP_ERR_OK;
-
done:
- state->dp_error = dp_error;
if (ret == EOK) {
tevent_req_done(req);
} else {
@@ -215,16 +168,8 @@ hosts_get_done(struct tevent_req *subreq)
}
static errno_t
-hosts_get_recv(struct tevent_req *req,
- int *dp_error_out)
+hosts_get_recv(struct tevent_req *req)
{
- struct hosts_get_state *state = tevent_req_data(req,
- struct hosts_get_state);
-
- if (dp_error_out) {
- *dp_error_out = state->dp_error;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -266,7 +211,7 @@ sdap_hostid_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -279,17 +224,16 @@ static void sdap_hostid_handler_done(struct tevent_req *subreq)
{
struct sdap_hostid_handler_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_hostid_handler_state);
- ret = hosts_get_recv(subreq, &dp_error);
+ ret = hosts_get_recv(subreq);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c
index f9fe516708c..ea2b548d053 100644
--- a/src/providers/ldap/sdap_id_op.c
+++ b/src/providers/ldap/sdap_id_op.c
@@ -108,7 +108,7 @@ static void sdap_id_op_hook_conn_data(struct sdap_id_op *op, struct sdap_id_conn
static int sdap_id_op_destroy(void *pvt);
static bool sdap_id_op_can_reconnect(struct sdap_id_op *op);
-static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret);
+static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int ret);
static int sdap_id_op_connect_state_destroy(void *pvt);
static int sdap_id_op_connect_step(struct tevent_req *req);
static void sdap_id_op_connect_done(struct tevent_req *subreq);
@@ -518,7 +518,6 @@ struct sdap_id_op_connect_state {
struct sdap_id_conn_ctx *id_conn;
struct tevent_context *ev;
struct sdap_id_op *op;
- int dp_error;
int result;
};
@@ -848,7 +847,7 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq)
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);
+ sdap_id_op_connect_req_complete(op, retry_ret);
}
continue;
@@ -858,14 +857,14 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq)
if (ret == EOK) {
DEBUG(SSSDBG_TRACE_ALL,
"notify connected to op #%d\n", notify_count);
- sdap_id_op_connect_req_complete(op, DP_ERR_OK, ret);
+ sdap_id_op_connect_req_complete(op, ret);
} else if (is_offline) {
DEBUG(SSSDBG_TRACE_ALL, "notify offline to op #%d\n", notify_count);
- sdap_id_op_connect_req_complete(op, DP_ERR_OFFLINE, EAGAIN);
+ sdap_id_op_connect_req_complete(op, EAGAIN);
} else {
DEBUG(SSSDBG_TRACE_ALL,
"notify error to op #%d: %d [%s]\n", notify_count, ret, strerror(ret));
- sdap_id_op_connect_req_complete(op, DP_ERR_FATAL, ret);
+ sdap_id_op_connect_req_complete(op, ret);
}
}
@@ -927,7 +926,7 @@ static void sdap_id_op_connect_reinit_done(struct tevent_req *req)
}
/* Mark operation connection request as complete */
-static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error, int ret)
+static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int ret)
{
struct tevent_req *req = op->connect_req;
struct sdap_id_op_connect_state *state;
@@ -940,7 +939,6 @@ static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error,
op->connect_req = NULL;
state = tevent_req_data(req, struct sdap_id_op_connect_state);
- state->dp_error = dp_error;
state->result = ret;
/* Set the chain id to the one associated with this request. */
@@ -956,29 +954,28 @@ static void sdap_id_op_connect_req_complete(struct sdap_id_op *op, int dp_error,
/* 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
+ * In data provider error code is returned:
+ * ERR_OK - connection established
+ * ERR_OFFLINE - backend is offline, operation result is set EAGAIN
+ * ERR_FATAL - operation failed
*/
-int sdap_id_op_connect_recv(struct tevent_req *req, int *dp_error)
+int sdap_id_op_connect_recv(struct tevent_req *req)
{
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)
+ * In data provider error code is returned:
+ * ERR_OK (operation result = EOK) - operation completed
+ * ERR_OK (operation result != EOK) - operation can be retried
+ * ERR_OFFLINE - backend is offline, operation result is set EAGAIN
+ * ERR_FATAL - operation failed */
+int sdap_id_op_done(struct sdap_id_op *op, int retval)
{
bool communication_error;
struct sdap_id_conn_data *current_conn = op->conn_data;
@@ -1005,36 +1002,29 @@ int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out)
op->conn_cache->id_conn->service->name);
}
- int dp_err;
if (retval == EOK) {
- dp_err = DP_ERR_OK;
+ /* operation completed successfully */
+ op->reconnect_retry_count = 0;
} 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;
+ op->reconnect_retry_count = 0;
DEBUG(SSSDBG_TRACE_ALL, "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(SSSDBG_TRACE_ALL,
"too many communication failures, giving up...\n");
+ op->reconnect_retry_count = 0;
} else {
- dp_err = DP_ERR_OK;
retval = EAGAIN;
+ op->reconnect_retry_count++;
+ DEBUG(SSSDBG_TRACE_ALL,
+ "advising for connection retry #%i\n", op->reconnect_retry_count);
}
} else {
- dp_err = DP_ERR_FATAL;
- }
-
- if (dp_err == DP_ERR_OK && retval != EOK) {
- /* reconnect retry */
- op->reconnect_retry_count++;
- DEBUG(SSSDBG_TRACE_ALL,
- "advising for connection retry #%i\n", op->reconnect_retry_count);
- } else {
- /* end of request */
+ /* fatal error, cannot retry */
op->reconnect_retry_count = 0;
}
@@ -1043,7 +1033,6 @@ int sdap_id_op_done(struct sdap_id_op *op, int retval, int *dp_err_out)
sdap_id_op_hook_conn_data(op, NULL);
}
- *dp_err_out = dp_err;
return retval;
}
diff --git a/src/providers/ldap/sdap_id_op.h b/src/providers/ldap/sdap_id_op.h
index f7f230a734a..1e0f9d8ce97 100644
--- a/src/providers/ldap/sdap_id_op.h
+++ b/src/providers/ldap/sdap_id_op.h
@@ -52,21 +52,21 @@ struct tevent_req *sdap_id_op_connect_send(struct sdap_id_op *op,
/* 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
+ * ERR_OK - connection established
+ * ERR_OFFLINE - backend is offline, operation result is set EAGAIN
+ * ERR_FATAL - operation failed
*/
-int sdap_id_op_connect_recv(struct tevent_req *req, int *dp_error);
+int sdap_id_op_connect_recv(struct tevent_req *req);
/* 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*, int ret, int *dp_error);
+ * ERR_OK (operation result = EOK) - operation completed
+ * ERR_OK (operation result != EOK) - operation can be retried
+ * ERR_OFFLINE - backend is offline, operation result is set EAGAIN
+ * ERR_FATAL - operation failed */
+int sdap_id_op_done(struct sdap_id_op*, int ret);
/* Get SDAP handle associated with operation by sdap_id_op_connect */
struct sdap_handle *sdap_id_op_handle(struct sdap_id_op *op);
diff --git a/src/providers/ldap/sdap_iphost.c b/src/providers/ldap/sdap_iphost.c
index 79c707b6d71..049a0ce7b49 100644
--- a/src/providers/ldap/sdap_iphost.c
+++ b/src/providers/ldap/sdap_iphost.c
@@ -28,10 +28,9 @@ struct sdap_ip_host_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
struct sdap_domain *sdom;
- struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
uint32_t filter_type;
const char *filter_value;
@@ -39,20 +38,17 @@ struct sdap_ip_host_get_state {
char *filter;
const char **attrs;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
};
-static errno_t
-sdap_ip_host_get_retry(struct tevent_req *req);
+static void
+sdap_ip_host_get_connect_done(struct tevent_req *subreq);
static struct tevent_req *
sdap_iphost_get_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
uint32_t filter_type,
const char *filter_value,
bool noexist_delete)
@@ -71,21 +67,12 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->id_ctx = id_ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
state->filter_value = filter_value;
state->filter_type = filter_type;
state->noexist_delete = noexist_delete;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (state->op == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
-
switch(filter_type) {
case BE_FILTER_NAME:
attr_name = id_ctx->opts->iphost_map[SDAP_AT_IPHOST_NAME].name;
@@ -118,8 +105,8 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx,
if (ret != EOK) {
goto fail;
}
-
- ret = sdap_ip_host_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req,
+ sdap_ip_host_get_connect_done);
if (ret != EOK) {
goto fail;
}
@@ -132,27 +119,6 @@ sdap_iphost_get_send(TALLOC_CTX *mem_ctx,
return req;
}
-static void
-sdap_ip_host_get_connect_done(struct tevent_req *subreq);
-
-static errno_t
-sdap_ip_host_get_retry(struct tevent_req *req)
-{
- struct sdap_ip_host_get_state *state;
- struct tevent_req *subreq;
- errno_t ret = EOK;
-
- state = tevent_req_data(req, struct sdap_ip_host_get_state);
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (subreq == NULL) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_ip_host_get_connect_done, req);
-
- return EOK;
-}
static void
sdap_ip_host_get_done(struct tevent_req *subreq);
@@ -162,18 +128,17 @@ sdap_ip_host_get_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct sdap_ip_host_get_state *state;
- int dp_error = DP_ERR_FATAL;
- errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ip_host_get_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -181,7 +146,7 @@ sdap_ip_host_get_connect_done(struct tevent_req *subreq)
state->domain, state->sysdb,
state->id_ctx->opts,
state->sdom->iphost_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -200,7 +165,6 @@ sdap_ip_host_get_done(struct tevent_req *subreq)
errno_t ret;
struct tevent_req *req;
struct sdap_ip_host_get_state *state;
- int dp_error = DP_ERR_FATAL;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ip_host_get_state);
@@ -208,29 +172,6 @@ sdap_ip_host_get_done(struct tevent_req *subreq)
ret = sdap_get_iphost_recv(NULL, subreq, NULL);
talloc_zfree(subreq);
- /* Check whether we need to try again with another
- * failover server. */
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_ip_host_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- /* Return to the mainloop to retry */
- return;
- }
- state->sdap_ret = ret;
-
- /* An error occurred. */
- if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
-
if (ret == ENOENT && state->noexist_delete == true) {
/* Ensure that this entry is removed from the sysdb */
switch (state->filter_type) {
@@ -258,27 +199,12 @@ sdap_ip_host_get_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
static errno_t
-sdap_ip_host_get_recv(struct tevent_req *req,
- int *dp_error_out,
- int *sdap_ret)
+sdap_ip_host_get_recv(struct tevent_req *req)
{
- struct sdap_ip_host_get_state *state;
-
- state = tevent_req_data(req, struct sdap_ip_host_get_state);
-
- if (dp_error_out != NULL) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret != NULL) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -317,7 +243,6 @@ sdap_iphost_handler_send(TALLOC_CTX *mem_ctx,
subreq = sdap_iphost_get_send(state, params->ev,
resolver_ctx->id_ctx,
resolver_ctx->id_ctx->opts->sdom,
- resolver_ctx->id_ctx->conn,
resolver_data->filter_type,
resolver_data->filter_value,
true);
@@ -331,7 +256,7 @@ sdap_iphost_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -344,17 +269,16 @@ static void sdap_ip_host_handler_done(struct tevent_req *subreq)
{
struct sdap_ip_host_handler_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ip_host_handler_state);
- ret = sdap_ip_host_get_recv(subreq, &dp_error, NULL);
+ ret = sdap_ip_host_get_recv(subreq);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_ipnetwork.c b/src/providers/ldap/sdap_ipnetwork.c
index b78f50b787d..c4a034ea5d4 100644
--- a/src/providers/ldap/sdap_ipnetwork.c
+++ b/src/providers/ldap/sdap_ipnetwork.c
@@ -28,10 +28,9 @@ struct sdap_ipnetwork_get_state {
struct tevent_context *ev;
struct sdap_id_ctx *id_ctx;
struct sdap_domain *sdom;
- struct sdap_id_op *op;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
- struct sdap_id_conn_ctx *conn;
+ struct sss_failover_ldap_connection *conn;
uint32_t filter_type;
const char *filter_value;
@@ -39,20 +38,17 @@ struct sdap_ipnetwork_get_state {
char *filter;
const char **attrs;
- int dp_error;
- int sdap_ret;
bool noexist_delete;
};
-static errno_t
-sdap_ipnetwork_get_retry(struct tevent_req *req);
+static void
+sdap_ipnetwork_get_connect_done(struct tevent_req *subreq);
static struct tevent_req *
sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sdap_id_ctx *id_ctx,
struct sdap_domain *sdom,
- struct sdap_id_conn_ctx *conn,
uint32_t filter_type,
const char *filter_value,
bool noexist_delete)
@@ -71,21 +67,12 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->id_ctx = id_ctx;
state->sdom = sdom;
- state->conn = conn;
- state->dp_error = DP_ERR_FATAL;
state->domain = sdom->dom;
state->sysdb = sdom->dom->sysdb;
state->filter_value = filter_value;
state->filter_type = filter_type;
state->noexist_delete = noexist_delete;
- state->op = sdap_id_op_create(state, state->conn->conn_cache);
- if (state->op == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
- ret = ENOMEM;
- goto fail;
- }
-
switch(filter_type) {
case BE_FILTER_NAME:
attr_name = id_ctx->opts->ipnetwork_map[SDAP_AT_IPNETWORK_NAME].name;
@@ -118,8 +105,8 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx,
if (ret != EOK) {
goto fail;
}
-
- ret = sdap_ipnetwork_get_retry(req);
+ ret = sss_failover_transaction_send(state, ev, id_ctx->fctx, req,
+ sdap_ipnetwork_get_connect_done);
if (ret != EOK) {
goto fail;
}
@@ -132,28 +119,6 @@ sdap_ipnetwork_get_send(TALLOC_CTX *mem_ctx,
return req;
}
-static void
-sdap_ipnetwork_get_connect_done(struct tevent_req *subreq);
-
-static errno_t
-sdap_ipnetwork_get_retry(struct tevent_req *req)
-{
- struct sdap_ipnetwork_get_state *state;
- struct tevent_req *subreq;
- errno_t ret = EOK;
-
- state = tevent_req_data(req, struct sdap_ipnetwork_get_state);
-
- subreq = sdap_id_op_connect_send(state->op, state, &ret);
- if (subreq == NULL) {
- return ret;
- }
-
- tevent_req_set_callback(subreq, sdap_ipnetwork_get_connect_done, req);
-
- return EOK;
-}
-
static void
sdap_ipnetwork_get_done(struct tevent_req *subreq);
@@ -162,18 +127,17 @@ sdap_ipnetwork_get_connect_done(struct tevent_req *subreq)
{
struct tevent_req *req;
struct sdap_ipnetwork_get_state *state;
- int dp_error = DP_ERR_FATAL;
- errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ipnetwork_get_state);
- ret = sdap_id_op_connect_recv(subreq, &dp_error);
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
talloc_zfree(subreq);
- if (ret != EOK) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
return;
}
@@ -181,7 +145,7 @@ sdap_ipnetwork_get_connect_done(struct tevent_req *subreq)
state->domain, state->sysdb,
state->id_ctx->opts,
state->sdom->ipnetwork_search_bases,
- sdap_id_op_handle(state->op),
+ state->conn->sh,
state->attrs, state->filter,
dp_opt_get_int(state->id_ctx->opts->basic,
SDAP_SEARCH_TIMEOUT),
@@ -200,7 +164,6 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq)
errno_t ret;
struct tevent_req *req;
struct sdap_ipnetwork_get_state *state;
- int dp_error = DP_ERR_FATAL;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ipnetwork_get_state);
@@ -208,29 +171,6 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq)
ret = sdap_get_ipnetwork_recv(NULL, subreq, NULL);
talloc_zfree(subreq);
- /* Check whether we need to try again with another
- * failover server. */
- ret = sdap_id_op_done(state->op, ret, &dp_error);
- if (dp_error == DP_ERR_OK && ret != EOK) {
- /* retry */
- ret = sdap_ipnetwork_get_retry(req);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
- /* Return to the mainloop to retry */
- return;
- }
- state->sdap_ret = ret;
-
- /* An error occurred. */
- if (ret && ret != ENOENT) {
- state->dp_error = dp_error;
- tevent_req_error(req, ret);
- return;
- }
-
if (ret == ENOENT && state->noexist_delete == true) {
/* Ensure that this entry is removed from the sysdb */
switch (state->filter_type) {
@@ -259,27 +199,12 @@ sdap_ipnetwork_get_done(struct tevent_req *subreq)
}
}
- state->dp_error = DP_ERR_OK;
tevent_req_done(req);
}
static errno_t
-sdap_ipnetwork_get_recv(struct tevent_req *req,
- int *dp_error_out,
- int *sdap_ret)
+sdap_ipnetwork_get_recv(struct tevent_req *req)
{
- struct sdap_ipnetwork_get_state *state;
-
- state = tevent_req_data(req, struct sdap_ipnetwork_get_state);
-
- if (dp_error_out != NULL) {
- *dp_error_out = state->dp_error;
- }
-
- if (sdap_ret != NULL) {
- *sdap_ret = state->sdap_ret;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
@@ -319,7 +244,6 @@ sdap_ipnetwork_handler_send(TALLOC_CTX *mem_ctx,
subreq = sdap_ipnetwork_get_send(state, params->ev,
resolver_ctx->id_ctx,
resolver_ctx->id_ctx->opts->sdom,
- resolver_ctx->id_ctx->conn,
resolver_data->filter_type,
resolver_data->filter_value,
true);
@@ -333,7 +257,7 @@ sdap_ipnetwork_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -347,17 +271,16 @@ sdap_ipnetwork_handler_done(struct tevent_req *subreq)
{
struct sdap_ipnetwork_handler_state *state;
struct tevent_req *req;
- int dp_error;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_ipnetwork_handler_state);
- ret = sdap_ipnetwork_get_recv(subreq, &dp_error, NULL);
+ ret = sdap_ipnetwork_get_recv(subreq);
talloc_zfree(subreq);
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_online_check.c b/src/providers/ldap/sdap_online_check.c
index cd26841c2f3..f70e6a2423f 100644
--- a/src/providers/ldap/sdap_online_check.c
+++ b/src/providers/ldap/sdap_online_check.c
@@ -207,7 +207,7 @@ sdap_online_check_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -242,7 +242,7 @@ static void sdap_online_check_handler_done(struct tevent_req *subreq)
}
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
@@ -271,7 +271,7 @@ static void sdap_online_check_subdomains_done(struct tevent_req *subreq)
/* We return the EOK of the initial online check here, the result of the
* subdomains request is not important for the online-check request. */
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, EOK, NULL);
+ dp_reply_std_set(&state->reply, EOK, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_refresh.c b/src/providers/ldap/sdap_refresh.c
index 402db53a986..562c8352459 100644
--- a/src/providers/ldap/sdap_refresh.c
+++ b/src/providers/ldap/sdap_refresh.c
@@ -150,20 +150,17 @@ static void sdap_refresh_done(struct tevent_req *subreq)
struct sdap_refresh_state *state = NULL;
struct tevent_req *req = NULL;
const char *err_msg = NULL;
- errno_t dp_error;
- int sdap_ret;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_refresh_state);
- ret = sdap_handle_acct_req_recv(subreq, &dp_error, &err_msg, &sdap_ret);
+ ret = sdap_handle_acct_req_recv(subreq, &err_msg);
talloc_zfree(subreq);
if (ret != EOK) {
- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [dp_error: %d, "
- "sdap_ret: %d, errno: %d]: %s\n",
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh %s [errno: %d]: %s\n",
be_req2str(state->account_req->entry_type),
- dp_error, sdap_ret, ret, err_msg);
+ ret, err_msg);
goto done;
}
diff --git a/src/providers/ldap/sdap_reinit.c b/src/providers/ldap/sdap_reinit.c
index 1764ecd6ba5..10946965e45 100644
--- a/src/providers/ldap/sdap_reinit.c
+++ b/src/providers/ldap/sdap_reinit.c
@@ -80,7 +80,7 @@ struct tevent_req* sdap_reinit_cleanup_send(TALLOC_CTX *mem_ctx,
}
subreq = sdap_dom_enum_send(id_ctx, be_ctx->ev, id_ctx,
- id_ctx->opts->sdom, id_ctx->conn);
+ id_ctx->opts->sdom);
if (subreq == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to issue enumeration request\n");
ret = ENOMEM;
diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c
index 8cea919b940..a80347ce9bd 100644
--- a/src/providers/ldap/sdap_sudo.c
+++ b/src/providers/ldap/sdap_sudo.c
@@ -83,7 +83,7 @@ sdap_sudo_handler_send(TALLOC_CTX *mem_ctx,
return req;
immediately:
- dp_reply_std_set(&state->reply, DP_ERR_DECIDE, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
/* TODO For backward compatibility we always return EOK to DP now. */
tevent_req_done(req);
@@ -96,7 +96,6 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq)
{
struct sdap_sudo_handler_state *state;
struct tevent_req *req;
- int dp_error;
bool deleted;
errno_t ret;
@@ -105,17 +104,17 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq)
switch (state->type) {
case BE_REQ_SUDO_FULL:
- ret = sdap_sudo_full_refresh_recv(subreq, &dp_error);
+ ret = sdap_sudo_full_refresh_recv(subreq);
talloc_zfree(subreq);
/* Reschedule the periodic task since the refresh was just finished
* per user request. */
- if (ret == EOK && dp_error == DP_ERR_OK) {
+ if (ret == EOK) {
be_ptask_postpone(state->sudo_ctx->full_refresh);
}
break;
case BE_REQ_SUDO_RULES:
- ret = sdap_sudo_rules_refresh_recv(subreq, &dp_error, &deleted);
+ ret = sdap_sudo_rules_refresh_recv(subreq, &deleted);
talloc_zfree(subreq);
if (ret == EOK && deleted == true) {
ret = ENOENT;
@@ -123,13 +122,12 @@ static void sdap_sudo_handler_done(struct tevent_req *subreq)
break;
default:
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request type: %d\n", state->type);
- dp_error = DP_ERR_FATAL;
ret = ERR_INTERNAL;
break;
}
/* TODO For backward compatibility we always return EOK to DP now. */
- dp_reply_std_set(&state->reply, dp_error, ret, NULL);
+ dp_reply_std_set(&state->reply, ret, NULL);
tevent_req_done(req);
}
diff --git a/src/providers/ldap/sdap_sudo.h b/src/providers/ldap/sdap_sudo.h
index 85eeccf268a..df3f175cc78 100644
--- a/src/providers/ldap/sdap_sudo.h
+++ b/src/providers/ldap/sdap_sudo.h
@@ -57,27 +57,23 @@ struct tevent_req *sdap_sudo_refresh_send(TALLOC_CTX *mem_ctx,
int sdap_sudo_refresh_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- int *dp_error,
size_t *num_rules);
struct tevent_req *sdap_sudo_full_refresh_send(TALLOC_CTX *mem_ctx,
struct sdap_sudo_ctx *sudo_ctx);
-int sdap_sudo_full_refresh_recv(struct tevent_req *req,
- int *dp_error);
+int sdap_sudo_full_refresh_recv(struct tevent_req *req);
struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
struct sdap_sudo_ctx *sudo_ctx);
-int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
- int *dp_error);
+int sdap_sudo_smart_refresh_recv(struct tevent_req *req);
struct tevent_req *sdap_sudo_rules_refresh_send(TALLOC_CTX *mem_ctx,
struct sdap_sudo_ctx *sudo_ctx,
const char **rules);
int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
- int *dp_error,
bool *deleted);
errno_t
diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
index a484c6ae2c2..03b4f2b4242 100644
--- a/src/providers/ldap/sdap_sudo_refresh.c
+++ b/src/providers/ldap/sdap_sudo_refresh.c
@@ -33,7 +33,6 @@ struct sdap_sudo_full_refresh_state {
struct sdap_id_ctx *id_ctx;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
- int dp_error;
};
static void sdap_sudo_full_refresh_done(struct tevent_req *subreq);
@@ -106,9 +105,9 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
- ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL);
+ ret = sdap_sudo_refresh_recv(state, subreq, NULL);
talloc_zfree(subreq);
- if (ret != EOK || state->dp_error != DP_ERR_OK) {
+ if (ret != EOK) {
goto done;
}
@@ -136,23 +135,16 @@ static void sdap_sudo_full_refresh_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int sdap_sudo_full_refresh_recv(struct tevent_req *req,
- int *dp_error)
+int sdap_sudo_full_refresh_recv(struct tevent_req *req)
{
- struct sdap_sudo_full_refresh_state *state = NULL;
- state = tevent_req_data(req, struct sdap_sudo_full_refresh_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
return EOK;
}
struct sdap_sudo_smart_refresh_state {
struct sdap_id_ctx *id_ctx;
struct sysdb_ctx *sysdb;
- int dp_error;
};
static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq);
@@ -179,7 +171,6 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
if (be_ptask_running(sudo_ctx->full_refresh)) {
DEBUG(SSSDBG_TRACE_FUNC, "Skipping smart refresh because "
"there is ongoing full refresh.\n");
- state->dp_error = DP_ERR_OK;
ret = EOK;
goto immediately;
}
@@ -245,9 +236,9 @@ static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
- ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error, NULL);
+ ret = sdap_sudo_refresh_recv(state, subreq, NULL);
talloc_zfree(subreq);
- if (ret != EOK || state->dp_error != DP_ERR_OK) {
+ if (ret != EOK) {
goto done;
}
@@ -262,23 +253,16 @@ static void sdap_sudo_smart_refresh_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int sdap_sudo_smart_refresh_recv(struct tevent_req *req,
- int *dp_error)
+int sdap_sudo_smart_refresh_recv(struct tevent_req *req)
{
- struct sdap_sudo_smart_refresh_state *state = NULL;
- state = tevent_req_data(req, struct sdap_sudo_smart_refresh_state);
-
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
-
return EOK;
}
struct sdap_sudo_rules_refresh_state {
struct sdap_id_ctx *id_ctx;
size_t num_rules;
- int dp_error;
bool deleted;
};
@@ -396,10 +380,9 @@ static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sdap_sudo_rules_refresh_state);
- ret = sdap_sudo_refresh_recv(state, subreq, &state->dp_error,
- &downloaded_rules_num);
+ ret = sdap_sudo_refresh_recv(state, subreq, &downloaded_rules_num);
talloc_zfree(subreq);
- if (ret != EOK || state->dp_error != DP_ERR_OK) {
+ if (ret != EOK) {
goto done;
}
@@ -415,7 +398,6 @@ static void sdap_sudo_rules_refresh_done(struct tevent_req *subreq)
}
int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
- int *dp_error,
bool *deleted)
{
struct sdap_sudo_rules_refresh_state *state = NULL;
@@ -423,7 +405,6 @@ int sdap_sudo_rules_refresh_recv(struct tevent_req *req,
TEVENT_REQ_RETURN_ON_ERROR(req);
- *dp_error = state->dp_error;
*deleted = state->deleted;
return EOK;
@@ -445,9 +426,7 @@ sdap_sudo_ptask_full_refresh_send(TALLOC_CTX *mem_ctx,
static errno_t
sdap_sudo_ptask_full_refresh_recv(struct tevent_req *req)
{
- int dp_error;
-
- return sdap_sudo_full_refresh_recv(req, &dp_error);
+ return sdap_sudo_full_refresh_recv(req);
}
static struct tevent_req *
@@ -466,9 +445,7 @@ sdap_sudo_ptask_smart_refresh_send(TALLOC_CTX *mem_ctx,
static errno_t
sdap_sudo_ptask_smart_refresh_recv(struct tevent_req *req)
{
- int dp_error;
-
- return sdap_sudo_smart_refresh_recv(req, &dp_error);
+ return sdap_sudo_smart_refresh_recv(req);
}
errno_t
diff --git a/src/providers/minimal/minimal.h b/src/providers/minimal/minimal.h
new file mode 100644
index 00000000000..0f9a15adf7c
--- /dev/null
+++ b/src/providers/minimal/minimal.h
@@ -0,0 +1,42 @@
+/*
+ SSSD
+
+ minimal Identity Backend Module
+
+ Authors:
+ Justin Stephenson
+
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifndef _MINIMAL_H_
+#define _MINIMAL_H_
+
+#include "config.h"
+#include
+
+#include "providers/ldap/ldap_common.h"
+#include "providers/failover/failover.h"
+
+struct minimal_init_ctx {
+ struct sdap_options *options;
+ struct sdap_id_ctx *id_ctx;
+ struct sdap_auth_ctx *auth_ctx;
+ struct sss_failover_ctx *fctx;
+};
+
+#endif
diff --git a/src/providers/minimal/minimal_id.c b/src/providers/minimal/minimal_id.c
new file mode 100644
index 00000000000..6c471932650
--- /dev/null
+++ b/src/providers/minimal/minimal_id.c
@@ -0,0 +1,241 @@
+/*
+ SSSD
+
+ minimal Identity Backend Module
+
+ Authors:
+ Justin Stephenson
+
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+
+#include "util/util.h"
+#include "providers/minimal/minimal.h"
+#include "providers/minimal/minimal_id.h"
+#include "providers/minimal/minimal_id_services.h"
+#include "providers/failover/failover_transaction.h"
+
+struct minimal_handle_acct_req_state {
+ struct dp_id_data *ar;
+ const char *err;
+ int minimal_ret;
+ int sdap_ret;
+};
+
+static void minimal_handle_acct_req_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+minimal_handle_acct_req_send(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct dp_id_data *ar,
+ struct sss_failover_ctx *fctx,
+ struct sdap_id_ctx *id_ctx,
+ struct sdap_domain *sdom,
+ bool noexist_delete)
+{
+ struct tevent_req *req;
+ struct tevent_req *subreq;
+ struct minimal_handle_acct_req_state *state;
+ errno_t ret;
+
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct minimal_handle_acct_req_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create() failed.\n");
+ return NULL;
+ }
+ state->ar = ar;
+
+ if (ar == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Missing input.\n");
+ ret = EINVAL;
+ goto done;
+ }
+
+ switch (ar->entry_type & BE_REQ_TYPE_MASK) {
+ case BE_REQ_SERVICES:
+ DEBUG(SSSDBG_TRACE_FUNC, "Executing BE_REQ_SERVICES request\n");
+
+ subreq = minimal_services_get_send(state, be_ctx->ev, fctx, id_ctx,
+ sdom, ar->filter_value,
+ ar->extra_value, ar->filter_type,
+ noexist_delete);
+ break;
+ default: /*fail*/
+ ret = EINVAL;
+ state->err = "Invalid request type";
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unexpected request type: 0x%X [%s:%s] in %s\n",
+ ar->entry_type, ar->filter_value,
+ ar->extra_value?ar->extra_value:"-",
+ ar->domain);
+ goto done;
+ }
+
+ if (!subreq) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, minimal_handle_acct_req_done, req);
+ return req;
+
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+
+ tevent_req_post(req, be_ctx->ev);
+ return req;
+}
+
+static void minimal_handle_acct_req_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req);
+ struct minimal_handle_acct_req_state *state;
+ errno_t ret;
+ const char *err = "Invalid request type";
+
+ state = tevent_req_data(req, struct minimal_handle_acct_req_state);
+
+ switch (state->ar->entry_type & BE_REQ_TYPE_MASK) {
+ case BE_REQ_SERVICES:
+ err = "Service lookup failed";
+ ret = minimal_services_get_recv(subreq);
+ break;
+ default: /* fail */
+ ret = EINVAL;
+ break;
+ }
+ talloc_zfree(subreq);
+
+ state->minimal_ret = ret;
+ if (ret != EOK) {
+ state->err = err;
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ state->err = "Success";
+ tevent_req_done(req);
+}
+
+static errno_t
+minimal_handle_acct_req_recv(struct tevent_req *req,
+ const char **_err,
+ int *minimal_ret)
+{
+ struct minimal_handle_acct_req_state *state;
+
+ state = tevent_req_data(req, struct minimal_handle_acct_req_state);
+
+ if (_err) {
+ *_err = state->err;
+ }
+
+ if (minimal_ret) {
+ *minimal_ret = state->minimal_ret;
+ }
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+ return EOK;
+}
+
+struct minimal_account_info_handler_state {
+ struct dp_reply_std reply;
+};
+
+static void minimal_account_info_handler_done(struct tevent_req *subreq);
+
+struct tevent_req *
+minimal_account_info_handler_send(TALLOC_CTX *mem_ctx,
+ struct minimal_init_ctx *init_ctx,
+ struct dp_id_data *data,
+ struct dp_req_params *params)
+{
+ struct minimal_account_info_handler_state *state;
+ struct tevent_req *subreq = NULL;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct minimal_account_info_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ subreq = minimal_handle_acct_req_send(state, params->be_ctx, data,
+ init_ctx->fctx,
+ init_ctx->id_ctx,
+ init_ctx->id_ctx->opts->sdom,
+ true);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "minimal_handle_acct_req_send() failed.\n");
+ ret = ENOMEM;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, minimal_account_info_handler_done, req);
+
+ return req;
+
+immediately:
+ dp_reply_std_set(&state->reply, ret, NULL);
+
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
+}
+
+static void minimal_account_info_handler_done(struct tevent_req *subreq)
+{
+ struct minimal_account_info_handler_state *state;
+ struct tevent_req *req;
+ const char *error_msg = NULL;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct minimal_account_info_handler_state);
+
+ ret = minimal_handle_acct_req_recv(subreq, &error_msg, NULL);
+ talloc_zfree(subreq);
+
+ dp_reply_std_set(&state->reply, ret, error_msg);
+ tevent_req_done(req);
+}
+
+errno_t
+minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data)
+{
+ struct minimal_account_info_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct minimal_account_info_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *data = state->reply;
+
+ return EOK;
+}
diff --git a/src/providers/minimal/minimal_id.h b/src/providers/minimal/minimal_id.h
new file mode 100644
index 00000000000..d7f9e79a24c
--- /dev/null
+++ b/src/providers/minimal/minimal_id.h
@@ -0,0 +1,51 @@
+/*
+ SSSD
+
+ minimal Identity Backend Module
+
+ Authors:
+ Justin Stephenson
+
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifndef _MINIMAL_ID_H_
+#define _MINIMAL_ID_H_
+
+#include "config.h"
+#include
+
+#include "providers/backend.h"
+#include "providers/ldap/ldap_common.h"
+#include "util/util.h"
+
+struct minimal_id_ctx {
+ struct be_ctx *be_ctx;
+ struct minimal_init_ctx *init_ctx;
+ struct dp_option *minimal_options;
+};
+
+struct tevent_req *
+minimal_account_info_handler_send(TALLOC_CTX *mem_ctx,
+ struct minimal_init_ctx *init_ctx,
+ struct dp_id_data *data,
+ struct dp_req_params *params);
+
+errno_t minimal_account_info_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct dp_reply_std *data);
+#endif
diff --git a/src/providers/minimal/minimal_id_services.c b/src/providers/minimal/minimal_id_services.c
new file mode 100644
index 00000000000..66f2d70d9fd
--- /dev/null
+++ b/src/providers/minimal/minimal_id_services.c
@@ -0,0 +1,276 @@
+/*
+ SSSD
+
+ Authors:
+ Stephen Gallagher
+
+ Copyright (C) 2012 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#include
+
+#include "util/util.h"
+#include "util/strtonum.h"
+#include "db/sysdb.h"
+#include "db/sysdb_services.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/minimal/minimal_id_services.h"
+#include "providers/failover/ldap/failover_ldap.h"
+#include "providers/failover/failover_transaction.h"
+
+struct minimal_services_get_state {
+ struct tevent_context *ev;
+ struct sdap_id_ctx *id_ctx;
+ struct sdap_domain *sdom;
+ struct sysdb_ctx *sysdb;
+ struct sss_domain_info *domain;
+ struct sss_failover_ldap_connection *conn;
+
+ const char *name;
+ const char *protocol;
+
+ char *filter;
+ const char **attrs;
+
+ int filter_type;
+
+ bool noexist_delete;
+ bool test;
+};
+
+static void
+minimal_services_get_connect_done(struct tevent_req *subreq);
+static void
+minimal_services_get_done(struct tevent_req *subreq);
+
+struct tevent_req *
+minimal_services_get_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sdap_id_ctx *id_ctx,
+ struct sdap_domain *sdom,
+ const char *name,
+ const char *protocol,
+ int filter_type,
+ bool noexist_delete)
+{
+ errno_t ret;
+ struct tevent_req *req;
+ struct minimal_services_get_state *state;
+ const char *attr_name;
+ char *clean_name;
+ char *clean_protocol = NULL;
+
+ req = tevent_req_create(mem_ctx, &state, struct minimal_services_get_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->id_ctx = id_ctx;
+ state->sdom = sdom;
+ state->domain = sdom->dom;
+ state->sysdb = sdom->dom->sysdb;
+ state->name = name;
+ state->protocol = protocol;
+ state->filter_type = filter_type;
+ state->noexist_delete = noexist_delete;
+ state->test = true;
+
+ switch(filter_type) {
+ case BE_FILTER_NAME:
+ attr_name = id_ctx->opts->service_map[SDAP_AT_SERVICE_NAME].name;
+ break;
+ case BE_FILTER_IDNUM:
+ attr_name = id_ctx->opts->service_map[SDAP_AT_SERVICE_PORT].name;
+ break;
+ default:
+ ret = EINVAL;
+ goto error;
+ }
+
+ ret = sss_filter_sanitize(state, name, &clean_name);
+ if (ret != EOK) goto error;
+
+ if (protocol != NULL) {
+ ret = sss_filter_sanitize(state, protocol, &clean_protocol);
+ if (ret != EOK) goto error;
+ }
+
+ if (clean_protocol) {
+ state->filter = talloc_asprintf(
+ state, "(&(%s=%s)(%s=%s)(objectclass=%s))",
+ attr_name, clean_name,
+ id_ctx->opts->service_map[SDAP_AT_SERVICE_PROTOCOL].name,
+ clean_protocol,
+ id_ctx->opts->service_map[SDAP_OC_SERVICE].name);
+ } else {
+ state->filter =
+ talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
+ attr_name, clean_name,
+ id_ctx->opts->service_map[SDAP_OC_SERVICE].name);
+ }
+ talloc_zfree(clean_name);
+ talloc_zfree(clean_protocol);
+ if (!state->filter) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Failed to build the base filter\n");
+ ret = ENOMEM;
+ goto error;
+ }
+ DEBUG(SSSDBG_TRACE_LIBS,
+ "Preparing to search for services with filter [%s]\n",
+ state->filter);
+
+ ret = build_attrs_from_map(state, id_ctx->opts->service_map,
+ SDAP_OPTS_SERVICES, NULL,
+ &state->attrs, NULL);
+ if (ret != EOK) goto error;
+
+ ret = sss_failover_transaction_send(state, ev, fctx, req,
+ minimal_services_get_connect_done);
+ if (ret != EOK) goto error;
+
+ return req;
+
+error:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void
+minimal_services_get_connect_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct minimal_services_get_state *state =
+ tevent_req_data(req, struct minimal_services_get_state);
+
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
+ if (state->test) {
+ state->test = false;
+ tevent_req_error(req, ERR_SERVER_FAILURE);
+ return;
+ }
+
+ subreq = sdap_get_services_send(state, state->ev,
+ state->domain, state->sysdb,
+ state->id_ctx->opts,
+ state->sdom->service_search_bases,
+ state->conn->sh,
+ state->attrs, state->filter,
+ dp_opt_get_int(state->id_ctx->opts->basic,
+ SDAP_SEARCH_TIMEOUT),
+ false);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, minimal_services_get_done, req);
+}
+
+static void
+minimal_services_get_done(struct tevent_req *subreq)
+{
+ errno_t ret;
+ uint16_t port;
+ char *endptr;
+ struct tevent_req *req =
+ tevent_req_callback_data(subreq, struct tevent_req);
+ struct minimal_services_get_state *state =
+ tevent_req_data(req, struct minimal_services_get_state);
+
+ ret = sdap_get_services_recv(NULL, subreq, NULL);
+ talloc_zfree(subreq);
+
+ /* Check whether we need to try again with another
+ * failover server.
+ */
+ // TODO handle how to yield ERR_SERVER_FAILED
+ // ret = sdap_id_op_done(state->op, ret, &dp_error);
+ // if (dp_error == DP_ERR_OK && ret != EOK) {
+ // /* retry */
+ // ret = minimal_services_get_retry(req);
+ // if (ret != EOK) {
+ // tevent_req_error(req, ret);
+ // return;
+ // }
+
+ // /* Return to the mainloop to retry */
+ // return;
+ // }
+ // state->sdap_ret = ret;
+
+ // /* An error occurred. */
+ // if (ret && ret != ENOENT) {
+ // state->dp_error = dp_error;
+ // tevent_req_error(req, ret);
+ // return;
+ //}
+
+ if (ret == ENOENT && state->noexist_delete == true) {
+ /* Ensure that this entry is removed from the sysdb */
+ switch(state->filter_type) {
+ case BE_FILTER_NAME:
+ ret = sysdb_svc_delete(state->domain, state->name,
+ 0, state->protocol);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ break;
+
+ case BE_FILTER_IDNUM:
+ port = strtouint16(state->name, &endptr, 10);
+ if (errno || *endptr || (state->name == endptr)) {
+ tevent_req_error(req, (errno ? errno : EINVAL));
+ return;
+ }
+
+ ret = sysdb_svc_delete(state->domain, NULL, port,
+ state->protocol);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+ break;
+
+ default:
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+ }
+
+ tevent_req_done(req);
+}
+
+errno_t
+minimal_services_get_recv(struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
diff --git a/src/providers/minimal/minimal_id_services.h b/src/providers/minimal/minimal_id_services.h
new file mode 100644
index 00000000000..6f82b2e3ac2
--- /dev/null
+++ b/src/providers/minimal/minimal_id_services.h
@@ -0,0 +1,52 @@
+/*
+ SSSD
+
+ minimal Identity Backend Module
+
+ Authors:
+ Justin Stephenson
+
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifndef _MINIMAL_ID_SERVICES_H_
+#define _MINIMAL_ID_SERVICES_H_
+
+#include "config.h"
+#include
+#include
+
+#include "providers/backend.h"
+#include "providers/ldap/ldap_common.h"
+#include "util/util.h"
+#include "providers/failover/failover.h"
+
+struct tevent_req *
+minimal_services_get_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sdap_id_ctx *id_ctx,
+ struct sdap_domain *sdom,
+ const char *name,
+ const char *protocol,
+ int filter_type,
+ bool noexist_delete);
+
+errno_t
+minimal_services_get_recv(struct tevent_req *req);
+
+#endif
diff --git a/src/providers/minimal/minimal_init.c b/src/providers/minimal/minimal_init.c
new file mode 100644
index 00000000000..d6f126fc46d
--- /dev/null
+++ b/src/providers/minimal/minimal_init.c
@@ -0,0 +1,349 @@
+/*
+ SSSD
+
+ minimal Provider Initialization functions
+
+ Authors:
+ Justin Stephenson
+
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "src/providers/data_provider.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/ldap_opts.h"
+#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/sdap_access.h"
+#include "providers/ldap/ldap_resolver_enum.h"
+#include "providers/fail_over_srv.h"
+#include "providers/be_refresh.h"
+
+#include "src/providers/minimal/minimal.h"
+#include "src/providers/minimal/minimal_id.h"
+#include "src/providers/minimal/minimal_ldap_auth.h"
+#include "src/providers/failover/failover.h"
+#include "src/providers/failover/failover_vtable.h"
+#include "src/providers/failover/ldap/failover_ldap.h"
+
+/* Copied from ldap_init.c with no changes */
+static errno_t get_sdap_service(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_options *opts,
+ struct sdap_service **_sdap_service)
+{
+ errno_t ret;
+ const char *urls;
+ const char *backup_urls;
+ const char *dns_service_name;
+ struct sdap_service *sdap_service;
+
+ urls = dp_opt_get_string(opts->basic, SDAP_URI);
+ backup_urls = dp_opt_get_string(opts->basic, SDAP_BACKUP_URI);
+ dns_service_name = dp_opt_get_string(opts->basic, SDAP_DNS_SERVICE_NAME);
+ if (dns_service_name != NULL) {
+ DEBUG(SSSDBG_CONF_SETTINGS,
+ "Service name for discovery set to %s\n", dns_service_name);
+ }
+
+ ret = sdap_service_init(mem_ctx, be_ctx, "LDAP",
+ dns_service_name,
+ urls,
+ backup_urls,
+ &sdap_service);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ *_sdap_service = sdap_service;
+ return EOK;
+}
+
+/* Copied from ldap_init.c with some changes
+ * removing calls to
+ * - sdap_gssapi_init()
+ * - sdap_idmap_init()
+ * - confdb_certmap_to_sysdb()
+ * - sdap_init_certmap() */
+static errno_t ldap_init_misc(struct be_ctx *be_ctx,
+ struct sdap_options *options,
+ struct sdap_id_ctx *id_ctx)
+{
+ errno_t ret;
+
+ setup_ldap_debug(options->basic);
+
+ ret = setup_tls_config(options->basic);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get TLS options [%d]: %s\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+
+ ret = ldap_id_setup_tasks(id_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup background tasks "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+
+ /* Setup SRV lookup plugin */
+ ret = be_fo_set_dns_srv_lookup_plugin(be_ctx, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to set SRV lookup plugin "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+
+ /* Setup periodical refresh of expired records */
+ ret = sdap_refresh_init(be_ctx, id_ctx);
+ if (ret != EOK && ret != EEXIST) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Periodical refresh will not work "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ }
+
+ return EOK;
+}
+
+/* Copied from ldap_init.c */
+static errno_t minimal_init_auth_ctx(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_id_ctx *id_ctx,
+ struct sdap_options *options,
+ struct sdap_auth_ctx **_auth_ctx)
+{
+ struct sdap_auth_ctx *auth_ctx;
+
+ auth_ctx = talloc(mem_ctx, struct sdap_auth_ctx);
+ if (auth_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ auth_ctx->be = be_ctx;
+ auth_ctx->opts = options;
+ auth_ctx->service = id_ctx->conn->service;
+ auth_ctx->chpass_service = NULL;
+
+ *_auth_ctx = auth_ctx;
+
+ return EOK;
+}
+
+static struct sss_failover_ctx *
+sssm_minimal_init_failover(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct sdap_options *opts)
+{
+ struct sss_failover_ctx *fctx;
+ struct sss_failover_group *group;
+ struct sss_failover_server *server;
+ errno_t ret;
+
+ /* Setup new failover. */
+ fctx = sss_failover_init(mem_ctx, be_ctx->ev, "LDAP",
+ be_ctx->be_res->resolv,
+ be_ctx->be_res->family_order);
+ if (fctx == NULL) {
+ return NULL;
+ }
+
+ /* Add primary servers */
+ group = sss_failover_group_new(fctx, "primary");
+ if (group == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_setup_dns_discovery(group);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ server = sss_failover_server_new(fctx, "fake_1.ldap.test",
+ "ldap://fake_1.ldap.test", 389, 1, 1);
+ if (server == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_add_server(group, server);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ server = sss_failover_server_new(fctx, "fake_2.ldap.test",
+ "ldap://fake_2.ldap.test", 389, 1, 1);
+ if (server == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_add_server(group, server);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ server = sss_failover_server_new(fctx, "master.ldap.test",
+ "ldap://master.ldap.test", 389, 1, 1);
+ if (server == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = sss_failover_group_add_server(group, server);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ sss_failover_vtable_set_connect(fctx,
+ sss_failover_ldap_connect_send,
+ sss_failover_ldap_connect_recv,
+ opts);
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(fctx);
+ return NULL;
+ }
+
+ return fctx;
+}
+
+errno_t sssm_minimal_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ struct data_provider *provider,
+ const char *module_name,
+ void **_module_data)
+{
+ struct sdap_service *sdap_service;
+ struct minimal_init_ctx *init_ctx;
+ errno_t ret;
+
+ init_ctx = talloc_zero(mem_ctx, struct minimal_init_ctx);
+ if (init_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ /* Always initialize options since it is needed everywhere. */
+ ret = ldap_get_options(init_ctx, be_ctx->domain, be_ctx->cdb,
+ be_ctx->conf_path, be_ctx->provider,
+ &init_ctx->options);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP options "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ /* Always initialize id_ctx since it is needed everywhere. */
+ ret = get_sdap_service(init_ctx, be_ctx, init_ctx->options, &sdap_service);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to initialize failover service "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ init_ctx->id_ctx = sdap_id_ctx_new(init_ctx, be_ctx, sdap_service);
+ if (init_ctx->id_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to initialize LDAP ID context\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ init_ctx->id_ctx->opts = init_ctx->options;
+
+ /* Setup miscellaneous things. */
+ ret = ldap_init_misc(be_ctx, init_ctx->options, init_ctx->id_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to init LDAP module "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+ /* Initialize auth_ctx only if DPT_AUTH target is enabled. */
+ if (dp_target_enabled(provider, module_name, DPT_AUTH)) {
+ ret = minimal_init_auth_ctx(init_ctx, be_ctx, init_ctx->id_ctx,
+ init_ctx->options, &init_ctx->auth_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create auth context "
+ "[%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+ }
+
+ /* Setup new failover. */
+ init_ctx->fctx = sssm_minimal_init_failover(init_ctx, be_ctx, init_ctx->id_ctx->opts);
+ if (init_ctx->fctx == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to init new failover\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ *_module_data = init_ctx;
+
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(init_ctx);
+ }
+
+ return ret;
+}
+
+errno_t sssm_minimal_id_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
+{
+ struct minimal_init_ctx *init_ctx;
+ errno_t ret;
+
+ init_ctx = talloc_get_type(module_data, struct minimal_init_ctx);
+
+ dp_set_method(dp_methods, DPM_ACCOUNT_HANDLER,
+ minimal_account_info_handler_send, minimal_account_info_handler_recv, init_ctx,
+ struct minimal_init_ctx, struct dp_id_data, struct dp_reply_std);
+
+ /* LDAP provider check online handler */
+ dp_set_method(dp_methods, DPM_CHECK_ONLINE,
+ sdap_online_check_handler_send, sdap_online_check_handler_recv, init_ctx->id_ctx,
+ struct sdap_id_ctx, void, struct dp_reply_std);
+
+ dp_set_method(dp_methods, DPM_ACCT_DOMAIN_HANDLER,
+ default_account_domain_send, default_account_domain_recv, NULL,
+ void, struct dp_get_acct_domain_data, struct dp_reply_std);
+
+ ret = EOK;
+
+ return ret;
+}
+
+errno_t sssm_minimal_auth_init(TALLOC_CTX *mem_ctx,
+ struct be_ctx *be_ctx,
+ void *module_data,
+ struct dp_method *dp_methods)
+{
+ struct minimal_init_ctx *init_ctx;
+
+ init_ctx = talloc_get_type(module_data, struct minimal_init_ctx);
+
+ dp_set_method(dp_methods, DPM_AUTH_HANDLER,
+ minimal_sdap_pam_auth_handler_send, minimal_sdap_pam_auth_handler_recv, init_ctx,
+ struct minimal_init_ctx, struct pam_data, struct pam_data *);
+
+ return EOK;
+}
diff --git a/src/providers/minimal/minimal_ldap_auth.c b/src/providers/minimal/minimal_ldap_auth.c
new file mode 100644
index 00000000000..3a6e47c706f
--- /dev/null
+++ b/src/providers/minimal/minimal_ldap_auth.c
@@ -0,0 +1,884 @@
+/*
+ SSSD
+
+ LDAP Backend Module
+
+ Authors:
+ Sumit Bose
+
+ Copyright (C) 2008 Red Hat
+ Copyright (C) 2010, rhafer@suse.de, Novell Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "util/util.h"
+#include "util/user_info_msg.h"
+#include "db/sysdb.h"
+#include "providers/ldap/ldap_common.h"
+#include "providers/ldap/sdap_async.h"
+#include "providers/ldap/sdap_async_private.h"
+#include "providers/ldap/ldap_auth.h"
+#include "providers/minimal/minimal.h"
+#include "providers/failover/failover_transaction.h"
+#include "providers/failover/ldap/failover_ldap.h"
+
+static errno_t
+find_password_expiration_attributes(TALLOC_CTX *mem_ctx,
+ const struct ldb_message *msg,
+ enum sdap_access_type access_type,
+ struct dp_option *opts,
+ enum pwexpire *pwd_exp_type,
+ void **data)
+{
+ const char *mark;
+ const char *val;
+ struct spwd *spwd;
+ const char *pwd_policy;
+ int ret;
+
+ *pwd_exp_type = PWEXPIRE_NONE;
+ *data = NULL;
+
+ switch (access_type) {
+ case SDAP_TYPE_IPA:
+ /* MIT-Kerberos is the only option for IPA */
+ pwd_policy = PWD_POL_OPT_MIT;
+ break;
+ case SDAP_TYPE_LDAP:
+ pwd_policy = dp_opt_get_string(opts, SDAP_PWD_POLICY);
+ if (pwd_policy == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing password policy.\n");
+ return EINVAL;
+ }
+ break;
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE,"Unknown access_type [%i].\n", access_type);
+ return EINVAL;
+ }
+
+ if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) == 0) {
+ DEBUG(SSSDBG_TRACE_ALL, "No password policy requested.\n");
+ return EOK;
+ } else if (strcasecmp(pwd_policy, PWD_POL_OPT_MIT) == 0) {
+ mark = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_LASTCHANGE, NULL);
+ if (mark != NULL) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Found Kerberos password expiration attributes.\n");
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_EXPIRATION,
+ NULL);
+ if (val != NULL) {
+ *data = talloc_strdup(mem_ctx, val);
+ if (*data == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n");
+ return ENOMEM;
+ }
+ *pwd_exp_type = PWEXPIRE_KERBEROS;
+
+ return EOK;
+ }
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "No Kerberos password expiration attributes found, "
+ "but MIT Kerberos password policy was requested. "
+ "Access will be denied.\n");
+ return EACCES;
+ }
+ } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) {
+ mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL);
+ if (mark != NULL) {
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Found shadow password expiration attributes.\n");
+ spwd = talloc_zero(mem_ctx, struct spwd);
+ if (spwd == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n");
+ return ENOMEM;
+ }
+
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL);
+ ret = string_to_shadowpw_days(val, &spwd->sp_lstchg);
+ if (ret != EOK) goto shadow_fail;
+
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL);
+ ret = string_to_shadowpw_days(val, &spwd->sp_min);
+ if (ret != EOK) goto shadow_fail;
+
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MAX, NULL);
+ ret = string_to_shadowpw_days(val, &spwd->sp_max);
+ if (ret != EOK) goto shadow_fail;
+
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_WARNING, NULL);
+ ret = string_to_shadowpw_days(val, &spwd->sp_warn);
+ if (ret != EOK) goto shadow_fail;
+
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_INACTIVE, NULL);
+ ret = string_to_shadowpw_days(val, &spwd->sp_inact);
+ if (ret != EOK) goto shadow_fail;
+
+ val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_EXPIRE, NULL);
+ ret = string_to_shadowpw_days(val, &spwd->sp_expire);
+ if (ret != EOK) goto shadow_fail;
+
+ *data = spwd;
+ *pwd_exp_type = PWEXPIRE_SHADOW;
+
+ return EOK;
+ } else {
+ DEBUG(SSSDBG_CRIT_FAILURE, "No shadow password attributes found, "
+ "but shadow password policy was requested. "
+ "Access will be denied.\n");
+ return EACCES;
+ }
+ }
+
+ DEBUG(SSSDBG_TRACE_ALL, "No password expiration attributes found.\n");
+ return EOK;
+
+shadow_fail:
+ talloc_free(spwd);
+ return ret;
+}
+
+/* ==Get-User-DN========================================================== */
+struct get_user_dn_state {
+ char *username;
+
+ char *orig_dn;
+};
+
+static void get_user_dn_done(struct tevent_req *subreq);
+
+static struct tevent_req *get_user_dn_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sss_domain_info *domain,
+ struct sdap_handle *sh,
+ struct sdap_options *opts,
+ const char *username)
+{
+ struct tevent_req *req;
+ struct tevent_req *subreq;
+ struct get_user_dn_state *state;
+ char *clean_name;
+ char *filter;
+ const char **attrs;
+ errno_t ret;
+
+ req = tevent_req_create(memctx, &state, struct get_user_dn_state);
+ if (!req) return NULL;
+
+ ret = sss_parse_internal_fqname(state, username,
+ &state->username, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot parse %s\n", username);
+ goto done;
+ }
+
+ ret = sss_filter_sanitize(state, state->username, &clean_name);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
+ opts->user_map[SDAP_AT_USER_NAME].name,
+ clean_name,
+ opts->user_map[SDAP_OC_USER].name);
+ talloc_zfree(clean_name);
+ if (filter == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to build the base filter\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* We're mostly interested in the DN anyway */
+ attrs = talloc_array(state, const char *, 3);
+ if (attrs == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ attrs[0] = "objectclass";
+ attrs[1] = opts->user_map[SDAP_AT_USER_NAME].name;
+ attrs[2] = NULL;
+
+ subreq = sdap_search_user_send(state, ev, domain, opts,
+ opts->sdom->user_search_bases,
+ sh, attrs, filter,
+ dp_opt_get_int(opts->basic,
+ SDAP_SEARCH_TIMEOUT),
+ SDAP_LOOKUP_SINGLE);
+ if (!subreq) {
+ ret = ENOMEM;
+ goto done;
+ }
+ tevent_req_set_callback(subreq, get_user_dn_done, req);
+ return req;
+
+done:
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void get_user_dn_done(struct tevent_req *subreq)
+{
+ errno_t ret;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct get_user_dn_state *state = tevent_req_data(req,
+ struct get_user_dn_state);
+ struct ldb_message_element *el;
+ struct sysdb_attrs **users;
+ size_t count;
+
+ ret = sdap_search_user_recv(state, subreq, NULL, &users, &count);
+ talloc_zfree(subreq);
+ if (ret && ret != ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to retrieve users\n");
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ if (count == 0) {
+ DEBUG(SSSDBG_OP_FAILURE, "No such user\n");
+ tevent_req_error(req, ENOMEM);
+ return;
+ } else if (count > 1) {
+ DEBUG(SSSDBG_OP_FAILURE, "Multiple users matched\n");
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ /* exactly one user. Get the originalDN */
+ ret = sysdb_attrs_get_el_ext(users[0], SYSDB_ORIG_DN, false, &el);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "originalDN is not available for [%s].\n", state->username);
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ state->orig_dn = talloc_strdup(state, (const char *) el->values[0].data);
+ if (state->orig_dn == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Found originalDN [%s] for [%s]\n",
+ state->orig_dn, state->username);
+ tevent_req_done(req);
+}
+
+static int get_user_dn_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req,
+ char **orig_dn)
+{
+ struct get_user_dn_state *state = tevent_req_data(req,
+ struct get_user_dn_state);
+
+ if (orig_dn) {
+ *orig_dn = talloc_move(mem_ctx, &state->orig_dn);
+ }
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
+int get_user_dn(TALLOC_CTX *memctx,
+ struct sss_domain_info *domain,
+ enum sdap_access_type access_type,
+ struct sdap_options *opts,
+ const char *username,
+ char **user_dn,
+ enum pwexpire *user_pw_expire_type,
+ void **user_pw_expire_data)
+{
+ TALLOC_CTX *tmpctx;
+ enum pwexpire pw_expire_type = PWEXPIRE_NONE;
+ void *pw_expire_data;
+ struct ldb_result *res;
+ const char **attrs;
+ const char *dn = NULL;
+ int ret;
+
+ tmpctx = talloc_new(memctx);
+ if (!tmpctx) {
+ return ENOMEM;
+ }
+
+ attrs = talloc_array(tmpctx, const char *, 11);
+ if (!attrs) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ attrs[0] = SYSDB_ORIG_DN;
+ attrs[1] = SYSDB_SHADOWPW_LASTCHANGE;
+ attrs[2] = SYSDB_SHADOWPW_MIN;
+ attrs[3] = SYSDB_SHADOWPW_MAX;
+ attrs[4] = SYSDB_SHADOWPW_WARNING;
+ attrs[5] = SYSDB_SHADOWPW_INACTIVE;
+ attrs[6] = SYSDB_SHADOWPW_EXPIRE;
+ attrs[7] = SYSDB_KRBPW_LASTCHANGE;
+ attrs[8] = SYSDB_KRBPW_EXPIRATION;
+ attrs[9] = SYSDB_PWD_ATTRIBUTE;
+ attrs[10] = NULL;
+
+ ret = sysdb_get_user_attr(tmpctx, domain, username, attrs, &res);
+ if (ret) {
+ goto done;
+ }
+
+ switch (res->count) {
+ case 0:
+ /* No such user entry? Look it up */
+ ret = EAGAIN;
+ break;
+
+ case 1:
+ dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL);
+ if (dn == NULL) {
+ /* The user entry has no original DN. This is the case when the ID
+ * provider is not LDAP-based (proxy perhaps) */
+ ret = EAGAIN;
+ break;
+ }
+
+ dn = talloc_strdup(tmpctx, dn);
+ if (!dn) {
+ ret = ENOMEM;
+ break;
+ }
+
+ ret = find_password_expiration_attributes(tmpctx,
+ res->msgs[0],
+ access_type,
+ opts->basic,
+ &pw_expire_type,
+ &pw_expire_data);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "find_password_expiration_attributes failed.\n");
+ }
+ break;
+
+ default:
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "User search by name (%s) returned > 1 results!\n",
+ username);
+ ret = EFAULT;
+ break;
+ }
+
+done:
+ if (ret == EOK) {
+ *user_dn = talloc_strdup(memctx, dn);
+ if (!*user_dn) {
+ ret = ENOMEM;
+ }
+ /* pw_expire_data may be NULL */
+ *user_pw_expire_data = talloc_steal(memctx, pw_expire_data);
+ *user_pw_expire_type = pw_expire_type;
+ }
+
+ talloc_zfree(tmpctx);
+ return ret;
+}
+
+/* ==Authenticate-User==================================================== */
+
+struct minimal_auth_state {
+ struct tevent_context *ev;
+ struct sss_failover_ctx *fctx;
+ struct sdap_auth_ctx *ctx;
+ const char *username;
+ struct sss_auth_token *authtok;
+ struct sdap_service *sdap_service;
+
+ struct sss_failover_ldap_connection *conn;
+
+ char *dn;
+ enum pwexpire pw_expire_type;
+ void *pw_expire_data;
+};
+
+static errno_t auth_connect_send(struct tevent_req *req);
+static void auth_get_dn_done(struct tevent_req *subreq);
+static void auth_do_bind(struct tevent_req *req);
+static void auth_connect_done(struct tevent_req *subreq);
+static void auth_bind_user_done(struct tevent_req *subreq);
+
+static struct tevent_req *
+minimal_auth_send(TALLOC_CTX *memctx,
+ struct tevent_context *ev,
+ struct sss_failover_ctx *fctx,
+ struct sdap_auth_ctx *ctx,
+ const char *username,
+ struct sss_auth_token *authtok,
+ bool try_chpass_service)
+{
+ struct tevent_req *req;
+ struct minimal_auth_state *state;
+ errno_t ret;
+
+ req = tevent_req_create(memctx, &state, struct minimal_auth_state);
+ if (!req) return NULL;
+
+ /* The token must be a password token */
+ if (sss_authtok_get_type(authtok) != SSS_AUTHTOK_TYPE_PASSWORD &&
+ sss_authtok_get_type(authtok) != SSS_AUTHTOK_TYPE_PAM_STACKED) {
+ if (sss_authtok_get_type(authtok) == SSS_AUTHTOK_TYPE_SC_PIN
+ || sss_authtok_get_type(authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD) {
+ /* Tell frontend that we do not support Smartcard authentication */
+ ret = ERR_SC_AUTH_NOT_SUPPORTED;
+ } else {
+ ret = ERR_AUTH_FAILED;
+ }
+ goto fail;
+ }
+
+ state->ev = ev;
+ state->fctx = fctx;
+ state->ctx = ctx;
+ state->username = username;
+ state->authtok = authtok;
+ if (try_chpass_service && ctx->chpass_service != NULL &&
+ ctx->chpass_service->name != NULL) {
+ state->sdap_service = ctx->chpass_service;
+ } else {
+ state->sdap_service = ctx->service;
+ }
+
+ ret = get_user_dn(state, state->ctx->be->domain, SDAP_TYPE_LDAP,
+ state->ctx->opts, state->username, &state->dn,
+ &state->pw_expire_type, &state->pw_expire_data);
+ if (ret == EAGAIN) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Need to look up the DN of %s later\n", state->username);
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Cannot get user DN [%d]: %s\n", ret, sss_strerror(ret));
+ goto fail;
+ }
+
+ ret = auth_connect_send(req);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ return req;
+
+fail:
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static errno_t auth_connect_send(struct tevent_req *req)
+{
+ struct minimal_auth_state *state = tevent_req_data(req,
+ struct minimal_auth_state);
+ bool use_tls;
+ bool skip_conn_auth = false;
+ const char *sasl_mech;
+ errno_t ret;
+
+ /* Check for undocumented debugging feature to disable TLS
+ * for authentication. This should never be used in production
+ * for obvious reasons.
+ */
+ use_tls = !dp_opt_get_bool(state->ctx->opts->basic, SDAP_DISABLE_AUTH_TLS);
+ if (!use_tls) {
+ sss_log(SSS_LOG_ALERT, "LDAP authentication being performed over "
+ "insecure connection. This should be done "
+ "for debugging purposes only.");
+ }
+
+ if (state->dn != NULL) {
+ /* In case the user's DN is known, the connection will only be used
+ * to bind as the user to perform the authentication. In that case,
+ * we don't need to authenticate the connection, because we're not
+ * looking up any information using the connection. This might be
+ * needed e.g. in case both ID and AUTH providers are set to LDAP
+ * and the server is AD, because otherwise the connection would both
+ * do a startTLS and later bind using GSSAPI or GSS-SPNEGO which
+ * doesn't work well with AD.
+ */
+ skip_conn_auth = true;
+ }
+
+ if (skip_conn_auth == false) {
+ sasl_mech = dp_opt_get_string(state->ctx->opts->basic,
+ SDAP_SASL_MECH);
+ if (sasl_mech && sdap_sasl_mech_needs_kinit(sasl_mech)) {
+ /* Don't force TLS on if we're told to use GSSAPI or GSS-SPNEGO */
+ use_tls = false;
+ }
+ }
+
+ if (ldap_is_ldapi_url(state->sdap_service->uri)) {
+ /* Don't force TLS on if we're a unix domain socket */
+ use_tls = false;
+ }
+
+ ret = sss_failover_transaction_ex_send(
+ state, state->ev, state->fctx, req, auth_connect_done, false,
+ !skip_conn_auth, true,
+ use_tls ? SSS_FAILOVER_TRANSACTION_TLS_ON
+ : SSS_FAILOVER_TRANSACTION_TLS_OFF);
+
+ return ret;
+}
+
+static bool check_encryption_used(LDAP *ldap)
+{
+ ber_len_t sasl_ssf = 0;
+ int tls_inplace = 0;
+ int ret;
+
+ ret = ldap_get_option(ldap, LDAP_OPT_X_SASL_SSF, &sasl_ssf);
+ if (ret != LDAP_OPT_SUCCESS) {
+ DEBUG(SSSDBG_TRACE_LIBS, "ldap_get_option failed to get sasl ssf, "
+ "assuming SASL is not used.\n");
+ sasl_ssf = 0;
+ }
+
+ tls_inplace = ldap_tls_inplace(ldap);
+
+ DEBUG(SSSDBG_TRACE_ALL,
+ "Encryption used: SASL SSF [%lu] tls_inplace [%s].\n", sasl_ssf,
+ tls_inplace == 1 ? "TLS inplace" : "TLS NOT inplace");
+
+ if (sasl_ssf <= 1 && tls_inplace != 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "No encryption detected on LDAP connection.\n");
+ sss_log(SSS_LOG_CRIT, "No encryption detected on LDAP connection.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void auth_connect_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct minimal_auth_state *state = tevent_req_data(req,
+ struct minimal_auth_state);
+
+ state->conn = sss_failover_transaction_connected_recv(state, subreq,
+ struct sss_failover_ldap_connection);
+ talloc_zfree(subreq);
+
+ if (state->conn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: No connection?\n");
+ tevent_req_error(req, EINVAL);
+ return;
+ }
+
+ if (!ldap_is_ldapi_url(state->sdap_service->uri) &&
+ !check_encryption_used(state->conn->sh->ldap) &&
+ !dp_opt_get_bool(state->ctx->opts->basic, SDAP_DISABLE_AUTH_TLS)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Aborting the authentication request.\n");
+ sss_log(SSS_LOG_CRIT, "Aborting the authentication request.\n");
+ tevent_req_error(req, ERR_AUTH_FAILED);
+ return;
+ }
+
+ if (state->dn == NULL) {
+ /* The cached user entry was missing the bind DN. Need to look
+ * it up based on user name in order to perform the bind */
+ subreq = get_user_dn_send(req, state->ev, state->ctx->be->domain,
+ state->conn->sh, state->ctx->opts, state->username);
+ if (subreq == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, auth_get_dn_done, req);
+ return;
+ }
+
+ /* All required user data was pre-cached during an identity lookup.
+ * We can proceed with the bind */
+ auth_do_bind(req);
+ return;
+}
+
+static void auth_get_dn_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state);
+ errno_t ret;
+
+ ret = get_user_dn_recv(state, subreq, &state->dn);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ERR_ACCOUNT_UNKNOWN);
+ return;
+ }
+
+ /* The DN was found with an LDAP lookup
+ * We can proceed with the bind */
+ return auth_do_bind(req);
+}
+
+static void auth_do_bind(struct tevent_req *req)
+{
+ struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state);
+ struct tevent_req *subreq;
+ bool use_ppolicy = dp_opt_get_bool(state->ctx->opts->basic,
+ SDAP_USE_PPOLICY);
+ int timeout = dp_opt_get_int(state->ctx->opts->basic, SDAP_OPT_TIMEOUT);
+
+ subreq = sdap_auth_send(state, state->ev, state->conn->sh,
+ NULL, NULL, state->dn,
+ state->authtok,
+ timeout, use_ppolicy,
+ state->ctx->opts->pwmodify_mode);
+ if (!subreq) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ tevent_req_set_callback(subreq, auth_bind_user_done, req);
+}
+
+static void auth_bind_user_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct minimal_auth_state *state = tevent_req_data(req,
+ struct minimal_auth_state);
+ int ret;
+ struct sdap_ppolicy_data *ppolicy = NULL;
+
+ ret = sdap_auth_recv(subreq, state, &ppolicy);
+ talloc_zfree(subreq);
+ if (ppolicy != NULL) {
+ DEBUG(SSSDBG_TRACE_ALL,"Found ppolicy data, "
+ "assuming LDAP password policies are active.\n");
+ state->pw_expire_type = PWEXPIRE_LDAP_PASSWORD_POLICY;
+ state->pw_expire_data = ppolicy;
+ }
+ switch (ret) {
+ case EOK:
+ break;
+ case ETIMEDOUT:
+ case ERR_NETWORK_IO:
+ tevent_req_error(req, ERR_SERVER_FAILURE);
+ return;
+ default:
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+static errno_t
+minimal_auth_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ enum pwexpire *pw_expire_type,
+ void **pw_expire_data)
+{
+ struct minimal_auth_state *state = tevent_req_data(req, struct minimal_auth_state);
+
+ if (pw_expire_data != NULL) {
+ *pw_expire_data = talloc_steal(memctx, state->pw_expire_data);
+ }
+
+ *pw_expire_type = state->pw_expire_type;
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
+struct minimal_sdap_pam_auth_handler_state {
+ struct pam_data *pd;
+ struct be_ctx *be_ctx;
+ struct sdap_auth_ctx *auth_ctx;
+};
+
+static void minimal_sdap_pam_auth_handler_done(struct tevent_req *subreq);
+
+struct tevent_req *
+minimal_sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx,
+ struct minimal_init_ctx *init_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params)
+{
+ struct sdap_auth_ctx *auth_ctx = init_ctx->auth_ctx;
+ struct minimal_sdap_pam_auth_handler_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct minimal_sdap_pam_auth_handler_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
+ return NULL;
+ }
+
+ state->pd = pd;
+ state->be_ctx = params->be_ctx;
+ state->auth_ctx = auth_ctx;
+ pd->pam_status = PAM_SYSTEM_ERR;
+
+ switch (pd->cmd) {
+ case SSS_PAM_AUTHENTICATE:
+ subreq = minimal_auth_send(state, params->ev, init_ctx->fctx, auth_ctx,
+ pd->user, pd->authtok, false);
+ if (subreq == NULL) {
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
+ }
+
+ tevent_req_set_callback(subreq, minimal_sdap_pam_auth_handler_done, req);
+ break;
+ case SSS_PAM_CHAUTHTOK_PRELIM:
+ case SSS_PAM_CHAUTHTOK:
+ pd->pam_status = PAM_SYSTEM_ERR;
+ goto immediately;
+
+ case SSS_PAM_ACCT_MGMT:
+ case SSS_PAM_SETCRED:
+ case SSS_PAM_OPEN_SESSION:
+ case SSS_PAM_CLOSE_SESSION:
+ pd->pam_status = PAM_SUCCESS;
+ goto immediately;
+ default:
+ pd->pam_status = PAM_MODULE_UNKNOWN;
+ goto immediately;
+ }
+
+ return req;
+
+immediately:
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+ tevent_req_post(req, params->ev);
+
+ return req;
+}
+
+static void minimal_sdap_pam_auth_handler_done(struct tevent_req *subreq)
+{
+ struct minimal_sdap_pam_auth_handler_state *state;
+ struct tevent_req *req;
+ enum pwexpire pw_expire_type;
+ void *pw_expire_data;
+ const char *password;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct minimal_sdap_pam_auth_handler_state);
+
+ ret = minimal_auth_recv(subreq, state, &pw_expire_type, &pw_expire_data);
+ talloc_free(subreq);
+
+ if (ret == EOK) {
+ ret = check_pwexpire_policy(pw_expire_type, pw_expire_data, state->pd,
+ state->be_ctx->domain->pwd_expiration_warning,
+ state->auth_ctx->opts);
+ if (ret == EINVAL) {
+ /* Unknown password expiration type. */
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ }
+
+ switch (ret) {
+ case EOK:
+ state->pd->pam_status = PAM_SUCCESS;
+ break;
+ case ERR_AUTH_DENIED:
+ state->pd->pam_status = PAM_PERM_DENIED;
+ break;
+ case ERR_AUTH_FAILED:
+ state->pd->pam_status = PAM_AUTH_ERR;
+ break;
+ case ETIMEDOUT:
+ case ERR_NETWORK_IO:
+ state->pd->pam_status = PAM_AUTHINFO_UNAVAIL;
+ be_mark_offline(state->be_ctx);
+ break;
+ case ERR_ACCOUNT_EXPIRED:
+ state->pd->pam_status = PAM_ACCT_EXPIRED;
+ break;
+ case ERR_PASSWORD_EXPIRED:
+ state->pd->pam_status = PAM_NEW_AUTHTOK_REQD;
+ break;
+ case ERR_ACCOUNT_LOCKED:
+ state->pd->account_locked = true;
+ state->pd->pam_status = PAM_PERM_DENIED;
+ break;
+ case ERR_SC_AUTH_NOT_SUPPORTED:
+ state->pd->pam_status = PAM_BAD_ITEM;
+ break;
+ default:
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ break;
+ }
+
+ if (ret == EOK && state->be_ctx->domain->cache_credentials) {
+ ret = sss_authtok_get_password(state->pd->authtok, &password, NULL);
+ if (ret == EOK) {
+ ret = sysdb_cache_password(state->be_ctx->domain, state->pd->user,
+ password);
+ }
+
+ /* password caching failures are not fatal errors */
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to cache password for %s\n",
+ state->pd->user);
+ } else {
+ DEBUG(SSSDBG_CONF_SETTINGS, "Password successfully cached for %s\n",
+ state->pd->user);
+ }
+ }
+
+done:
+ /* TODO For backward compatibility we always return EOK to DP now. */
+ tevent_req_done(req);
+}
+
+errno_t
+minimal_sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data)
+{
+ struct minimal_sdap_pam_auth_handler_state *state = NULL;
+
+ state = tevent_req_data(req, struct minimal_sdap_pam_auth_handler_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_data = talloc_steal(mem_ctx, state->pd);
+
+ return EOK;
+}
diff --git a/src/providers/minimal/minimal_ldap_auth.h b/src/providers/minimal/minimal_ldap_auth.h
new file mode 100644
index 00000000000..23b9015fedd
--- /dev/null
+++ b/src/providers/minimal/minimal_ldap_auth.h
@@ -0,0 +1,49 @@
+/*
+ SSSD
+
+ minimal Identity Backend Module
+
+ Authors:
+ Pavel Březina
+
+ Copyright (C) 2026 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+
+#ifndef _MINIMAL_LDAP_AUTH_H_
+#define _MINIMAL_LDAP_AUTH_H_
+
+#include "config.h"
+#include
+#include
+
+#include "providers/data_provider/dp.h"
+#include "providers/ldap/ldap_common.h"
+#include "util/sss_pam_data.h"
+#include "providers/minimal/minimal.h"
+
+struct tevent_req *
+minimal_sdap_pam_auth_handler_send(TALLOC_CTX *mem_ctx,
+ struct minimal_init_ctx *init_ctx,
+ struct pam_data *pd,
+ struct dp_req_params *params);
+
+errno_t
+minimal_sdap_pam_auth_handler_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ struct pam_data **_data);
+
+#endif
diff --git a/src/providers/proxy/proxy_hosts.c b/src/providers/proxy/proxy_hosts.c
index d2248293039..2249bf12cd6 100644
--- a/src/providers/proxy/proxy_hosts.c
+++ b/src/providers/proxy/proxy_hosts.c
@@ -704,7 +704,7 @@ proxy_hosts_info(TALLOC_CTX *mem_ctx,
break;
default:
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, EINVAL,
"Invalid filter type");
return reply;
}
@@ -716,11 +716,11 @@ proxy_hosts_info(TALLOC_CTX *mem_ctx,
be_mark_offline(be_ctx);
}
- dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL);
+ dp_reply_std_set(&reply, ret, NULL);
return reply;
}
- dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL);
+ dp_reply_std_set(&reply, EOK, NULL);
return reply;
}
diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c
index b1d0c22ad13..4b4147e0416 100644
--- a/src/providers/proxy/proxy_id.c
+++ b/src/providers/proxy/proxy_id.c
@@ -1748,7 +1748,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
/* Proxy provider does not support security ID lookups. */
if (data->filter_type == BE_FILTER_SECID) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, ENOSYS,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Security lookups are not supported");
return reply;
}
@@ -1767,14 +1767,14 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
case BE_FILTER_IDNUM:
uid = (uid_t) strtouint32(data->filter_value, &endptr, 10);
if (errno || *endptr || (data->filter_value == endptr)) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid attr type");
return reply;
}
ret = get_pw_uid(ctx, domain, uid);
break;
default:
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid filter type");
return reply;
}
@@ -1791,14 +1791,14 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
case BE_FILTER_IDNUM:
gid = (gid_t) strtouint32(data->filter_value, &endptr, 10);
if (errno || *endptr || (data->filter_value == endptr)) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid attr type");
return reply;
}
ret = get_gr_gid(mem_ctx, ctx, sysdb, domain, gid, 0);
break;
default:
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid filter type");
return reply;
}
@@ -1806,12 +1806,12 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
case BE_REQ_INITGROUPS: /* init groups for user */
if (data->filter_type != BE_FILTER_NAME) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid filter type");
return reply;
}
if (ctx->ops.initgroups_dyn == NULL) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV,
+ dp_reply_std_set(&reply, ERR_INTERNAL,
"Initgroups call not supported");
return reply;
}
@@ -1820,13 +1820,13 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
case BE_REQ_NETGROUP:
if (data->filter_type != BE_FILTER_NAME) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid filter type");
return reply;
}
if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL ||
ctx->ops.endnetgrent == NULL) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV,
+ dp_reply_std_set(&reply, ERR_INTERNAL,
"Netgroups are not supported");
return reply;
}
@@ -1838,7 +1838,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
switch (data->filter_type) {
case BE_FILTER_NAME:
if (ctx->ops.getservbyname_r == NULL) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV,
+ dp_reply_std_set(&reply, ERR_INTERNAL,
"Services are not supported");
return reply;
}
@@ -1848,7 +1848,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
break;
case BE_FILTER_IDNUM:
if (ctx->ops.getservbyport_r == NULL) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV,
+ dp_reply_std_set(&reply, ERR_INTERNAL,
"Services are not supported");
return reply;
}
@@ -1860,14 +1860,14 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
if (!ctx->ops.setservent
|| !ctx->ops.getservent_r
|| !ctx->ops.endservent) {
- dp_reply_std_set(&reply, DP_ERR_FATAL, ENODEV,
+ dp_reply_std_set(&reply, ERR_INTERNAL,
"Services are not supported");
return reply;
}
ret = enum_services(ctx, sysdb, domain);
break;
default:
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid filter type");
return reply;
}
@@ -1878,7 +1878,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
DEBUG(SSSDBG_CRIT_FAILURE,
"Unexpected filter type for lookup by cert: %d\n",
data->filter_type);
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Unexpected filter type for lookup by cert");
return reply;
}
@@ -1896,7 +1896,7 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
break;
default: /*fail*/
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, ERR_INVALID_FILTER,
"Invalid filter type");
return reply;
}
@@ -1908,11 +1908,11 @@ proxy_account_info(TALLOC_CTX *mem_ctx,
be_mark_offline(be_ctx);
}
- dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL);
+ dp_reply_std_set(&reply, ret, NULL);
return reply;
}
- dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL);
+ dp_reply_std_set(&reply, EOK, NULL);
return reply;
}
diff --git a/src/providers/proxy/proxy_ipnetworks.c b/src/providers/proxy/proxy_ipnetworks.c
index 73919b8352d..8c07754cde8 100644
--- a/src/providers/proxy/proxy_ipnetworks.c
+++ b/src/providers/proxy/proxy_ipnetworks.c
@@ -565,7 +565,7 @@ proxy_nets_info(TALLOC_CTX *mem_ctx,
break;
default:
- dp_reply_std_set(&reply, DP_ERR_FATAL, EINVAL,
+ dp_reply_std_set(&reply, EINVAL,
"Invalid filter type");
return reply;
}
@@ -577,11 +577,11 @@ proxy_nets_info(TALLOC_CTX *mem_ctx,
be_mark_offline(be_ctx);
}
- dp_reply_std_set(&reply, DP_ERR_FATAL, ret, NULL);
+ dp_reply_std_set(&reply, ret, NULL);
return reply;
}
- dp_reply_std_set(&reply, DP_ERR_OK, EOK, NULL);
+ dp_reply_std_set(&reply, EOK, NULL);
return reply;
}
diff --git a/src/providers/simple/simple_access_check.c b/src/providers/simple/simple_access_check.c
index 8adfb1e263d..b2ddda88e4d 100644
--- a/src/providers/simple/simple_access_check.c
+++ b/src/providers/simple/simple_access_check.c
@@ -369,10 +369,10 @@ static void simple_resolve_group_done(struct tevent_req *subreq)
return;
}
- if (reply->dp_error != DP_ERR_OK) {
+ if (reply->error != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
- "Cannot refresh data from DP: %u,%u: %s\n",
- reply->dp_error, reply->error, reply->message);
+ "Cannot refresh data from DP: %u: %s\n",
+ reply->error, reply->message);
tevent_req_error(req, EIO);
return;
}
diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h
index 22f197b4793..29922ec43c3 100644
--- a/src/responder/common/cache_req/cache_req_private.h
+++ b/src/responder/common/cache_req/cache_req_private.h
@@ -208,9 +208,7 @@ cache_req_well_known_sid_result(TALLOC_CTX *mem_ctx,
bool
cache_req_common_process_dp_reply(struct cache_req *cr,
errno_t ret,
- uint16_t err_maj,
- uint32_t err_min,
- const char *err_msg);
+ uint32_t err);
bool
cache_req_common_dp_recv(struct tevent_req *subreq,
diff --git a/src/responder/common/cache_req/plugins/cache_req_common.c b/src/responder/common/cache_req/plugins/cache_req_common.c
index 00b9383ee4c..e4fbb091c0b 100644
--- a/src/responder/common/cache_req/plugins/cache_req_common.c
+++ b/src/responder/common/cache_req/plugins/cache_req_common.c
@@ -122,9 +122,7 @@ cache_req_well_known_sid_result(TALLOC_CTX *mem_ctx,
bool
cache_req_common_process_dp_reply(struct cache_req *cr,
errno_t ret,
- uint16_t err_maj,
- uint32_t err_min,
- const char *err_msg)
+ uint32_t err)
{
bool bret;
@@ -142,10 +140,10 @@ cache_req_common_process_dp_reply(struct cache_req *cr,
goto done;
}
- if (err_maj) {
+ if (err) {
CACHE_REQ_DEBUG(SSSDBG_IMPORTANT_INFO, cr,
- "Data Provider Error: %u, %u, %s\n",
- (unsigned int)err_maj, (unsigned int)err_min, err_msg);
+ "Data Provider Error: %u, %s\n",
+ (unsigned int)err, sss_strerror(err));
CACHE_REQ_DEBUG(SSSDBG_TRACE_FUNC, cr,
"Due to an error we will return cached data\n");
@@ -163,16 +161,12 @@ bool
cache_req_common_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
- const char *err_msg;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
bool bret;
- /* Use subreq as memory context so err_msg is freed with it. */
- ret = sss_dp_get_account_recv(subreq, subreq, &err_maj, &err_min, &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_get_account_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c b/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c
index ae468b3d24e..3f704d19fdc 100644
--- a/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c
+++ b/src/responder/common/cache_req/plugins/cache_req_enum_ip_hosts.c
@@ -63,15 +63,11 @@ cache_req_enum_host_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
bool bret;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
- const char *err_msg;
- ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min,
- &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_resolver_get_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c b/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c
index e03bf6ad52b..8a6601312ba 100644
--- a/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c
+++ b/src/responder/common/cache_req/plugins/cache_req_enum_ip_networks.c
@@ -63,15 +63,11 @@ cache_req_enum_ip_networks_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
bool bret;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
- const char *err_msg;
- ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min,
- &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_resolver_get_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c
index 1ecfc979868..1e00cb65395 100644
--- a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c
+++ b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_addr.c
@@ -108,15 +108,11 @@ cache_req_ip_host_by_addr_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
bool bret;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
- const char *err_msg;
- ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min,
- &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_resolver_get_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c
index b5f33ee5f78..df5fa91098a 100644
--- a/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c
+++ b/src/responder/common/cache_req/plugins/cache_req_ip_host_by_name.c
@@ -103,15 +103,11 @@ cache_req_ip_host_by_name_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
bool bret;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
- const char *err_msg;
- ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min,
- &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_resolver_get_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c
index 238d104ea38..9f2e37f71ac 100644
--- a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c
+++ b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_addr.c
@@ -108,15 +108,11 @@ cache_req_ip_network_by_addr_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
bool bret;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
- const char *err_msg;
- ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min,
- &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_resolver_get_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c
index c02bc065a1d..0d3ba853ba6 100644
--- a/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c
+++ b/src/responder/common/cache_req/plugins/cache_req_ip_network_by_name.c
@@ -103,15 +103,11 @@ cache_req_ip_network_by_name_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
bool bret;
- uint16_t err_maj;
- uint32_t err_min;
+ uint32_t err;
errno_t ret;
- const char *err_msg;
- ret = sss_dp_resolver_get_recv(subreq, subreq, &err_maj, &err_min,
- &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sss_dp_resolver_get_recv(subreq, subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c b/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c
index d5d39de98d1..889d60ca4c3 100644
--- a/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c
+++ b/src/responder/common/cache_req/plugins/cache_req_ssh_host_id_by_name.c
@@ -89,17 +89,12 @@ static bool
cache_req_host_by_name_dp_recv(struct tevent_req *subreq,
struct cache_req *cr)
{
- const char *err_msg;
- dbus_uint16_t err_maj;
- dbus_uint32_t err_min;
+ dbus_uint32_t err;
errno_t ret;
bool bret;
- /* Use subreq as memory context so err_msg is freed with it. */
- ret = sbus_call_dp_dp_hostHandler_recv(subreq, subreq, &err_maj,
- &err_min, &err_msg);
- bret = cache_req_common_process_dp_reply(cr, ret, err_maj,
- err_min, err_msg);
+ ret = sbus_call_dp_dp_hostHandler_recv(subreq, &err);
+ bret = cache_req_common_process_dp_reply(cr, ret, err);
return bret;
}
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index e2dacc289fa..b17bd6def4b 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -259,9 +259,7 @@ sss_dp_get_account_send(TALLOC_CTX *mem_ctx,
errno_t
sss_dp_get_account_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_error_message);
+ uint32_t *_error);
struct tevent_req *
sss_dp_resolver_get_send(TALLOC_CTX *mem_ctx,
@@ -275,9 +273,7 @@ sss_dp_resolver_get_send(TALLOC_CTX *mem_ctx,
errno_t
sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_error_message);
+ uint32_t *_error);
bool sss_utf8_check(const uint8_t *s, size_t n);
diff --git a/src/responder/common/responder_dp.c b/src/responder/common/responder_dp.c
index 5db22ec9a68..03db215e0ff 100644
--- a/src/responder/common/responder_dp.c
+++ b/src/responder/common/responder_dp.c
@@ -114,9 +114,7 @@ sss_dp_get_account_filter(TALLOC_CTX *mem_ctx,
}
struct sss_dp_get_account_state {
- uint16_t dp_error;
uint32_t error;
- const char *error_message;
};
static void sss_dp_get_account_done(struct tevent_req *subreq);
@@ -210,9 +208,7 @@ static void sss_dp_get_account_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sss_dp_get_account_state);
- ret = sbus_call_dp_dp_getAccountInfo_recv(state, subreq, &state->dp_error,
- &state->error,
- &state->error_message);
+ ret = sbus_call_dp_dp_getAccountInfo_recv(subreq, &state->error);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -226,26 +222,20 @@ static void sss_dp_get_account_done(struct tevent_req *subreq)
errno_t
sss_dp_get_account_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_error_message)
+ uint32_t *_error)
{
struct sss_dp_get_account_state *state;
state = tevent_req_data(req, struct sss_dp_get_account_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- *_dp_error = state->dp_error;
*_error = state->error;
- *_error_message = talloc_steal(mem_ctx, state->error_message);
return EOK;
}
struct sss_dp_resolver_get_state {
- uint16_t dp_error;
uint32_t error;
- const char *error_message;
};
static void sss_dp_resolver_get_done(struct tevent_req *subreq);
@@ -334,10 +324,7 @@ static void sss_dp_resolver_get_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sss_dp_resolver_get_state);
- ret = sbus_call_dp_dp_resolverHandler_recv(state, subreq,
- &state->dp_error,
- &state->error,
- &state->error_message);
+ ret = sbus_call_dp_dp_resolverHandler_recv(subreq, &state->error);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -351,18 +338,14 @@ static void sss_dp_resolver_get_done(struct tevent_req *subreq)
errno_t
sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_error_message)
+ uint32_t *_error)
{
struct sss_dp_resolver_get_state *state;
state = tevent_req_data(req, struct sss_dp_resolver_get_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- *_dp_error = state->dp_error;
*_error = state->error;
- *_error_message = talloc_steal(mem_ctx, state->error_message);
return EOK;
}
diff --git a/src/responder/common/responder_get_domains.c b/src/responder/common/responder_get_domains.c
index f179eb14635..4f9ce00b36f 100644
--- a/src/responder/common/responder_get_domains.c
+++ b/src/responder/common/responder_get_domains.c
@@ -27,9 +27,7 @@
/* ========== Get subdomains for a domain ================= */
struct get_subdomains_state {
- uint16_t dp_error;
uint32_t error;
- const char *error_message;
};
static void get_subdomains_done(struct tevent_req *subreq);
@@ -89,11 +87,9 @@ static void get_subdomains_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct get_subdomains_state);
- ret = sbus_call_dp_dp_getDomains_recv(state, subreq, &state->dp_error,
- &state->error, &state->error_message);
+ ret = sbus_call_dp_dp_getDomains_recv(subreq, &state->error);
talloc_zfree(subreq);
if (ret != EOK) {
- state->dp_error = DP_ERR_FATAL;
state->error = ret;
}
@@ -104,18 +100,14 @@ static void get_subdomains_done(struct tevent_req *subreq)
static errno_t
get_subdomains_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char **_error_message)
+ uint32_t *_error)
{
struct get_subdomains_state *state;
state = tevent_req_data(req, struct get_subdomains_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- *_dp_error = state->dp_error;
*_error = state->error;
- *_error_message = talloc_steal(mem_ctx, state->error_message);
return EOK;
}
@@ -230,11 +222,9 @@ sss_dp_get_domains_process(struct tevent_req *subreq)
struct tevent_req);
struct sss_dp_get_domains_state *state = tevent_req_data(req,
struct sss_dp_get_domains_state);
- uint16_t dp_err;
- uint32_t dp_ret;
- const char *err_msg;
+ uint32_t err;
- ret = get_subdomains_recv(subreq, subreq, &dp_err, &dp_ret, &err_msg);
+ ret = get_subdomains_recv(subreq, subreq, &err);
talloc_zfree(subreq);
if (ret != EOK) {
goto fail;
@@ -630,7 +620,6 @@ errno_t sss_parse_inp_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct sss_dp_get_account_domain_state {
- uint16_t dp_error;
uint32_t error;
const char *domain_name;
};
@@ -738,7 +727,7 @@ static void sss_dp_get_account_domain_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sss_dp_get_account_domain_state);
- ret = sbus_call_dp_dp_getAccountDomain_recv(state, subreq, &state->dp_error,
+ ret = sbus_call_dp_dp_getAccountDomain_recv(state, subreq,
&state->error,
&state->domain_name);
talloc_zfree(subreq);
@@ -749,12 +738,11 @@ static void sss_dp_get_account_domain_done(struct tevent_req *subreq)
return;
}
- if (state->dp_error != DP_ERR_OK) {
+ if (state->error != ERR_OK) {
DEBUG(state->error == ERR_GET_ACCT_DOM_NOT_SUPPORTED ? SSSDBG_TRACE_INTERNAL
: SSSDBG_IMPORTANT_INFO,
- "Data Provider Error: %u, %u [%s]\n",
- (unsigned int)state->dp_error, (unsigned int)state->error,
- sss_strerror(state->error));
+ "Data Provider Error: %u [%s]\n",
+ (unsigned int)state->error, sss_strerror(state->error));
tevent_req_error(req, state->error ? state->error : EIO);
return;
}
diff --git a/src/responder/sudo/sudosrv_dp.c b/src/responder/sudo/sudosrv_dp.c
index 20832b1ea3f..7c8fbd349ea 100644
--- a/src/responder/sudo/sudosrv_dp.c
+++ b/src/responder/sudo/sudosrv_dp.c
@@ -137,9 +137,7 @@ sss_dp_get_sudoers_msg(TALLOC_CTX *mem_ctx,
}
struct sss_dp_get_sudoers_state {
- uint16_t dp_error;
uint32_t error;
- const char *error_message;
};
static void sss_dp_get_sudoers_done(struct tevent_req *subreq);
@@ -209,9 +207,7 @@ static void sss_dp_get_sudoers_done(struct tevent_req *subreq)
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sss_dp_get_sudoers_state);
- ret = sbus_call_dp_dp_sudoHandler_recv(state, subreq, &state->dp_error,
- &state->error,
- &state->error_message);
+ ret = sbus_call_dp_dp_sudoHandler_recv(subreq, &state->error);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -225,18 +221,14 @@ static void sss_dp_get_sudoers_done(struct tevent_req *subreq)
errno_t
sss_dp_get_sudoers_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char ** _error_message)
+ uint32_t *_error)
{
struct sss_dp_get_sudoers_state *state;
state = tevent_req_data(req, struct sss_dp_get_sudoers_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- *_dp_error = state->dp_error;
*_error = state->error;
- *_error_message = talloc_steal(mem_ctx, state->error_message);
return EOK;
}
diff --git a/src/responder/sudo/sudosrv_get_sudorules.c b/src/responder/sudo/sudosrv_get_sudorules.c
index 1bcfc377ace..f364fe63379 100644
--- a/src/responder/sudo/sudosrv_get_sudorules.c
+++ b/src/responder/sudo/sudosrv_get_sudorules.c
@@ -663,30 +663,19 @@ static void sudosrv_refresh_rules_done(struct tevent_req *subreq)
{
struct sudosrv_refresh_rules_state *state;
struct tevent_req *req;
- dbus_uint16_t err_maj;
- dbus_uint32_t err_min;
- const char *err_msg;
+ uint32_t err;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
state = tevent_req_data(req, struct sudosrv_refresh_rules_state);
- ret = sss_dp_get_sudoers_recv(state, subreq, &err_maj, &err_min, &err_msg);
+ ret = sss_dp_get_sudoers_recv(state, subreq, &err);
talloc_zfree(subreq);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to refresh rules [%d]: %s\n",
ret, sss_strerror(ret));
goto done;
- } else if (err_maj != 0 || err_min != 0) {
- DEBUG(SSSDBG_CRIT_FAILURE,
- "Unable to get information from Data Provider, "
- "Error: %u, %u, %s\n",
- (unsigned int)err_maj, (unsigned int)err_min,
- (err_msg == NULL ? "(null)" : err_msg));
- goto done;
- }
-
- if (err_min == ENOENT) {
+ } else if (err == ENOENT) {
DEBUG(SSSDBG_TRACE_INTERNAL,
"Some expired rules were removed from the server, scheduling "
"full refresh out of band\n");
@@ -701,6 +690,13 @@ static void sudosrv_refresh_rules_done(struct tevent_req *subreq)
}
tevent_req_set_callback(subreq, sudosrv_dp_oob_req_done, NULL);
+ } else if (err != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unable to get information from Data Provider, "
+ "Error: %u, %s\n",
+ (unsigned int)err,
+ sss_strerror(err));
+ goto done;
}
ret = EOK;
diff --git a/src/responder/sudo/sudosrv_private.h b/src/responder/sudo/sudosrv_private.h
index 157afaa4492..0537a4a8eae 100644
--- a/src/responder/sudo/sudosrv_private.h
+++ b/src/responder/sudo/sudosrv_private.h
@@ -105,8 +105,6 @@ sss_dp_get_sudoers_send(TALLOC_CTX *mem_ctx,
errno_t
sss_dp_get_sudoers_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t *_dp_error,
- uint32_t *_error,
- const char ** _error_message);
+ uint32_t *_error);
#endif /* _SUDOSRV_PRIVATE_H_ */
diff --git a/src/sss_iface/sbus_sss_arguments.c b/src/sss_iface/sbus_sss_arguments.c
index 14d705ba89e..6af387db7ee 100644
--- a/src/sss_iface/sbus_sss_arguments.c
+++ b/src/sss_iface/sbus_sss_arguments.c
@@ -201,55 +201,6 @@ errno_t _sbus_sss_invoker_write_q
return EOK;
}
-errno_t _sbus_sss_invoker_read_qus
- (TALLOC_CTX *mem_ctx,
- DBusMessageIter *iter,
- struct _sbus_sss_invoker_args_qus *args)
-{
- errno_t ret;
-
- ret = sbus_iterator_read_q(iter, &args->arg0);
- if (ret != EOK) {
- return ret;
- }
-
- ret = sbus_iterator_read_u(iter, &args->arg1);
- if (ret != EOK) {
- return ret;
- }
-
- ret = sbus_iterator_read_s(mem_ctx, iter, &args->arg2);
- if (ret != EOK) {
- return ret;
- }
-
- return EOK;
-}
-
-errno_t _sbus_sss_invoker_write_qus
- (DBusMessageIter *iter,
- struct _sbus_sss_invoker_args_qus *args)
-{
- errno_t ret;
-
- ret = sbus_iterator_write_q(iter, args->arg0);
- if (ret != EOK) {
- return ret;
- }
-
- ret = sbus_iterator_write_u(iter, args->arg1);
- if (ret != EOK) {
- return ret;
- }
-
- ret = sbus_iterator_write_s(iter, args->arg2);
- if (ret != EOK) {
- return ret;
- }
-
- return EOK;
-}
-
errno_t _sbus_sss_invoker_read_s
(TALLOC_CTX *mem_ctx,
DBusMessageIter *iter,
@@ -445,6 +396,45 @@ errno_t _sbus_sss_invoker_write_u
return EOK;
}
+errno_t _sbus_sss_invoker_read_us
+ (TALLOC_CTX *mem_ctx,
+ DBusMessageIter *iter,
+ struct _sbus_sss_invoker_args_us *args)
+{
+ errno_t ret;
+
+ ret = sbus_iterator_read_u(iter, &args->arg0);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sbus_iterator_read_s(mem_ctx, iter, &args->arg1);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return EOK;
+}
+
+errno_t _sbus_sss_invoker_write_us
+ (DBusMessageIter *iter,
+ struct _sbus_sss_invoker_args_us *args)
+{
+ errno_t ret;
+
+ ret = sbus_iterator_write_u(iter, args->arg0);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sbus_iterator_write_s(iter, args->arg1);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return EOK;
+}
+
errno_t _sbus_sss_invoker_read_usq
(TALLOC_CTX *mem_ctx,
DBusMessageIter *iter,
diff --git a/src/sss_iface/sbus_sss_arguments.h b/src/sss_iface/sbus_sss_arguments.h
index 41067aae6c9..1e561b10ee4 100644
--- a/src/sss_iface/sbus_sss_arguments.h
+++ b/src/sss_iface/sbus_sss_arguments.h
@@ -118,23 +118,6 @@ _sbus_sss_invoker_write_q
(DBusMessageIter *iter,
struct _sbus_sss_invoker_args_q *args);
-struct _sbus_sss_invoker_args_qus {
- uint16_t arg0;
- uint32_t arg1;
- const char * arg2;
-};
-
-errno_t
-_sbus_sss_invoker_read_qus
- (TALLOC_CTX *mem_ctx,
- DBusMessageIter *iter,
- struct _sbus_sss_invoker_args_qus *args);
-
-errno_t
-_sbus_sss_invoker_write_qus
- (DBusMessageIter *iter,
- struct _sbus_sss_invoker_args_qus *args);
-
struct _sbus_sss_invoker_args_s {
const char * arg0;
};
@@ -215,6 +198,22 @@ _sbus_sss_invoker_write_u
(DBusMessageIter *iter,
struct _sbus_sss_invoker_args_u *args);
+struct _sbus_sss_invoker_args_us {
+ uint32_t arg0;
+ const char * arg1;
+};
+
+errno_t
+_sbus_sss_invoker_read_us
+ (TALLOC_CTX *mem_ctx,
+ DBusMessageIter *iter,
+ struct _sbus_sss_invoker_args_us *args);
+
+errno_t
+_sbus_sss_invoker_write_us
+ (DBusMessageIter *iter,
+ struct _sbus_sss_invoker_args_us *args);
+
struct _sbus_sss_invoker_args_usq {
uint32_t arg0;
const char * arg1;
diff --git a/src/sss_iface/sbus_sss_client_async.c b/src/sss_iface/sbus_sss_client_async.c
index 1391d8de0ea..45f8c1d7bbb 100644
--- a/src/sss_iface/sbus_sss_client_async.c
+++ b/src/sss_iface/sbus_sss_client_async.c
@@ -212,30 +212,30 @@ sbus_method_in_pam_data_out_pam_response_recv
return EOK;
}
-struct sbus_method_in_raw_out_qus_state {
- struct _sbus_sss_invoker_args_qus *out;
+struct sbus_method_in_raw_out_u_state {
+ struct _sbus_sss_invoker_args_u *out;
};
-static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq);
+static void sbus_method_in_raw_out_u_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_raw_out_qus_send
+sbus_method_in_raw_out_u_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
DBusMessage *raw_message)
{
- struct sbus_method_in_raw_out_qus_state *state;
+ struct sbus_method_in_raw_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_raw_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_raw_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -254,7 +254,7 @@ sbus_method_in_raw_out_qus_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_raw_out_qus_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_raw_out_u_done, req);
ret = EAGAIN;
@@ -267,15 +267,15 @@ sbus_method_in_raw_out_qus_send
return req;
}
-static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq)
+static void sbus_method_in_raw_out_u_done(struct tevent_req *subreq)
{
- struct sbus_method_in_raw_out_qus_state *state;
+ struct sbus_method_in_raw_out_u_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_raw_out_qus_state);
+ state = tevent_req_data(req, struct sbus_method_in_raw_out_u_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -284,7 +284,7 @@ static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -295,21 +295,16 @@ static void sbus_method_in_raw_out_qus_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_raw_out_qus_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _arg0,
- uint32_t* _arg1,
- const char ** _arg2)
+sbus_method_in_raw_out_u_recv
+ (struct tevent_req *req,
+ uint32_t* _arg0)
{
- struct sbus_method_in_raw_out_qus_state *state;
- state = tevent_req_data(req, struct sbus_method_in_raw_out_qus_state);
+ struct sbus_method_in_raw_out_u_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_raw_out_u_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*_arg0 = state->out->arg0;
- *_arg1 = state->out->arg1;
- *_arg2 = talloc_steal(mem_ctx, state->out->arg2);
return EOK;
}
@@ -521,15 +516,15 @@ sbus_method_in_s_out_b_recv
return EOK;
}
-struct sbus_method_in_s_out_qus_state {
+struct sbus_method_in_s_out_s_state {
struct _sbus_sss_invoker_args_s in;
- struct _sbus_sss_invoker_args_qus *out;
+ struct _sbus_sss_invoker_args_s *out;
};
-static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq);
+static void sbus_method_in_s_out_s_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_s_out_qus_send
+sbus_method_in_s_out_s_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
sbus_invoker_keygen keygen,
@@ -539,18 +534,18 @@ sbus_method_in_s_out_qus_send
const char *method,
const char * arg0)
{
- struct sbus_method_in_s_out_qus_state *state;
+ struct sbus_method_in_s_out_s_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_s_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_s);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -569,7 +564,7 @@ sbus_method_in_s_out_qus_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_s_out_qus_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_s_out_s_done, req);
ret = EAGAIN;
@@ -582,15 +577,15 @@ sbus_method_in_s_out_qus_send
return req;
}
-static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq)
+static void sbus_method_in_s_out_s_done(struct tevent_req *subreq)
{
- struct sbus_method_in_s_out_qus_state *state;
+ struct sbus_method_in_s_out_s_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_s_out_qus_state);
+ state = tevent_req_data(req, struct sbus_method_in_s_out_s_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -599,7 +594,7 @@ static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_s, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -610,34 +605,30 @@ static void sbus_method_in_s_out_qus_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_s_out_qus_recv
+sbus_method_in_s_out_s_recv
(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t* _arg0,
- uint32_t* _arg1,
- const char ** _arg2)
+ const char ** _arg0)
{
- struct sbus_method_in_s_out_qus_state *state;
- state = tevent_req_data(req, struct sbus_method_in_s_out_qus_state);
+ struct sbus_method_in_s_out_s_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_s_out_s_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- *_arg0 = state->out->arg0;
- *_arg1 = state->out->arg1;
- *_arg2 = talloc_steal(mem_ctx, state->out->arg2);
+ *_arg0 = talloc_steal(mem_ctx, state->out->arg0);
return EOK;
}
-struct sbus_method_in_s_out_s_state {
+struct sbus_method_in_s_out_u_state {
struct _sbus_sss_invoker_args_s in;
- struct _sbus_sss_invoker_args_s *out;
+ struct _sbus_sss_invoker_args_u *out;
};
-static void sbus_method_in_s_out_s_done(struct tevent_req *subreq);
+static void sbus_method_in_s_out_u_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_s_out_s_send
+sbus_method_in_s_out_u_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
sbus_invoker_keygen keygen,
@@ -647,18 +638,18 @@ sbus_method_in_s_out_s_send
const char *method,
const char * arg0)
{
- struct sbus_method_in_s_out_s_state *state;
+ struct sbus_method_in_s_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_s_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_s_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_s);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -677,7 +668,7 @@ sbus_method_in_s_out_s_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_s_out_s_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_s_out_u_done, req);
ret = EAGAIN;
@@ -690,15 +681,15 @@ sbus_method_in_s_out_s_send
return req;
}
-static void sbus_method_in_s_out_s_done(struct tevent_req *subreq)
+static void sbus_method_in_s_out_u_done(struct tevent_req *subreq)
{
- struct sbus_method_in_s_out_s_state *state;
+ struct sbus_method_in_s_out_u_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_s_out_s_state);
+ state = tevent_req_data(req, struct sbus_method_in_s_out_u_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -707,7 +698,7 @@ static void sbus_method_in_s_out_s_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_s, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -718,17 +709,16 @@ static void sbus_method_in_s_out_s_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_s_out_s_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- const char ** _arg0)
+sbus_method_in_s_out_u_recv
+ (struct tevent_req *req,
+ uint32_t* _arg0)
{
- struct sbus_method_in_s_out_s_state *state;
- state = tevent_req_data(req, struct sbus_method_in_s_out_s_state);
+ struct sbus_method_in_s_out_u_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_s_out_u_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
- *_arg0 = talloc_steal(mem_ctx, state->out->arg0);
+ *_arg0 = state->out->arg0;
return EOK;
}
@@ -1182,15 +1172,15 @@ sbus_method_in_ussu_out__recv
return EOK;
}
-struct sbus_method_in_ussu_out_qus_state {
+struct sbus_method_in_ussu_out_u_state {
struct _sbus_sss_invoker_args_ussu in;
- struct _sbus_sss_invoker_args_qus *out;
+ struct _sbus_sss_invoker_args_u *out;
};
-static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq);
+static void sbus_method_in_ussu_out_u_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_ussu_out_qus_send
+sbus_method_in_ussu_out_u_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
sbus_invoker_keygen keygen,
@@ -1203,18 +1193,18 @@ sbus_method_in_ussu_out_qus_send
const char * arg2,
uint32_t arg3)
{
- struct sbus_method_in_ussu_out_qus_state *state;
+ struct sbus_method_in_ussu_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_ussu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_ussu_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -1236,7 +1226,7 @@ sbus_method_in_ussu_out_qus_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_ussu_out_qus_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_ussu_out_u_done, req);
ret = EAGAIN;
@@ -1249,15 +1239,15 @@ sbus_method_in_ussu_out_qus_send
return req;
}
-static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq)
+static void sbus_method_in_ussu_out_u_done(struct tevent_req *subreq)
{
- struct sbus_method_in_ussu_out_qus_state *state;
+ struct sbus_method_in_ussu_out_u_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_ussu_out_qus_state);
+ state = tevent_req_data(req, struct sbus_method_in_ussu_out_u_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -1266,7 +1256,7 @@ static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1277,21 +1267,16 @@ static void sbus_method_in_ussu_out_qus_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_ussu_out_qus_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _arg0,
- uint32_t* _arg1,
- const char ** _arg2)
+sbus_method_in_ussu_out_u_recv
+ (struct tevent_req *req,
+ uint32_t* _arg0)
{
- struct sbus_method_in_ussu_out_qus_state *state;
- state = tevent_req_data(req, struct sbus_method_in_ussu_out_qus_state);
+ struct sbus_method_in_ussu_out_u_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_ussu_out_u_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*_arg0 = state->out->arg0;
- *_arg1 = state->out->arg1;
- *_arg2 = talloc_steal(mem_ctx, state->out->arg2);
return EOK;
}
@@ -1382,15 +1367,15 @@ sbus_method_in_usu_out__recv
return EOK;
}
-struct sbus_method_in_uusssu_out_qus_state {
+struct sbus_method_in_uusssu_out_u_state {
struct _sbus_sss_invoker_args_uusssu in;
- struct _sbus_sss_invoker_args_qus *out;
+ struct _sbus_sss_invoker_args_u *out;
};
-static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq);
+static void sbus_method_in_uusssu_out_u_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_uusssu_out_qus_send
+sbus_method_in_uusssu_out_u_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
sbus_invoker_keygen keygen,
@@ -1405,18 +1390,18 @@ sbus_method_in_uusssu_out_qus_send
const char * arg4,
uint32_t arg5)
{
- struct sbus_method_in_uusssu_out_qus_state *state;
+ struct sbus_method_in_uusssu_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusssu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusssu_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -1440,7 +1425,7 @@ sbus_method_in_uusssu_out_qus_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_uusssu_out_qus_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_uusssu_out_u_done, req);
ret = EAGAIN;
@@ -1453,15 +1438,15 @@ sbus_method_in_uusssu_out_qus_send
return req;
}
-static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq)
+static void sbus_method_in_uusssu_out_u_done(struct tevent_req *subreq)
{
- struct sbus_method_in_uusssu_out_qus_state *state;
+ struct sbus_method_in_uusssu_out_u_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_uusssu_out_qus_state);
+ state = tevent_req_data(req, struct sbus_method_in_uusssu_out_u_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -1470,7 +1455,7 @@ static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1481,34 +1466,29 @@ static void sbus_method_in_uusssu_out_qus_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_uusssu_out_qus_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _arg0,
- uint32_t* _arg1,
- const char ** _arg2)
+sbus_method_in_uusssu_out_u_recv
+ (struct tevent_req *req,
+ uint32_t* _arg0)
{
- struct sbus_method_in_uusssu_out_qus_state *state;
- state = tevent_req_data(req, struct sbus_method_in_uusssu_out_qus_state);
+ struct sbus_method_in_uusssu_out_u_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_uusssu_out_u_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*_arg0 = state->out->arg0;
- *_arg1 = state->out->arg1;
- *_arg2 = talloc_steal(mem_ctx, state->out->arg2);
return EOK;
}
-struct sbus_method_in_uusu_out_qus_state {
+struct sbus_method_in_uusu_out_us_state {
struct _sbus_sss_invoker_args_uusu in;
- struct _sbus_sss_invoker_args_qus *out;
+ struct _sbus_sss_invoker_args_us *out;
};
-static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq);
+static void sbus_method_in_uusu_out_us_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_uusu_out_qus_send
+sbus_method_in_uusu_out_us_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
sbus_invoker_keygen keygen,
@@ -1521,18 +1501,18 @@ sbus_method_in_uusu_out_qus_send
const char * arg2,
uint32_t arg3)
{
- struct sbus_method_in_uusu_out_qus_state *state;
+ struct sbus_method_in_uusu_out_us_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uusu_out_us_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_us);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -1554,7 +1534,7 @@ sbus_method_in_uusu_out_qus_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_uusu_out_qus_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_uusu_out_us_done, req);
ret = EAGAIN;
@@ -1567,15 +1547,15 @@ sbus_method_in_uusu_out_qus_send
return req;
}
-static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq)
+static void sbus_method_in_uusu_out_us_done(struct tevent_req *subreq)
{
- struct sbus_method_in_uusu_out_qus_state *state;
+ struct sbus_method_in_uusu_out_us_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_uusu_out_qus_state);
+ state = tevent_req_data(req, struct sbus_method_in_uusu_out_us_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -1584,7 +1564,7 @@ static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_us, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1595,34 +1575,32 @@ static void sbus_method_in_uusu_out_qus_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_uusu_out_qus_recv
+sbus_method_in_uusu_out_us_recv
(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t* _arg0,
- uint32_t* _arg1,
- const char ** _arg2)
+ uint32_t* _arg0,
+ const char ** _arg1)
{
- struct sbus_method_in_uusu_out_qus_state *state;
- state = tevent_req_data(req, struct sbus_method_in_uusu_out_qus_state);
+ struct sbus_method_in_uusu_out_us_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_uusu_out_us_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*_arg0 = state->out->arg0;
- *_arg1 = state->out->arg1;
- *_arg2 = talloc_steal(mem_ctx, state->out->arg2);
+ *_arg1 = talloc_steal(mem_ctx, state->out->arg1);
return EOK;
}
-struct sbus_method_in_uuusu_out_qus_state {
+struct sbus_method_in_uuusu_out_u_state {
struct _sbus_sss_invoker_args_uuusu in;
- struct _sbus_sss_invoker_args_qus *out;
+ struct _sbus_sss_invoker_args_u *out;
};
-static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq);
+static void sbus_method_in_uuusu_out_u_done(struct tevent_req *subreq);
static struct tevent_req *
-sbus_method_in_uuusu_out_qus_send
+sbus_method_in_uuusu_out_u_send
(TALLOC_CTX *mem_ctx,
struct sbus_connection *conn,
sbus_invoker_keygen keygen,
@@ -1636,18 +1614,18 @@ sbus_method_in_uuusu_out_qus_send
const char * arg3,
uint32_t arg4)
{
- struct sbus_method_in_uuusu_out_qus_state *state;
+ struct sbus_method_in_uuusu_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uuusu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct sbus_method_in_uuusu_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
}
- state->out = talloc_zero(state, struct _sbus_sss_invoker_args_qus);
+ state->out = talloc_zero(state, struct _sbus_sss_invoker_args_u);
if (state->out == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to allocate space for output parameters!\n");
@@ -1670,7 +1648,7 @@ sbus_method_in_uuusu_out_qus_send
goto done;
}
- tevent_req_set_callback(subreq, sbus_method_in_uuusu_out_qus_done, req);
+ tevent_req_set_callback(subreq, sbus_method_in_uuusu_out_u_done, req);
ret = EAGAIN;
@@ -1683,15 +1661,15 @@ sbus_method_in_uuusu_out_qus_send
return req;
}
-static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq)
+static void sbus_method_in_uuusu_out_u_done(struct tevent_req *subreq)
{
- struct sbus_method_in_uuusu_out_qus_state *state;
+ struct sbus_method_in_uuusu_out_u_state *state;
struct tevent_req *req;
DBusMessage *reply;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct sbus_method_in_uuusu_out_qus_state);
+ state = tevent_req_data(req, struct sbus_method_in_uuusu_out_u_state);
ret = sbus_call_method_recv(state, subreq, &reply);
talloc_zfree(subreq);
@@ -1700,7 +1678,7 @@ static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq)
return;
}
- ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_qus, state->out);
+ ret = sbus_read_output(state->out, reply, (sbus_invoker_reader_fn)_sbus_sss_invoker_read_u, state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1711,21 +1689,16 @@ static void sbus_method_in_uuusu_out_qus_done(struct tevent_req *subreq)
}
static errno_t
-sbus_method_in_uuusu_out_qus_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _arg0,
- uint32_t* _arg1,
- const char ** _arg2)
+sbus_method_in_uuusu_out_u_recv
+ (struct tevent_req *req,
+ uint32_t* _arg0)
{
- struct sbus_method_in_uuusu_out_qus_state *state;
- state = tevent_req_data(req, struct sbus_method_in_uuusu_out_qus_state);
+ struct sbus_method_in_uuusu_out_u_state *state;
+ state = tevent_req_data(req, struct sbus_method_in_uuusu_out_u_state);
TEVENT_REQ_RETURN_ON_ERROR(req);
*_arg0 = state->out->arg0;
- *_arg1 = state->out->arg1;
- *_arg2 = talloc_steal(mem_ctx, state->out->arg2);
return EOK;
}
@@ -1967,7 +1940,7 @@ sbus_call_dp_dp_getAccountDomain_send
const char * arg_filter,
uint32_t arg_cli_id)
{
- return sbus_method_in_uusu_out_qus_send(mem_ctx, conn, _sbus_sss_key_uusu_0_1_2,
+ return sbus_method_in_uusu_out_us_send(mem_ctx, conn, _sbus_sss_key_uusu_0_1_2,
busname, object_path, "sssd.dataprovider", "getAccountDomain", arg_dp_flags, arg_entry_type, arg_filter, arg_cli_id);
}
@@ -1975,11 +1948,10 @@ errno_t
sbus_call_dp_dp_getAccountDomain_recv
(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t* _dp_error,
uint32_t* _error,
const char ** _domain_name)
{
- return sbus_method_in_uusu_out_qus_recv(mem_ctx, req, _dp_error, _error, _domain_name);
+ return sbus_method_in_uusu_out_us_recv(mem_ctx, req, _error, _domain_name);
}
struct tevent_req *
@@ -1995,19 +1967,16 @@ sbus_call_dp_dp_getAccountInfo_send
const char * arg_extra,
uint32_t arg_cli_id)
{
- return sbus_method_in_uusssu_out_qus_send(mem_ctx, conn, _sbus_sss_key_uusssu_0_1_2_3_4,
+ return sbus_method_in_uusssu_out_u_send(mem_ctx, conn, _sbus_sss_key_uusssu_0_1_2_3_4,
busname, object_path, "sssd.dataprovider", "getAccountInfo", arg_dp_flags, arg_entry_type, arg_filter, arg_domain, arg_extra, arg_cli_id);
}
errno_t
sbus_call_dp_dp_getAccountInfo_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message)
+ (struct tevent_req *req,
+ uint32_t* _error)
{
- return sbus_method_in_uusssu_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message);
+ return sbus_method_in_uusssu_out_u_recv(req, _error);
}
struct tevent_req *
@@ -2018,19 +1987,16 @@ sbus_call_dp_dp_getDomains_send
const char *object_path,
const char * arg_domain_hint)
{
- return sbus_method_in_s_out_qus_send(mem_ctx, conn, _sbus_sss_key_s_0,
+ return sbus_method_in_s_out_u_send(mem_ctx, conn, _sbus_sss_key_s_0,
busname, object_path, "sssd.dataprovider", "getDomains", arg_domain_hint);
}
errno_t
sbus_call_dp_dp_getDomains_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message)
+ (struct tevent_req *req,
+ uint32_t* _error)
{
- return sbus_method_in_s_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message);
+ return sbus_method_in_s_out_u_recv(req, _error);
}
struct tevent_req *
@@ -2044,19 +2010,16 @@ sbus_call_dp_dp_hostHandler_send
const char * arg_alias,
uint32_t arg_cli_id)
{
- return sbus_method_in_ussu_out_qus_send(mem_ctx, conn, _sbus_sss_key_ussu_0_1,
+ return sbus_method_in_ussu_out_u_send(mem_ctx, conn, _sbus_sss_key_ussu_0_1,
busname, object_path, "sssd.dataprovider", "hostHandler", arg_dp_flags, arg_name, arg_alias, arg_cli_id);
}
errno_t
sbus_call_dp_dp_hostHandler_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message)
+ (struct tevent_req *req,
+ uint32_t* _error)
{
- return sbus_method_in_ussu_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message);
+ return sbus_method_in_ussu_out_u_recv(req, _error);
}
struct tevent_req *
@@ -2092,19 +2055,16 @@ sbus_call_dp_dp_resolverHandler_send
const char * arg_filter_value,
uint32_t arg_cli_id)
{
- return sbus_method_in_uuusu_out_qus_send(mem_ctx, conn, _sbus_sss_key_uuusu_0_1_2_3,
+ return sbus_method_in_uuusu_out_u_send(mem_ctx, conn, _sbus_sss_key_uuusu_0_1_2_3,
busname, object_path, "sssd.dataprovider", "resolverHandler", arg_dp_flags, arg_entry_type, arg_filter_type, arg_filter_value, arg_cli_id);
}
errno_t
sbus_call_dp_dp_resolverHandler_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message)
+ (struct tevent_req *req,
+ uint32_t* _error)
{
- return sbus_method_in_uuusu_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message);
+ return sbus_method_in_uuusu_out_u_recv(req, _error);
}
struct tevent_req *
@@ -2113,18 +2073,15 @@ sbus_call_dp_dp_sudoHandler_send
struct sbus_connection *conn,
DBusMessage *raw_message)
{
- return sbus_method_in_raw_out_qus_send(mem_ctx, conn, raw_message);
+ return sbus_method_in_raw_out_u_send(mem_ctx, conn, raw_message);
}
errno_t
sbus_call_dp_dp_sudoHandler_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message)
+ (struct tevent_req *req,
+ uint32_t* _error)
{
- return sbus_method_in_raw_out_qus_recv(mem_ctx, req, _dp_error, _error, _error_message);
+ return sbus_method_in_raw_out_u_recv(req, _error);
}
struct tevent_req *
diff --git a/src/sss_iface/sbus_sss_client_async.h b/src/sss_iface/sbus_sss_client_async.h
index d400cb4040f..3d4bf800d35 100644
--- a/src/sss_iface/sbus_sss_client_async.h
+++ b/src/sss_iface/sbus_sss_client_async.h
@@ -192,7 +192,6 @@ errno_t
sbus_call_dp_dp_getAccountDomain_recv
(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- uint16_t* _dp_error,
uint32_t* _error,
const char ** _domain_name);
@@ -211,11 +210,8 @@ sbus_call_dp_dp_getAccountInfo_send
errno_t
sbus_call_dp_dp_getAccountInfo_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message);
+ (struct tevent_req *req,
+ uint32_t* _error);
struct tevent_req *
sbus_call_dp_dp_getDomains_send
@@ -227,11 +223,8 @@ sbus_call_dp_dp_getDomains_send
errno_t
sbus_call_dp_dp_getDomains_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message);
+ (struct tevent_req *req,
+ uint32_t* _error);
struct tevent_req *
sbus_call_dp_dp_hostHandler_send
@@ -246,11 +239,8 @@ sbus_call_dp_dp_hostHandler_send
errno_t
sbus_call_dp_dp_hostHandler_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message);
+ (struct tevent_req *req,
+ uint32_t* _error);
struct tevent_req *
sbus_call_dp_dp_pamHandler_send
@@ -280,11 +270,8 @@ sbus_call_dp_dp_resolverHandler_send
errno_t
sbus_call_dp_dp_resolverHandler_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message);
+ (struct tevent_req *req,
+ uint32_t* _error);
struct tevent_req *
sbus_call_dp_dp_sudoHandler_send
@@ -294,11 +281,8 @@ sbus_call_dp_dp_sudoHandler_send
errno_t
sbus_call_dp_dp_sudoHandler_recv
- (TALLOC_CTX *mem_ctx,
- struct tevent_req *req,
- uint16_t* _dp_error,
- uint32_t* _error,
- const char ** _error_message);
+ (struct tevent_req *req,
+ uint32_t* _error);
struct tevent_req *
sbus_call_monitor_RegisterService_send
diff --git a/src/sss_iface/sbus_sss_interface.h b/src/sss_iface/sbus_sss_interface.h
index 138ced6276d..ea8587fc6ae 100644
--- a/src/sss_iface/sbus_sss_interface.h
+++ b/src/sss_iface/sbus_sss_interface.h
@@ -497,88 +497,88 @@
/* Method: sssd.dataprovider.getAccountDomain */
#define SBUS_METHOD_SYNC_sssd_dataprovider_getAccountDomain(handler, data) ({ \
- SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, uint32_t, uint32_t*, const char **); \
sbus_method_sync("getAccountDomain", \
&_sbus_sss_args_sssd_dataprovider_getAccountDomain, \
NULL, \
- _sbus_sss_invoke_in_uusu_out_qus_send, \
+ _sbus_sss_invoke_in_uusu_out_us_send, \
_sbus_sss_key_uusu_0_1_2, \
(handler), (data)); \
})
#define SBUS_METHOD_ASYNC_sssd_dataprovider_getAccountDomain(handler_send, handler_recv, data) ({ \
SBUS_CHECK_SEND((handler_send), (data), uint32_t, uint32_t, const char *, uint32_t); \
- SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_RECV((handler_recv), uint32_t*, const char **); \
sbus_method_async("getAccountDomain", \
&_sbus_sss_args_sssd_dataprovider_getAccountDomain, \
NULL, \
- _sbus_sss_invoke_in_uusu_out_qus_send, \
+ _sbus_sss_invoke_in_uusu_out_us_send, \
_sbus_sss_key_uusu_0_1_2, \
(handler_send), (handler_recv), (data)); \
})
/* Method: sssd.dataprovider.getAccountInfo */
#define SBUS_METHOD_SYNC_sssd_dataprovider_getAccountInfo(handler, data) ({ \
- SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint32_t*); \
sbus_method_sync("getAccountInfo", \
&_sbus_sss_args_sssd_dataprovider_getAccountInfo, \
NULL, \
- _sbus_sss_invoke_in_uusssu_out_qus_send, \
+ _sbus_sss_invoke_in_uusssu_out_u_send, \
_sbus_sss_key_uusssu_0_1_2_3_4, \
(handler), (data)); \
})
#define SBUS_METHOD_ASYNC_sssd_dataprovider_getAccountInfo(handler_send, handler_recv, data) ({ \
SBUS_CHECK_SEND((handler_send), (data), uint32_t, uint32_t, const char *, const char *, const char *, uint32_t); \
- SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_RECV((handler_recv), uint32_t*); \
sbus_method_async("getAccountInfo", \
&_sbus_sss_args_sssd_dataprovider_getAccountInfo, \
NULL, \
- _sbus_sss_invoke_in_uusssu_out_qus_send, \
+ _sbus_sss_invoke_in_uusssu_out_u_send, \
_sbus_sss_key_uusssu_0_1_2_3_4, \
(handler_send), (handler_recv), (data)); \
})
/* Method: sssd.dataprovider.getDomains */
#define SBUS_METHOD_SYNC_sssd_dataprovider_getDomains(handler, data) ({ \
- SBUS_CHECK_SYNC((handler), (data), const char *, uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_SYNC((handler), (data), const char *, uint32_t*); \
sbus_method_sync("getDomains", \
&_sbus_sss_args_sssd_dataprovider_getDomains, \
NULL, \
- _sbus_sss_invoke_in_s_out_qus_send, \
+ _sbus_sss_invoke_in_s_out_u_send, \
_sbus_sss_key_s_0, \
(handler), (data)); \
})
#define SBUS_METHOD_ASYNC_sssd_dataprovider_getDomains(handler_send, handler_recv, data) ({ \
SBUS_CHECK_SEND((handler_send), (data), const char *); \
- SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_RECV((handler_recv), uint32_t*); \
sbus_method_async("getDomains", \
&_sbus_sss_args_sssd_dataprovider_getDomains, \
NULL, \
- _sbus_sss_invoke_in_s_out_qus_send, \
+ _sbus_sss_invoke_in_s_out_u_send, \
_sbus_sss_key_s_0, \
(handler_send), (handler_recv), (data)); \
})
/* Method: sssd.dataprovider.hostHandler */
#define SBUS_METHOD_SYNC_sssd_dataprovider_hostHandler(handler, data) ({ \
- SBUS_CHECK_SYNC((handler), (data), uint32_t, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_SYNC((handler), (data), uint32_t, const char *, const char *, uint32_t, uint32_t*); \
sbus_method_sync("hostHandler", \
&_sbus_sss_args_sssd_dataprovider_hostHandler, \
NULL, \
- _sbus_sss_invoke_in_ussu_out_qus_send, \
+ _sbus_sss_invoke_in_ussu_out_u_send, \
_sbus_sss_key_ussu_0_1, \
(handler), (data)); \
})
#define SBUS_METHOD_ASYNC_sssd_dataprovider_hostHandler(handler_send, handler_recv, data) ({ \
SBUS_CHECK_SEND((handler_send), (data), uint32_t, const char *, const char *, uint32_t); \
- SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_RECV((handler_recv), uint32_t*); \
sbus_method_async("hostHandler", \
&_sbus_sss_args_sssd_dataprovider_hostHandler, \
NULL, \
- _sbus_sss_invoke_in_ussu_out_qus_send, \
+ _sbus_sss_invoke_in_ussu_out_u_send, \
_sbus_sss_key_ussu_0_1, \
(handler_send), (handler_recv), (data)); \
})
@@ -607,44 +607,44 @@
/* Method: sssd.dataprovider.resolverHandler */
#define SBUS_METHOD_SYNC_sssd_dataprovider_resolverHandler(handler, data) ({ \
- SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_SYNC((handler), (data), uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint32_t*); \
sbus_method_sync("resolverHandler", \
&_sbus_sss_args_sssd_dataprovider_resolverHandler, \
NULL, \
- _sbus_sss_invoke_in_uuusu_out_qus_send, \
+ _sbus_sss_invoke_in_uuusu_out_u_send, \
_sbus_sss_key_uuusu_0_1_2_3, \
(handler), (data)); \
})
#define SBUS_METHOD_ASYNC_sssd_dataprovider_resolverHandler(handler_send, handler_recv, data) ({ \
SBUS_CHECK_SEND((handler_send), (data), uint32_t, uint32_t, uint32_t, const char *, uint32_t); \
- SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_RECV((handler_recv), uint32_t*); \
sbus_method_async("resolverHandler", \
&_sbus_sss_args_sssd_dataprovider_resolverHandler, \
NULL, \
- _sbus_sss_invoke_in_uuusu_out_qus_send, \
+ _sbus_sss_invoke_in_uuusu_out_u_send, \
_sbus_sss_key_uuusu_0_1_2_3, \
(handler_send), (handler_recv), (data)); \
})
/* Method: sssd.dataprovider.sudoHandler */
#define SBUS_METHOD_SYNC_sssd_dataprovider_sudoHandler(handler, data) ({ \
- SBUS_CHECK_SYNC((handler), (data), DBusMessageIter *, uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_SYNC((handler), (data), DBusMessageIter *, uint32_t*); \
sbus_method_sync("sudoHandler", \
&_sbus_sss_args_sssd_dataprovider_sudoHandler, \
NULL, \
- _sbus_sss_invoke_in_raw_out_qus_send, \
+ _sbus_sss_invoke_in_raw_out_u_send, \
NULL, \
(handler), (data)); \
})
#define SBUS_METHOD_ASYNC_sssd_dataprovider_sudoHandler(handler_send, handler_recv, data) ({ \
SBUS_CHECK_SEND((handler_send), (data), DBusMessageIter *); \
- SBUS_CHECK_RECV((handler_recv), uint16_t*, uint32_t*, const char **); \
+ SBUS_CHECK_RECV((handler_recv), uint32_t*); \
sbus_method_async("sudoHandler", \
&_sbus_sss_args_sssd_dataprovider_sudoHandler, \
NULL, \
- _sbus_sss_invoke_in_raw_out_qus_send, \
+ _sbus_sss_invoke_in_raw_out_u_send, \
NULL, \
(handler_send), (handler_recv), (data)); \
})
diff --git a/src/sss_iface/sbus_sss_invokers.c b/src/sss_iface/sbus_sss_invokers.c
index ef035241d14..c0a609636c1 100644
--- a/src/sss_iface/sbus_sss_invokers.c
+++ b/src/sss_iface/sbus_sss_invokers.c
@@ -561,14 +561,14 @@ static void _sbus_sss_invoke_in_pam_data_out_pam_response_done(struct tevent_req
return;
}
-struct _sbus_sss_invoke_in_raw_out_qus_state {
- struct _sbus_sss_invoker_args_qus out;
+struct _sbus_sss_invoke_in_raw_out_u_state {
+ struct _sbus_sss_invoker_args_u out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, DBusMessageIter *, uint16_t*, uint32_t*, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, DBusMessageIter *, uint32_t*);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, DBusMessageIter *);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*);
} handler;
struct sbus_request *sbus_req;
@@ -577,18 +577,18 @@ struct _sbus_sss_invoke_in_raw_out_qus_state {
};
static void
-_sbus_sss_invoke_in_raw_out_qus_step
+_sbus_sss_invoke_in_raw_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_raw_out_qus_done
+_sbus_sss_invoke_in_raw_out_u_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_raw_out_qus_send
+_sbus_sss_invoke_in_raw_out_u_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -598,12 +598,12 @@ _sbus_sss_invoke_in_raw_out_qus_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_raw_out_qus_state *state;
+ struct _sbus_sss_invoke_in_raw_out_u_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_raw_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_raw_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -619,7 +619,7 @@ _sbus_sss_invoke_in_raw_out_qus_send
state->read_iterator = read_iterator;
state->write_iterator = write_iterator;
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_raw_out_qus_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_raw_out_u_step, req);
if (ret != EOK) {
goto done;
}
@@ -644,19 +644,19 @@ _sbus_sss_invoke_in_raw_out_qus_send
return req;
}
-static void _sbus_sss_invoke_in_raw_out_qus_step
+static void _sbus_sss_invoke_in_raw_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_raw_out_qus_state *state;
+ struct _sbus_sss_invoke_in_raw_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_u_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -666,12 +666,12 @@ static void _sbus_sss_invoke_in_raw_out_qus_step
goto done;
}
- ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->read_iterator, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->read_iterator, &state->out.arg0);
if (ret != EOK) {
goto done;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -687,7 +687,7 @@ static void _sbus_sss_invoke_in_raw_out_qus_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_raw_out_qus_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_raw_out_u_done, req);
ret = EAGAIN;
goto done;
}
@@ -702,23 +702,23 @@ static void _sbus_sss_invoke_in_raw_out_qus_step
}
}
-static void _sbus_sss_invoke_in_raw_out_qus_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_raw_out_u_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_raw_out_qus_state *state;
+ struct _sbus_sss_invoke_in_raw_out_u_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_raw_out_u_state);
- ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.recv(state, subreq, &state->out.arg0);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1263,15 +1263,15 @@ static void _sbus_sss_invoke_in_s_out_b_done(struct tevent_req *subreq)
return;
}
-struct _sbus_sss_invoke_in_s_out_qus_state {
+struct _sbus_sss_invoke_in_s_out_s_state {
struct _sbus_sss_invoker_args_s *in;
- struct _sbus_sss_invoker_args_qus out;
+ struct _sbus_sss_invoker_args_s out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, uint16_t*, uint32_t*, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, const char **);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, const char *);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, const char **);
} handler;
struct sbus_request *sbus_req;
@@ -1280,18 +1280,18 @@ struct _sbus_sss_invoke_in_s_out_qus_state {
};
static void
-_sbus_sss_invoke_in_s_out_qus_step
+_sbus_sss_invoke_in_s_out_s_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_s_out_qus_done
+_sbus_sss_invoke_in_s_out_s_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_s_out_qus_send
+_sbus_sss_invoke_in_s_out_s_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -1301,12 +1301,12 @@ _sbus_sss_invoke_in_s_out_qus_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_s_out_qus_state *state;
+ struct _sbus_sss_invoke_in_s_out_s_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_s_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -1335,7 +1335,7 @@ _sbus_sss_invoke_in_s_out_qus_send
goto done;
}
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_qus_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_s_step, req);
if (ret != EOK) {
goto done;
}
@@ -1360,19 +1360,19 @@ _sbus_sss_invoke_in_s_out_qus_send
return req;
}
-static void _sbus_sss_invoke_in_s_out_qus_step
+static void _sbus_sss_invoke_in_s_out_s_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_s_out_qus_state *state;
+ struct _sbus_sss_invoke_in_s_out_s_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -1382,12 +1382,12 @@ static void _sbus_sss_invoke_in_s_out_qus_step
goto done;
}
- ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, &state->out.arg0);
if (ret != EOK) {
goto done;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -1403,7 +1403,7 @@ static void _sbus_sss_invoke_in_s_out_qus_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_qus_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_s_done, req);
ret = EAGAIN;
goto done;
}
@@ -1418,23 +1418,23 @@ static void _sbus_sss_invoke_in_s_out_qus_step
}
}
-static void _sbus_sss_invoke_in_s_out_qus_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_s_out_s_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_s_out_qus_state *state;
+ struct _sbus_sss_invoke_in_s_out_s_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state);
- ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.recv(state, subreq, &state->out.arg0);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -1444,15 +1444,15 @@ static void _sbus_sss_invoke_in_s_out_qus_done(struct tevent_req *subreq)
return;
}
-struct _sbus_sss_invoke_in_s_out_s_state {
+struct _sbus_sss_invoke_in_s_out_u_state {
struct _sbus_sss_invoker_args_s *in;
- struct _sbus_sss_invoker_args_s out;
+ struct _sbus_sss_invoker_args_u out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, const char *, uint32_t*);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, const char *);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*);
} handler;
struct sbus_request *sbus_req;
@@ -1461,18 +1461,18 @@ struct _sbus_sss_invoke_in_s_out_s_state {
};
static void
-_sbus_sss_invoke_in_s_out_s_step
+_sbus_sss_invoke_in_s_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_s_out_s_done
+_sbus_sss_invoke_in_s_out_u_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_s_out_s_send
+_sbus_sss_invoke_in_s_out_u_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -1482,12 +1482,12 @@ _sbus_sss_invoke_in_s_out_s_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_s_out_s_state *state;
+ struct _sbus_sss_invoke_in_s_out_u_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_s_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_s_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -1516,7 +1516,7 @@ _sbus_sss_invoke_in_s_out_s_send
goto done;
}
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_s_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_s_out_u_step, req);
if (ret != EOK) {
goto done;
}
@@ -1541,19 +1541,19 @@ _sbus_sss_invoke_in_s_out_s_send
return req;
}
-static void _sbus_sss_invoke_in_s_out_s_step
+static void _sbus_sss_invoke_in_s_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_s_out_s_state *state;
+ struct _sbus_sss_invoke_in_s_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_u_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -1568,7 +1568,7 @@ static void _sbus_sss_invoke_in_s_out_s_step
goto done;
}
- ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -1584,7 +1584,7 @@ static void _sbus_sss_invoke_in_s_out_s_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_s_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_s_out_u_done, req);
ret = EAGAIN;
goto done;
}
@@ -1599,14 +1599,14 @@ static void _sbus_sss_invoke_in_s_out_s_step
}
}
-static void _sbus_sss_invoke_in_s_out_s_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_s_out_u_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_s_out_s_state *state;
+ struct _sbus_sss_invoke_in_s_out_u_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_s_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_s_out_u_state);
ret = state->handler.recv(state, subreq, &state->out.arg0);
talloc_zfree(subreq);
@@ -1615,7 +1615,7 @@ static void _sbus_sss_invoke_in_s_out_s_done(struct tevent_req *subreq)
return;
}
- ret = _sbus_sss_invoker_write_s(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -2679,15 +2679,15 @@ static void _sbus_sss_invoke_in_ussu_out__done(struct tevent_req *subreq)
return;
}
-struct _sbus_sss_invoke_in_ussu_out_qus_state {
+struct _sbus_sss_invoke_in_ussu_out_u_state {
struct _sbus_sss_invoker_args_ussu *in;
- struct _sbus_sss_invoker_args_qus out;
+ struct _sbus_sss_invoker_args_u out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, const char *, const char *, uint32_t, uint32_t*);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, const char *, const char *, uint32_t);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*);
} handler;
struct sbus_request *sbus_req;
@@ -2696,18 +2696,18 @@ struct _sbus_sss_invoke_in_ussu_out_qus_state {
};
static void
-_sbus_sss_invoke_in_ussu_out_qus_step
+_sbus_sss_invoke_in_ussu_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_ussu_out_qus_done
+_sbus_sss_invoke_in_ussu_out_u_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_ussu_out_qus_send
+_sbus_sss_invoke_in_ussu_out_u_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -2717,12 +2717,12 @@ _sbus_sss_invoke_in_ussu_out_qus_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_ussu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_ussu_out_u_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_ussu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_ussu_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -2751,7 +2751,7 @@ _sbus_sss_invoke_in_ussu_out_qus_send
goto done;
}
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_ussu_out_qus_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_ussu_out_u_step, req);
if (ret != EOK) {
goto done;
}
@@ -2776,19 +2776,19 @@ _sbus_sss_invoke_in_ussu_out_qus_send
return req;
}
-static void _sbus_sss_invoke_in_ussu_out_qus_step
+static void _sbus_sss_invoke_in_ussu_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_ussu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_ussu_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_u_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -2798,12 +2798,12 @@ static void _sbus_sss_invoke_in_ussu_out_qus_step
goto done;
}
- ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0);
if (ret != EOK) {
goto done;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -2819,7 +2819,7 @@ static void _sbus_sss_invoke_in_ussu_out_qus_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_ussu_out_qus_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_ussu_out_u_done, req);
ret = EAGAIN;
goto done;
}
@@ -2834,23 +2834,23 @@ static void _sbus_sss_invoke_in_ussu_out_qus_step
}
}
-static void _sbus_sss_invoke_in_ussu_out_qus_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_ussu_out_u_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_ussu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_ussu_out_u_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_ussu_out_u_state);
- ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.recv(state, subreq, &state->out.arg0);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -3033,15 +3033,15 @@ static void _sbus_sss_invoke_in_usu_out__done(struct tevent_req *subreq)
return;
}
-struct _sbus_sss_invoke_in_uusssu_out_qus_state {
+struct _sbus_sss_invoke_in_uusssu_out_u_state {
struct _sbus_sss_invoker_args_uusssu *in;
- struct _sbus_sss_invoker_args_qus out;
+ struct _sbus_sss_invoker_args_u out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint16_t*, uint32_t*, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, const char *, const char *, uint32_t, uint32_t*);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, const char *, const char *, uint32_t);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*);
} handler;
struct sbus_request *sbus_req;
@@ -3050,18 +3050,18 @@ struct _sbus_sss_invoke_in_uusssu_out_qus_state {
};
static void
-_sbus_sss_invoke_in_uusssu_out_qus_step
+_sbus_sss_invoke_in_uusssu_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_uusssu_out_qus_done
+_sbus_sss_invoke_in_uusssu_out_u_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_uusssu_out_qus_send
+_sbus_sss_invoke_in_uusssu_out_u_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -3071,12 +3071,12 @@ _sbus_sss_invoke_in_uusssu_out_qus_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_uusssu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uusssu_out_u_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusssu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusssu_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -3105,7 +3105,7 @@ _sbus_sss_invoke_in_uusssu_out_qus_send
goto done;
}
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusssu_out_qus_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusssu_out_u_step, req);
if (ret != EOK) {
goto done;
}
@@ -3130,19 +3130,19 @@ _sbus_sss_invoke_in_uusssu_out_qus_send
return req;
}
-static void _sbus_sss_invoke_in_uusssu_out_qus_step
+static void _sbus_sss_invoke_in_uusssu_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_uusssu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uusssu_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_u_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -3152,12 +3152,12 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_step
goto done;
}
- ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, state->in->arg5, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, state->in->arg5, &state->out.arg0);
if (ret != EOK) {
goto done;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -3173,7 +3173,7 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusssu_out_qus_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusssu_out_u_done, req);
ret = EAGAIN;
goto done;
}
@@ -3188,23 +3188,23 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_step
}
}
-static void _sbus_sss_invoke_in_uusssu_out_qus_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_uusssu_out_u_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_uusssu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uusssu_out_u_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusssu_out_u_state);
- ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.recv(state, subreq, &state->out.arg0);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -3214,15 +3214,15 @@ static void _sbus_sss_invoke_in_uusssu_out_qus_done(struct tevent_req *subreq)
return;
}
-struct _sbus_sss_invoke_in_uusu_out_qus_state {
+struct _sbus_sss_invoke_in_uusu_out_us_state {
struct _sbus_sss_invoker_args_uusu *in;
- struct _sbus_sss_invoker_args_qus out;
+ struct _sbus_sss_invoker_args_us out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, uint32_t, uint32_t*, const char **);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, uint32_t, const char *, uint32_t);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*, const char **);
} handler;
struct sbus_request *sbus_req;
@@ -3231,18 +3231,18 @@ struct _sbus_sss_invoke_in_uusu_out_qus_state {
};
static void
-_sbus_sss_invoke_in_uusu_out_qus_step
+_sbus_sss_invoke_in_uusu_out_us_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_uusu_out_qus_done
+_sbus_sss_invoke_in_uusu_out_us_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_uusu_out_qus_send
+_sbus_sss_invoke_in_uusu_out_us_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -3252,12 +3252,12 @@ _sbus_sss_invoke_in_uusu_out_qus_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_uusu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uusu_out_us_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uusu_out_us_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -3286,7 +3286,7 @@ _sbus_sss_invoke_in_uusu_out_qus_send
goto done;
}
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusu_out_qus_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uusu_out_us_step, req);
if (ret != EOK) {
goto done;
}
@@ -3311,19 +3311,19 @@ _sbus_sss_invoke_in_uusu_out_qus_send
return req;
}
-static void _sbus_sss_invoke_in_uusu_out_qus_step
+static void _sbus_sss_invoke_in_uusu_out_us_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_uusu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uusu_out_us_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_us_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -3333,12 +3333,12 @@ static void _sbus_sss_invoke_in_uusu_out_qus_step
goto done;
}
- ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, &state->out.arg0, &state->out.arg1);
if (ret != EOK) {
goto done;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_us(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -3354,7 +3354,7 @@ static void _sbus_sss_invoke_in_uusu_out_qus_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusu_out_qus_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uusu_out_us_done, req);
ret = EAGAIN;
goto done;
}
@@ -3369,23 +3369,23 @@ static void _sbus_sss_invoke_in_uusu_out_qus_step
}
}
-static void _sbus_sss_invoke_in_uusu_out_qus_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_uusu_out_us_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_uusu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uusu_out_us_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_uusu_out_us_state);
- ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_us(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
@@ -3395,15 +3395,15 @@ static void _sbus_sss_invoke_in_uusu_out_qus_done(struct tevent_req *subreq)
return;
}
-struct _sbus_sss_invoke_in_uuusu_out_qus_state {
+struct _sbus_sss_invoke_in_uuusu_out_u_state {
struct _sbus_sss_invoker_args_uuusu *in;
- struct _sbus_sss_invoker_args_qus out;
+ struct _sbus_sss_invoker_args_u out;
struct {
enum sbus_handler_type type;
void *data;
- errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint16_t*, uint32_t*, const char **);
+ errno_t (*sync)(TALLOC_CTX *, struct sbus_request *, void *, uint32_t, uint32_t, uint32_t, const char *, uint32_t, uint32_t*);
struct tevent_req * (*send)(TALLOC_CTX *, struct tevent_context *, struct sbus_request *, void *, uint32_t, uint32_t, uint32_t, const char *, uint32_t);
- errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint16_t*, uint32_t*, const char **);
+ errno_t (*recv)(TALLOC_CTX *, struct tevent_req *, uint32_t*);
} handler;
struct sbus_request *sbus_req;
@@ -3412,18 +3412,18 @@ struct _sbus_sss_invoke_in_uuusu_out_qus_state {
};
static void
-_sbus_sss_invoke_in_uuusu_out_qus_step
+_sbus_sss_invoke_in_uuusu_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data);
static void
-_sbus_sss_invoke_in_uuusu_out_qus_done
+_sbus_sss_invoke_in_uuusu_out_u_done
(struct tevent_req *subreq);
struct tevent_req *
-_sbus_sss_invoke_in_uuusu_out_qus_send
+_sbus_sss_invoke_in_uuusu_out_u_send
(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct sbus_request *sbus_req,
@@ -3433,12 +3433,12 @@ _sbus_sss_invoke_in_uuusu_out_qus_send
DBusMessageIter *write_iterator,
const char **_key)
{
- struct _sbus_sss_invoke_in_uuusu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uuusu_out_u_state *state;
struct tevent_req *req;
const char *key;
errno_t ret;
- req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uuusu_out_qus_state);
+ req = tevent_req_create(mem_ctx, &state, struct _sbus_sss_invoke_in_uuusu_out_u_state);
if (req == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
return NULL;
@@ -3467,7 +3467,7 @@ _sbus_sss_invoke_in_uuusu_out_qus_send
goto done;
}
- ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uuusu_out_qus_step, req);
+ ret = sbus_invoker_schedule(state, ev, _sbus_sss_invoke_in_uuusu_out_u_step, req);
if (ret != EOK) {
goto done;
}
@@ -3492,19 +3492,19 @@ _sbus_sss_invoke_in_uuusu_out_qus_send
return req;
}
-static void _sbus_sss_invoke_in_uuusu_out_qus_step
+static void _sbus_sss_invoke_in_uuusu_out_u_step
(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval tv,
void *private_data)
{
- struct _sbus_sss_invoke_in_uuusu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uuusu_out_u_state *state;
struct tevent_req *subreq;
struct tevent_req *req;
errno_t ret;
req = talloc_get_type(private_data, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_u_state);
switch (state->handler.type) {
case SBUS_HANDLER_SYNC:
@@ -3514,12 +3514,12 @@ static void _sbus_sss_invoke_in_uuusu_out_qus_step
goto done;
}
- ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.sync(state, state->sbus_req, state->handler.data, state->in->arg0, state->in->arg1, state->in->arg2, state->in->arg3, state->in->arg4, &state->out.arg0);
if (ret != EOK) {
goto done;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
goto done;
case SBUS_HANDLER_ASYNC:
if (state->handler.send == NULL || state->handler.recv == NULL) {
@@ -3535,7 +3535,7 @@ static void _sbus_sss_invoke_in_uuusu_out_qus_step
goto done;
}
- tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uuusu_out_qus_done, req);
+ tevent_req_set_callback(subreq, _sbus_sss_invoke_in_uuusu_out_u_done, req);
ret = EAGAIN;
goto done;
}
@@ -3550,23 +3550,23 @@ static void _sbus_sss_invoke_in_uuusu_out_qus_step
}
}
-static void _sbus_sss_invoke_in_uuusu_out_qus_done(struct tevent_req *subreq)
+static void _sbus_sss_invoke_in_uuusu_out_u_done(struct tevent_req *subreq)
{
- struct _sbus_sss_invoke_in_uuusu_out_qus_state *state;
+ struct _sbus_sss_invoke_in_uuusu_out_u_state *state;
struct tevent_req *req;
errno_t ret;
req = tevent_req_callback_data(subreq, struct tevent_req);
- state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_qus_state);
+ state = tevent_req_data(req, struct _sbus_sss_invoke_in_uuusu_out_u_state);
- ret = state->handler.recv(state, subreq, &state->out.arg0, &state->out.arg1, &state->out.arg2);
+ ret = state->handler.recv(state, subreq, &state->out.arg0);
talloc_zfree(subreq);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
}
- ret = _sbus_sss_invoker_write_qus(state->write_iterator, &state->out);
+ ret = _sbus_sss_invoker_write_u(state->write_iterator, &state->out);
if (ret != EOK) {
tevent_req_error(req, ret);
return;
diff --git a/src/sss_iface/sbus_sss_invokers.h b/src/sss_iface/sbus_sss_invokers.h
index 823ee995556..6737c522626 100644
--- a/src/sss_iface/sbus_sss_invokers.h
+++ b/src/sss_iface/sbus_sss_invokers.h
@@ -42,22 +42,22 @@
_sbus_sss_declare_invoker(, );
_sbus_sss_declare_invoker(, u);
_sbus_sss_declare_invoker(pam_data, pam_response);
-_sbus_sss_declare_invoker(raw, qus);
+_sbus_sss_declare_invoker(raw, u);
_sbus_sss_declare_invoker(s, );
_sbus_sss_declare_invoker(s, as);
_sbus_sss_declare_invoker(s, b);
-_sbus_sss_declare_invoker(s, qus);
_sbus_sss_declare_invoker(s, s);
+_sbus_sss_declare_invoker(s, u);
_sbus_sss_declare_invoker(sqq, q);
_sbus_sss_declare_invoker(ss, o);
_sbus_sss_declare_invoker(ssau, );
_sbus_sss_declare_invoker(u, );
_sbus_sss_declare_invoker(usq, );
_sbus_sss_declare_invoker(ussu, );
-_sbus_sss_declare_invoker(ussu, qus);
+_sbus_sss_declare_invoker(ussu, u);
_sbus_sss_declare_invoker(usu, );
-_sbus_sss_declare_invoker(uusssu, qus);
-_sbus_sss_declare_invoker(uusu, qus);
-_sbus_sss_declare_invoker(uuusu, qus);
+_sbus_sss_declare_invoker(uusssu, u);
+_sbus_sss_declare_invoker(uusu, us);
+_sbus_sss_declare_invoker(uuusu, u);
#endif /* _SBUS_SSS_INVOKERS_H_ */
diff --git a/src/sss_iface/sbus_sss_symbols.c b/src/sss_iface/sbus_sss_symbols.c
index 0219f370d34..606acdfe5b2 100644
--- a/src/sss_iface/sbus_sss_symbols.c
+++ b/src/sss_iface/sbus_sss_symbols.c
@@ -225,7 +225,6 @@ _sbus_sss_args_sssd_dataprovider_getAccountDomain = {
{NULL}
},
.output = (const struct sbus_argument[]){
- {.type = "q", .name = "dp_error"},
{.type = "u", .name = "error"},
{.type = "s", .name = "domain_name"},
{NULL}
@@ -244,9 +243,7 @@ _sbus_sss_args_sssd_dataprovider_getAccountInfo = {
{NULL}
},
.output = (const struct sbus_argument[]){
- {.type = "q", .name = "dp_error"},
{.type = "u", .name = "error"},
- {.type = "s", .name = "error_message"},
{NULL}
}
};
@@ -258,9 +255,7 @@ _sbus_sss_args_sssd_dataprovider_getDomains = {
{NULL}
},
.output = (const struct sbus_argument[]){
- {.type = "q", .name = "dp_error"},
{.type = "u", .name = "error"},
- {.type = "s", .name = "error_message"},
{NULL}
}
};
@@ -275,9 +270,7 @@ _sbus_sss_args_sssd_dataprovider_hostHandler = {
{NULL}
},
.output = (const struct sbus_argument[]){
- {.type = "q", .name = "dp_error"},
{.type = "u", .name = "error"},
- {.type = "s", .name = "error_message"},
{NULL}
}
};
@@ -305,9 +298,7 @@ _sbus_sss_args_sssd_dataprovider_resolverHandler = {
{NULL}
},
.output = (const struct sbus_argument[]){
- {.type = "q", .name = "dp_error"},
{.type = "u", .name = "error"},
- {.type = "s", .name = "error_message"},
{NULL}
}
};
@@ -318,9 +309,7 @@ _sbus_sss_args_sssd_dataprovider_sudoHandler = {
{NULL}
},
.output = (const struct sbus_argument[]){
- {.type = "q", .name = "dp_error"},
{.type = "u", .name = "error"},
- {.type = "s", .name = "error_message"},
{NULL}
}
};
diff --git a/src/sss_iface/sss_iface.xml b/src/sss_iface/sss_iface.xml
index 02b98789de4..2e7c809a113 100644
--- a/src/sss_iface/sss_iface.xml
+++ b/src/sss_iface/sss_iface.xml
@@ -107,18 +107,14 @@
-
-
-
-
@@ -126,15 +122,11 @@
-
-
-
-
@@ -143,16 +135,13 @@
-
-
-
diff --git a/src/tests/cmocka/common_mock_resp.h b/src/tests/cmocka/common_mock_resp.h
index c277682fd89..6565da74d56 100644
--- a/src/tests/cmocka/common_mock_resp.h
+++ b/src/tests/cmocka/common_mock_resp.h
@@ -47,7 +47,7 @@ mock_prctx(TALLOC_CTX *mem_ctx);
* sss_dp_get_account_recv call by calling mock_account_recv.
*
* The mocked sss_sp_get_account_recv shall return the return values
- * given with parameters dp_err, dp_ret and msg and optionally also call
+ * given with parameters dp_ret and optionally also call
* the acct_cb_t callback, if given with the pvt pointer as user data.
* The callback can for instance populate the cache, thus simulating
* Data Provider lookup.
@@ -58,8 +58,7 @@ mock_prctx(TALLOC_CTX *mem_ctx);
typedef int (*acct_cb_t)(void *);
typedef int (*resolver_cb_t)(void *);
-void mock_account_recv(uint16_t dp_err, uint32_t dp_ret, char *msg,
- acct_cb_t acct_cb, void *pvt);
+void mock_account_recv(uint32_t dp_ret, acct_cb_t acct_cb, void *pvt);
void mock_account_recv_simple(void);
diff --git a/src/tests/cmocka/common_mock_resp_dp.c b/src/tests/cmocka/common_mock_resp_dp.c
index 493231d0da0..f61c14b047b 100644
--- a/src/tests/cmocka/common_mock_resp_dp.c
+++ b/src/tests/cmocka/common_mock_resp_dp.c
@@ -43,15 +43,11 @@ sss_dp_get_account_send(TALLOC_CTX *mem_ctx,
errno_t
sss_dp_get_account_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- dbus_uint16_t *dp_err,
- dbus_uint32_t *dp_ret,
- const char **err_msg)
+ dbus_uint32_t *err)
{
acct_cb_t cb;
- *dp_err = sss_mock_type(dbus_uint16_t);
- *dp_ret = sss_mock_type(dbus_uint32_t);
- *err_msg = sss_mock_ptr_type(char *);
+ *err = sss_mock_type(dbus_uint32_t);
cb = sss_mock_ptr_type(acct_cb_t);
if (cb) {
@@ -76,15 +72,11 @@ sss_dp_resolver_get_send(TALLOC_CTX *mem_ctx,
errno_t
sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- dbus_uint16_t *dp_err,
- dbus_uint32_t *dp_ret,
- const char **err_msg)
+ dbus_uint32_t *err)
{
resolver_cb_t cb;
- *dp_err = sss_mock_type(dbus_uint16_t);
- *dp_ret = sss_mock_type(dbus_uint32_t);
- *err_msg = sss_mock_ptr_type(char *);
+ *err = sss_mock_type(dbus_uint32_t);
cb = sss_mock_ptr_type(resolver_cb_t);
if (cb) {
@@ -97,9 +89,7 @@ sss_dp_resolver_get_recv(TALLOC_CTX *mem_ctx,
void mock_resolver_recv(uint16_t dp_err, uint32_t dp_ret, char *msg,
resolver_cb_t cb, void *pvt)
{
- will_return(sss_dp_resolver_get_recv, dp_err);
will_return(sss_dp_resolver_get_recv, dp_ret);
- will_return(sss_dp_resolver_get_recv, msg);
will_return(sss_dp_resolver_get_recv, cb);
if (cb) {
@@ -148,15 +138,11 @@ sss_dp_get_ssh_host_recv(TALLOC_CTX *mem_ctx,
errno_t
sss_dp_req_recv(TALLOC_CTX *mem_ctx,
struct tevent_req *req,
- dbus_uint16_t *dp_err,
- dbus_uint32_t *dp_ret,
- char **err_msg)
+ dbus_uint32_t *err)
{
acct_cb_t cb;
- *dp_err = sss_mock_type(dbus_uint16_t);
- *dp_ret = sss_mock_type(dbus_uint32_t);
- *err_msg = sss_mock_ptr_type(char *);
+ *err = sss_mock_type(dbus_uint32_t);
cb = sss_mock_ptr_type(acct_cb_t);
if (cb) {
@@ -166,12 +152,10 @@ sss_dp_req_recv(TALLOC_CTX *mem_ctx,
return test_request_recv(req);
}
-void mock_account_recv(uint16_t dp_err, uint32_t dp_ret, char *msg,
- acct_cb_t acct_cb, void *pvt)
+void mock_account_recv(uint32_t dp_ret, acct_cb_t acct_cb,
+ void *pvt)
{
- will_return(sss_dp_get_account_recv, dp_err);
will_return(sss_dp_get_account_recv, dp_ret);
- will_return(sss_dp_get_account_recv, msg);
will_return(sss_dp_get_account_recv, acct_cb);
if (acct_cb) {
@@ -181,7 +165,7 @@ void mock_account_recv(uint16_t dp_err, uint32_t dp_ret, char *msg,
void mock_account_recv_simple(void)
{
- return mock_account_recv(0, 0, NULL, NULL, NULL);
+ return mock_account_recv(0, NULL, NULL);
}
struct tevent_req *
diff --git a/src/tests/cmocka/test_failover_server.c b/src/tests/cmocka/test_failover_server.c
new file mode 100644
index 00000000000..842179bb46e
--- /dev/null
+++ b/src/tests/cmocka/test_failover_server.c
@@ -0,0 +1,570 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "tests/cmocka/common_mock.h"
+#include "providers/failover/failover_server.h"
+#include "resolv/async_resolv.h"
+
+static int setup(void **state)
+{
+ TALLOC_CTX *test_ctx = NULL;
+
+ assert_true(leak_check_setup());
+ test_ctx = talloc_new(global_talloc_context);
+ assert_non_null(test_ctx);
+ check_leaks_push(test_ctx);
+
+ *state = test_ctx;
+
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ assert_true(check_leaks_pop(test_ctx));
+ talloc_free(test_ctx);
+ assert_true(leak_check_teardown());
+
+ return 0;
+}
+
+static uint8_t *mock_ip4_addr(TALLOC_CTX *mem_ctx, const char *addr)
+{
+ struct in_addr net_addr;
+ uint8_t *buf;
+ int ret;
+
+ if (addr == NULL) {
+ return NULL;
+ }
+
+ ret = inet_pton(AF_INET, addr, &net_addr);
+ assert_int_equal(ret, 1);
+ buf = talloc_memdup(mem_ctx, &net_addr, sizeof(struct in_addr));
+ assert_non_null(buf);
+
+ return buf;
+}
+
+static uint8_t *mock_ip6_addr(TALLOC_CTX *mem_ctx, const char *addr)
+{
+ struct in6_addr net_addr;
+ uint8_t *buf;
+ int ret;
+
+ if (addr == NULL) {
+ return NULL;
+ }
+
+ ret = inet_pton(AF_INET6, addr, &net_addr);
+ assert_int_equal(ret, 1);
+ buf = talloc_memdup(mem_ctx, &net_addr, sizeof(struct in6_addr));
+ assert_non_null(buf);
+
+ return buf;
+}
+
+/* Test: Successfully create a failover server */
+static void test_sss_failover_server_new(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+
+ srv = sss_failover_server_new(test_ctx, "server.ipa.test",
+ "ldap://server.ipa.test", 389, 10, 100);
+ assert_non_null(srv);
+ assert_non_null(srv->name);
+ assert_string_equal(srv->name, "server.ipa.test");
+ assert_non_null(srv->uri);
+ assert_string_equal(srv->uri, "ldap://server.ipa.test");
+ assert_int_equal(srv->port, 389);
+
+ assert_null(srv->addr);
+ assert_int_equal(srv->priority, 10);
+ assert_int_equal(srv->weight, 100);
+
+ talloc_free(srv);
+}
+
+/* Test: NULL hostname does not crash */
+static void test_sss_failover_server_new__null(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+
+ srv = sss_failover_server_new(test_ctx, NULL, "ldap://server.ipa.test", 389,
+ 10, 100);
+ assert_null(srv);
+}
+
+/* Test: Successfully create a failover server with IPv4 address */
+static void test_sss_failover_server_set_address__ipv4(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ struct in_addr expected_addr;
+ struct sockaddr_in *sa_in;
+ const char *hostname = "server.ipa.test";
+ const char *addr = "192.168.1.100";
+ uint8_t *net_addr;
+ errno_t ret;
+ time_t now;
+
+ net_addr = mock_ip4_addr(test_ctx, addr);
+ assert_non_null(net_addr);
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ now = time(NULL);
+ ret = sss_failover_server_set_address(srv, AF_INET, 10, net_addr);
+ assert_int_equal(ret, EOK);
+
+ assert_non_null(srv->addr);
+ assert_int_equal(srv->addr->family, AF_INET);
+ assert_non_null(srv->addr->human);
+ assert_string_equal(srv->addr->human, addr);
+ assert_true(srv->addr->expire - now >= 10);
+
+ ret = inet_pton(AF_INET, addr, &expected_addr);
+ assert_int_equal(ret, 1);
+ assert_non_null(srv->addr->binary);
+ assert_ptr_not_equal(srv->addr->binary, net_addr);
+ assert_memory_equal(srv->addr->binary, &expected_addr,
+ sizeof(struct in_addr));
+ assert_int_equal(srv->addr->binary_len, sizeof(struct in_addr));
+
+ /* Verify sockaddr is properly set */
+ assert_non_null(srv->addr->sockaddr);
+ assert_int_equal(srv->addr->sockaddr_len, sizeof(struct sockaddr_in));
+ sa_in = (struct sockaddr_in *)srv->addr->sockaddr;
+ assert_int_equal(sa_in->sin_family, AF_INET);
+ assert_int_equal(ntohs(sa_in->sin_port), 389);
+ assert_memory_equal(&sa_in->sin_addr, &expected_addr, sizeof(struct in_addr));
+
+ talloc_free(net_addr);
+ talloc_free(srv);
+}
+
+/* Test: Successfully create a failover server with IPv6 address */
+static void test_sss_failover_server_set_address__ipv6(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ struct in6_addr expected_addr;
+ struct sockaddr_in6 *sa_in6;
+ const char *hostname = "server.ipa.test";
+ const char *addr = "2a00:102a:403a:c7a7:e05e:11e6:3189:3326";
+ uint8_t *net_addr;
+ errno_t ret;
+ time_t now;
+
+ net_addr = mock_ip6_addr(test_ctx, addr);
+ assert_non_null(net_addr);
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ now = time(NULL);
+ ret = sss_failover_server_set_address(srv, AF_INET6, 10, net_addr);
+ assert_int_equal(ret, EOK);
+
+ assert_non_null(srv->addr);
+ assert_int_equal(srv->addr->family, AF_INET6);
+ assert_non_null(srv->addr->human);
+ assert_string_equal(srv->addr->human, addr);
+ assert_true(srv->addr->expire - now >= 10);
+
+ ret = inet_pton(AF_INET6, addr, &expected_addr);
+ assert_int_equal(ret, 1);
+ assert_non_null(srv->addr->binary);
+ assert_ptr_not_equal(srv->addr->binary, net_addr);
+ assert_memory_equal(srv->addr->binary, &expected_addr,
+ sizeof(struct in6_addr));
+ assert_int_equal(srv->addr->binary_len, sizeof(struct in6_addr));
+
+ /* Verify sockaddr is properly set */
+ assert_non_null(srv->addr->sockaddr);
+ assert_int_equal(srv->addr->sockaddr_len, sizeof(struct sockaddr_in6));
+ sa_in6 = (struct sockaddr_in6 *)srv->addr->sockaddr;
+ assert_int_equal(sa_in6->sin6_family, AF_INET6);
+ assert_int_equal(ntohs(sa_in6->sin6_port), 389);
+ assert_memory_equal(&sa_in6->sin6_addr, &expected_addr, sizeof(struct in6_addr));
+
+ talloc_free(net_addr);
+ talloc_free(srv);
+}
+
+/* Test: Error out if invalid family is given */
+static void test_sss_failover_server_set_address__invalid_family(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ const char *hostname = "server.ipa.test";
+ const char *addr = "192.168.1.100";
+ uint8_t *net_addr;
+ errno_t ret;
+
+ net_addr = mock_ip4_addr(test_ctx, addr);
+ assert_non_null(net_addr);
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ ret = sss_failover_server_set_address(srv, AF_UNIX, 10, net_addr);
+ assert_int_equal(ret, EINVAL);
+
+ talloc_free(net_addr);
+ talloc_free(srv);
+}
+
+/* Test: Error out if invalid address is given */
+static void test_sss_failover_server_set_address__null_addr(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ const char *hostname = "server.ipa.test";
+ errno_t ret;
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ ret = sss_failover_server_set_address(srv, AF_INET, 10, NULL);
+ assert_int_equal(ret, EINVAL);
+
+ talloc_free(srv);
+}
+
+/* Test: Successfully clone a failover server with IPv4 address */
+static void test_sss_failover_server_clone__ipv4(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ struct sss_failover_server *clone;
+ const char *hostname = "server.ipa.test";
+ const char *addr = "192.168.1.100";
+ uint8_t *net_addr;
+ errno_t ret;
+
+ net_addr = mock_ip4_addr(test_ctx, addr);
+ assert_non_null(net_addr);
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ ret = sss_failover_server_set_address(srv, AF_INET, 10, net_addr);
+ assert_int_equal(ret, EOK);
+
+ clone = sss_failover_server_clone(test_ctx, srv);
+ assert_non_null(clone);
+
+ /* Verify name is cloned */
+ assert_non_null(clone->name);
+ assert_string_equal(clone->name, srv->name);
+
+ /* Verify priority and weight are cloned */
+ assert_int_equal(clone->priority, srv->priority);
+ assert_int_equal(clone->weight, srv->weight);
+
+ /* Verify address is cloned */
+ assert_non_null(clone->addr);
+ assert_int_equal(clone->addr->family, srv->addr->family);
+ assert_int_equal(clone->addr->expire, srv->addr->expire);
+ assert_non_null(clone->addr->human);
+ assert_string_equal(clone->addr->human, srv->addr->human);
+ assert_non_null(clone->addr->binary);
+ assert_memory_equal(clone->addr->binary, srv->addr->binary,
+ sizeof(struct in_addr));
+ assert_int_equal(clone->addr->binary_len, srv->addr->binary_len);
+ assert_non_null(clone->addr->sockaddr);
+ assert_int_equal(clone->addr->sockaddr_len, srv->addr->sockaddr_len);
+
+ /* Verify clone is independent (different memory) */
+ assert_ptr_not_equal(clone, srv);
+ assert_ptr_not_equal(clone->name, srv->name);
+ assert_ptr_not_equal(clone->addr, srv->addr);
+ assert_ptr_not_equal(clone->addr->binary, srv->addr->binary);
+ assert_ptr_not_equal(clone->addr->human, srv->addr->human);
+ assert_ptr_not_equal(clone->addr->sockaddr, srv->addr->sockaddr);
+
+ talloc_free(net_addr);
+ talloc_free(srv);
+ talloc_free(clone);
+}
+
+/* Test: Successfully clone a failover server with IPv6 address */
+static void test_sss_failover_server_clone__ipv6(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ struct sss_failover_server *clone;
+ const char *hostname = "server1.ipa.test";
+ const char *addr = "2a00:102a:403a:c7a7:e05e:11e6:3189:3326";
+ uint8_t *net_addr;
+ errno_t ret;
+
+ net_addr = mock_ip6_addr(test_ctx, addr);
+ assert_non_null(net_addr);
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server1.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ ret = sss_failover_server_set_address(srv, AF_INET6, 10, net_addr);
+ assert_int_equal(ret, EOK);
+
+ clone = sss_failover_server_clone(test_ctx, srv);
+ assert_non_null(clone);
+
+ /* Verify name is cloned */
+ assert_non_null(clone->name);
+ assert_string_equal(clone->name, srv->name);
+
+ /* Verify priority and weight are cloned */
+ assert_int_equal(clone->priority, srv->priority);
+ assert_int_equal(clone->weight, srv->weight);
+
+ /* Verify address is cloned */
+ assert_non_null(clone->addr);
+ assert_int_equal(clone->addr->family, srv->addr->family);
+ assert_int_equal(clone->addr->expire, srv->addr->expire);
+ assert_non_null(clone->addr->human);
+ assert_string_equal(clone->addr->human, srv->addr->human);
+ assert_non_null(clone->addr->binary);
+ assert_memory_equal(clone->addr->binary, srv->addr->binary,
+ sizeof(struct in6_addr));
+ assert_int_equal(clone->addr->binary_len, srv->addr->binary_len);
+ assert_non_null(clone->addr->sockaddr);
+ assert_int_equal(clone->addr->sockaddr_len, srv->addr->sockaddr_len);
+
+ /* Verify clone is independent (different memory) */
+ assert_ptr_not_equal(clone, srv);
+ assert_ptr_not_equal(clone->name, srv->name);
+ assert_ptr_not_equal(clone->addr, srv->addr);
+ assert_ptr_not_equal(clone->addr->binary, srv->addr->binary);
+ assert_ptr_not_equal(clone->addr->human, srv->addr->human);
+ assert_ptr_not_equal(clone->addr->sockaddr, srv->addr->sockaddr);
+
+ talloc_free(net_addr);
+ talloc_free(srv);
+ talloc_free(clone);
+}
+
+/* Test: Successfully clone a failover server with empty address */
+static void test_sss_failover_server_clone__null_addr(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+ struct sss_failover_server *clone;
+ const char *hostname = "server.ipa.test";
+
+ srv = sss_failover_server_new(test_ctx, hostname, "ldap://server.ipa.test",
+ 389, 10, 100);
+ assert_non_null(srv);
+
+ clone = sss_failover_server_clone(test_ctx, srv);
+ assert_non_null(clone);
+
+ /* Verify name is cloned */
+ assert_non_null(clone->name);
+ assert_string_equal(clone->name, srv->name);
+
+ /* Verify priority and weight are cloned */
+ assert_int_equal(clone->priority, srv->priority);
+ assert_int_equal(clone->weight, srv->weight);
+
+ /* Verify address is cloned */
+ assert_null(clone->addr);
+
+ /* Verify clone is independent (different memory) */
+ assert_ptr_not_equal(clone, srv);
+ assert_ptr_not_equal(clone->name, srv->name);
+
+ talloc_free(srv);
+ talloc_free(clone);
+}
+
+/* Test: Fail when cloning NULL server */
+static void test_sss_failover_server_clone__null_server(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *clone;
+
+ clone = sss_failover_server_clone(test_ctx, NULL);
+ assert_null(clone);
+}
+
+/* Test: Server state transitions */
+static void test_sss_failover_server_state_management(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv;
+
+ srv = sss_failover_server_new(test_ctx, "server.ipa.test",
+ "ldap://server.ipa.test", 389, 10, 100);
+ assert_non_null(srv);
+
+ /* Initial state should be UNKNOWN */
+ assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_UNKNOWN);
+ assert_true(sss_failover_server_maybe_working(srv));
+
+ /* Mark as reachable */
+ sss_failover_server_mark_reachable(srv);
+ assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_REACHABLE);
+ assert_true(sss_failover_server_maybe_working(srv));
+
+ /* Mark as working */
+ sss_failover_server_mark_working(srv);
+ assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_WORKING);
+ assert_true(sss_failover_server_maybe_working(srv));
+
+ /* Mark as offline */
+ sss_failover_server_mark_offline(srv);
+ assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_OFFLINE);
+ assert_false(sss_failover_server_maybe_working(srv));
+
+ /* Mark as unknown again */
+ sss_failover_server_mark_unknown(srv);
+ assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_UNKNOWN);
+ assert_true(sss_failover_server_maybe_working(srv));
+
+ /* Mark as resolver error */
+ sss_failover_server_mark_resolver_error(srv);
+ assert_int_equal(srv->state, SSS_FAILOVER_SERVER_STATE_RESOLVER_ERROR);
+ assert_false(sss_failover_server_maybe_working(srv));
+
+ talloc_free(srv);
+}
+
+/* Test: Compare two equal servers */
+static void test_sss_failover_server_equal__same(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv1;
+ struct sss_failover_server *srv2;
+
+ srv1 = sss_failover_server_new(test_ctx, "server.ipa.test",
+ "ldap://server.ipa.test", 389, 10, 100);
+ assert_non_null(srv1);
+
+ srv2 = sss_failover_server_new(test_ctx, "server.ipa.test",
+ "ldap://server.ipa.test", 389, 20, 200);
+ assert_non_null(srv2);
+
+ /* Should be equal (only name and port matter) */
+ assert_true(sss_failover_server_equal(srv1, srv2));
+
+ talloc_free(srv1);
+ talloc_free(srv2);
+}
+
+/* Test: Compare two servers with different names */
+static void test_sss_failover_server_equal__different_name(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX*)*state;
+ struct sss_failover_server *srv1;
+ struct sss_failover_server *srv2;
+
+ srv1 = sss_failover_server_new(test_ctx, "server1.ipa.test",
+ "ldap://server1.ipa.test", 389, 10, 100);
+ assert_non_null(srv1);
+
+ srv2 = sss_failover_server_new(test_ctx, "server2.ipa.test",
+ "ldap://server2.ipa.test", 389, 10, 100);
+ assert_non_null(srv2);
+
+ /* Should not be equal (different names) */
+ assert_false(sss_failover_server_equal(srv1, srv2));
+
+ talloc_free(srv1);
+ talloc_free(srv2);
+}
+
+/* Test: Compare two servers with different ports */
+static void
+test_sss_failover_server_equal__different_port(void **state)
+{
+ TALLOC_CTX *test_ctx = (TALLOC_CTX *)*state;
+ struct sss_failover_server *srv1;
+ struct sss_failover_server *srv2;
+
+ srv1 = sss_failover_server_new(test_ctx, "server.ipa.test",
+ "ldap://server.ipa.test", 389, 10, 100);
+ assert_non_null(srv1);
+
+ srv2 = sss_failover_server_new(test_ctx, "server.ipa.test",
+ "ldaps://server.ipa.test", 636, 10, 100);
+ assert_non_null(srv2);
+
+ /* Should not be equal (different ports) */
+ assert_false(sss_failover_server_equal(srv1, srv2));
+
+ talloc_free(srv1);
+ talloc_free(srv2);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_new,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_new__null,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__ipv4,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__ipv6,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__invalid_family,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_set_address__null_addr,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__ipv4,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__ipv6,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__null_addr,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_clone__null_server,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_state_management,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_equal__same,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_equal__different_name,
+ setup, teardown),
+ cmocka_unit_test_setup_teardown(test_sss_failover_server_equal__different_port,
+ setup, teardown)
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/src/tests/cmocka/test_krb5_wait_queue.c b/src/tests/cmocka/test_krb5_wait_queue.c
index 9f8473b0612..63f3b9fbb3f 100644
--- a/src/tests/cmocka/test_krb5_wait_queue.c
+++ b/src/tests/cmocka/test_krb5_wait_queue.c
@@ -35,7 +35,6 @@ struct krb5_mocked_auth_state {
time_t us_delay;
int ret;
int pam_status;
- int dp_err;
};
static void krb5_mocked_auth_done(struct tevent_context *ev,
@@ -64,7 +63,6 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
state->us_delay = sss_mock_type(time_t);
state->ret = sss_mock_type(int);
state->pam_status = sss_mock_type(int);
- state->dp_err = sss_mock_type(int);
tv = tevent_timeval_current_ofs(0, state->us_delay);
@@ -97,8 +95,7 @@ static void krb5_mocked_auth_done(struct tevent_context *ev,
}
int krb5_auth_recv(struct tevent_req *req,
- int *_pam_status,
- int *_dp_err)
+ int *_pam_status)
{
struct krb5_mocked_auth_state *state;
@@ -108,10 +105,6 @@ int krb5_auth_recv(struct tevent_req *req,
*_pam_status = state->pam_status;
}
- if (_dp_err != NULL) {
- *_dp_err = state->dp_err;
- }
-
TEVENT_REQ_RETURN_ON_ERROR(req);
return EOK;
}
@@ -163,8 +156,7 @@ static void test_krb5_wait_mock(struct test_krb5_wait_queue *test_ctx,
const char *username,
time_t us_delay,
int ret,
- int pam_status,
- int dp_err)
+ int pam_status)
{
test_ctx->pd->user = discard_const(username);
@@ -172,13 +164,12 @@ static void test_krb5_wait_mock(struct test_krb5_wait_queue *test_ctx,
will_return(krb5_auth_send, us_delay);
will_return(krb5_auth_send, ret);
will_return(krb5_auth_send, pam_status);
- will_return(krb5_auth_send, dp_err);
}
static void test_krb5_wait_mock_success(struct test_krb5_wait_queue *test_ctx,
const char *username)
{
- return test_krb5_wait_mock(test_ctx, username, 200, 0, 0, 0);
+ return test_krb5_wait_mock(test_ctx, username, 200, 0, 0);
}
static void test_krb5_wait_queue_single_done(struct tevent_req *req);
@@ -210,9 +201,8 @@ static void test_krb5_wait_queue_single_done(struct tevent_req *req)
tevent_req_callback_data(req, struct test_krb5_wait_queue);
errno_t ret;
int pam_status;
- int dp_err;
- ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(req, &pam_status);
talloc_free(req);
assert_int_equal(ret, EOK);
@@ -253,9 +243,8 @@ static void test_krb5_wait_queue_multi_done(struct tevent_req *req)
tevent_req_callback_data(req, struct test_krb5_wait_queue);
errno_t ret;
int pam_status;
- int dp_err;
- ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(req, &pam_status);
talloc_free(req);
assert_int_equal(ret, EOK);
@@ -279,7 +268,7 @@ static void test_krb5_wait_queue_fail_odd(void **state)
test_ctx->num_auths = 10;
for (i=0; i < test_ctx->num_auths; i++) {
- test_krb5_wait_mock(test_ctx, "krb5_user", 0, i+1 % 2, PAM_SUCCESS, 0);
+ test_krb5_wait_mock(test_ctx, "krb5_user", 0, i+1 % 2, PAM_SUCCESS);
req = krb5_auth_queue_send(test_ctx,
test_ctx->tctx->ev,
@@ -300,9 +289,8 @@ static void test_krb5_wait_queue_fail_odd_done(struct tevent_req *req)
tevent_req_callback_data(req, struct test_krb5_wait_queue);
errno_t ret;
int pam_status;
- int dp_err;
- ret = krb5_auth_queue_recv(req, &pam_status, &dp_err);
+ ret = krb5_auth_queue_recv(req, &pam_status);
talloc_free(req);
assert_int_equal(ret, test_ctx->num_finished_auths+1 % 2);
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index b5a6162166e..c947cf9a2fe 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -857,7 +857,7 @@ void test_sss_nss_getpwnam_search(void **state)
struct ldb_result *res;
mock_input_user_or_group("testuser_search");
- mock_account_recv(0, 0, NULL, test_sss_nss_getpwnam_search_acct_cb, sss_nss_test_ctx);
+ mock_account_recv(0, test_sss_nss_getpwnam_search_acct_cb, sss_nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
mock_fill_user();
set_cmd_cb(test_sss_nss_getpwnam_search_check);
@@ -936,7 +936,7 @@ void test_sss_nss_getpwnam_update(void **state)
/* Mock client command */
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM);
/* Call this function when user is updated by the mock DP request */
- mock_account_recv(0, 0, NULL, test_sss_nss_getpwnam_update_acct_cb, sss_nss_test_ctx);
+ mock_account_recv(0, test_sss_nss_getpwnam_update_acct_cb, sss_nss_test_ctx);
/* Call this function to check what the responder returned to the client */
set_cmd_cb(test_sss_nss_getpwnam_update_check);
/* Mock output buffer */
@@ -1327,7 +1327,7 @@ void test_sss_nss_getpwuid_search(void **state)
struct ldb_result *res;
mock_input_id(sss_nss_test_ctx, getpwuid_srch.pw_uid);
- mock_account_recv(0, 0, NULL, test_sss_nss_getpwuid_search_acct_cb, sss_nss_test_ctx);
+ mock_account_recv(0, test_sss_nss_getpwuid_search_acct_cb, sss_nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
mock_fill_user();
set_cmd_cb(test_sss_nss_getpwuid_search_check);
@@ -1406,7 +1406,7 @@ void test_sss_nss_getpwuid_update(void **state)
/* Mock client command */
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID);
/* Call this function when id is updated by the mock DP request */
- mock_account_recv(0, 0, NULL, test_sss_nss_getpwuid_update_acct_cb, sss_nss_test_ctx);
+ mock_account_recv(0, test_sss_nss_getpwuid_update_acct_cb, sss_nss_test_ctx);
/* Call this function to check what the responder returned to the client */
set_cmd_cb(test_sss_nss_getpwuid_update_check);
/* Mock output buffer */
@@ -3354,7 +3354,7 @@ void test_sss_nss_initgr_search(void **state)
struct ldb_result *res;
mock_input_user_or_group("testinitgr_srch");
- mock_account_recv(0, 0, NULL, test_sss_nss_initgr_search_acct_cb, sss_nss_test_ctx);
+ mock_account_recv(0, test_sss_nss_initgr_search_acct_cb, sss_nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR);
will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
set_cmd_cb(test_sss_nss_initgr_search_check);
@@ -3474,7 +3474,7 @@ void test_sss_nss_initgr_update(void **state)
assert_int_equal(ret, EOK);
mock_input_user_or_group("testinitgr_update");
- mock_account_recv(0, 0, NULL, test_sss_nss_initgr_update_acct_cb, sss_nss_test_ctx);
+ mock_account_recv(0, test_sss_nss_initgr_update_acct_cb, sss_nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR);
will_return_always(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
set_cmd_cb(test_sss_nss_initgr_update_check);
@@ -3594,7 +3594,7 @@ void test_sss_nss_initgr_update_two_expire_attributes(void **state)
assert_int_equal(ret, EOK);
mock_input_user_or_group("testinitgr_2attr");
- mock_account_recv(0, 0, NULL,
+ mock_account_recv(0,
test_sss_nss_initgr_update_acct_2expire_attributes_cb,
sss_nss_test_ctx);
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR);
@@ -3991,7 +3991,7 @@ void test_sss_nss_getnamebysid_update(void **state)
/* Mock client command */
will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETNAMEBYSID);
/* Call this function when user is updated by the mock DP request */
- mock_account_recv(0, 0, NULL, test_sss_nss_getnamebysid_update_acct_cb,
+ mock_account_recv(0L, test_sss_nss_getnamebysid_update_acct_cb,
sss_nss_test_ctx);
/* Call this function to check what the responder returned to the client */
set_cmd_cb(test_sss_nss_getnamebysid_update_check);
diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c
index 715ac04a9e9..6d97c0aa547 100644
--- a/src/tests/cmocka/test_pam_srv.c
+++ b/src/tests/cmocka/test_pam_srv.c
@@ -669,7 +669,7 @@ static void mock_input_pam_passkey(TALLOC_CTX *mem_ctx,
}
if (acct_cb != NULL) {
- mock_account_recv(0, 0, NULL, acct_cb, discard_const(passkey));
+ mock_account_recv(0, acct_cb, discard_const(passkey));
}
}
@@ -843,7 +843,7 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name,
will_return(__wrap_sss_packet_get_body, buf_size);
if (acct_cb != NULL) {
- mock_account_recv(0, 0, NULL, acct_cb, discard_const(cert));
+ mock_account_recv(0, acct_cb, discard_const(cert));
}
if (name != NULL) {
diff --git a/src/util/typeof.h b/src/util/typeof.h
new file mode 100644
index 00000000000..89f499d560e
--- /dev/null
+++ b/src/util/typeof.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 2025 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#ifndef _SSS_TYPEOF_H_
+#define _SSS_TYPEOF_H_
+
+/**
+ * Provide a compile-time type safety for callbacks and handlers.
+ *
+ * We use GCC __typeof__ extension to achieve this. We retrieve the private
+ * data type and create the expected handler function type with it. If the
+ * method accepts parsed D-Bus arguments, they are appended with variadic
+ * parameters. We check that the handler type matches the expected type
+ * and return the sbus_handler structure value.
+ *
+ * We also use __attribute__((unused)) to suppress compiler warning about
+ * unused __fn.
+ *
+ * We do not perform this check on platforms where this extension is not
+ * available and just create a generic handler. This does not matter since
+ * we test compilation with GCC anyway.
+ */
+#if (__GNUC__ >= 3)
+
+#define SSS_CHECK_FUNCTION_TYPE(fn, return_type, ...) ({ \
+ __attribute__((unused)) return_type (*__fn)(__VA_ARGS__) = (fn); \
+})
+
+#define SSS_TYPEOF(data) __typeof__(data)
+
+#else
+#define SSS_CHECK_FUNCTION_TYPE(handler, return_type, ...)
+#define SSS_TYPEOF(data) (void*)
+#endif
+
+#endif /* _SSS_TYPEOF_H_ */
diff --git a/src/util/util.h b/src/util/util.h
index ccf0b30ab7e..a7cb9fdad6b 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -141,25 +141,39 @@ enum sssd_exit_status {
#endif
#endif
-#define TEVENT_REQ_RETURN_ON_ERROR(req) do { \
- enum tevent_req_state TRROEstate; \
- uint64_t TRROEuint64; \
- errno_t TRROEerr; \
+#define TEVENT_REQ_ERROR_TO_ERRNO(req) ({ \
+ enum tevent_req_state __TRETE_state; \
+ uint64_t __TRETE_uint64; \
+ errno_t __TRETE_err; \
+ errno_t __TRETE_ret = EOK; \
\
- if (tevent_req_is_error(req, &TRROEstate, &TRROEuint64)) { \
- TRROEerr = (errno_t)TRROEuint64; \
- switch (TRROEstate) { \
+ if (tevent_req_is_error(req, &__TRETE_state, &__TRETE_uint64)) { \
+ __TRETE_err = (errno_t)__TRETE_uint64; \
+ switch (__TRETE_state) { \
case TEVENT_REQ_USER_ERROR: \
- if (TRROEerr == 0) { \
- return ERR_INTERNAL; \
+ if (__TRETE_err == 0) { \
+ __TRETE_ret = ERR_INTERNAL; \
} \
- return TRROEerr; \
+ __TRETE_ret = __TRETE_err; \
+ break; \
case TEVENT_REQ_TIMED_OUT: \
- return ETIMEDOUT; \
+ __TRETE_ret = ETIMEDOUT; \
+ break; \
+ case TEVENT_REQ_NO_MEMORY: \
+ __TRETE_ret = ENOMEM; \
+ break; \
default: \
- return ERR_INTERNAL; \
+ __TRETE_ret = ERR_INTERNAL; \
} \
} \
+ __TRETE_ret; \
+})
+
+#define TEVENT_REQ_RETURN_ON_ERROR(req) do { \
+ errno_t TRROEret = TEVENT_REQ_ERROR_TO_ERRNO(req); \
+ if (TRROEret != EOK) { \
+ return TRROEret; \
+ } \
} while (0)
#define OUT_OF_ID_RANGE(id, min, max) \
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index 48badb914d7..21eb43f878d 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -157,6 +157,7 @@ struct err_string error_to_str[] = {
{ "Certificate authority file not found"}, /* ERR_CA_DB_NOT_FOUND */
{ "Server failure"}, /* ERR_SERVER_FAILURE */
+ { "No more servers to try"}, /* ERR_NO_MORE_SERVERS */
{ "ERR_LAST" } /* ERR_LAST */
};
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index 244ade63341..aa73626343c 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -182,6 +182,7 @@ enum sssd_errors {
ERR_CA_DB_NOT_FOUND,
ERR_SERVER_FAILURE,
+ ERR_NO_MORE_SERVERS,
ERR_LAST /* ALWAYS LAST */
};