From df9e4802c060fc21d38f238265805092352e5c95 Mon Sep 17 00:00:00 2001 From: Tomas Halman Date: Dec 05 2018 19:46:51 +0000 Subject: DYNDNS: Convert dyndns timer to be_ptask We have API for periodic tasks and we want to use it instead of tevent timers. Resolves: https://pagure.io/SSSD/sssd/issue/1944 Reviewed-by: Pavel Březina --- diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h index 2c52c99..cb4dda7 100644 --- a/src/providers/ad/ad_common.h +++ b/src/providers/ad/ad_common.h @@ -191,7 +191,6 @@ ad_get_dom_ldap_conn(struct ad_id_ctx *ad_ctx, struct sss_domain_info *dom); /* AD dynamic DNS updates */ errno_t ad_dyndns_init(struct be_ctx *be_ctx, struct ad_options *ctx); -void ad_dyndns_timer(void *pvt); errno_t ad_sudo_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c index 0019048..52a4e4d 100644 --- a/src/providers/ad/ad_dyndns.c +++ b/src/providers/ad/ad_dyndns.c @@ -29,12 +29,33 @@ #include "providers/be_dyndns.h" #include "providers/ad/ad_common.h" -void ad_dyndns_update(void *pvt); +struct ad_dyndns_update_state { + struct ad_options *ad_ctx; + struct sdap_id_op *sdap_op; +}; + +static void +ad_dyndns_sdap_update_done(struct tevent_req *subreq); + +static struct tevent_req * +ad_dyndns_update_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt); + +static errno_t +ad_dyndns_update_recv(struct tevent_req *req); + +static void +ad_dyndns_update_connect_done(struct tevent_req *subreq); errno_t ad_dyndns_init(struct be_ctx *be_ctx, struct ad_options *ad_opts) { errno_t ret; + const time_t ptask_first_delay = 10; + int period; /* nsupdate is available. Dynamic updates * are supported @@ -70,110 +91,42 @@ errno_t ad_dyndns_init(struct be_ctx *be_ctx, return EINVAL; } - ret = be_nsupdate_init_timer(ad_opts->dyndns_ctx, be_ctx->ev, - ad_dyndns_timer, ad_opts); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up periodic update\n"); - return ret; - } - - ret = be_add_online_cb(be_ctx, be_ctx, - ad_dyndns_update, - ad_opts, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up online callback\n"); - return ret; - } - - return EOK; -} - -static void ad_dyndns_timer_connected(struct tevent_req *req); - -void ad_dyndns_timer(void *pvt) -{ - struct ad_options *ctx = talloc_get_type(pvt, struct ad_options); - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; - struct tevent_req *req; - - req = sdap_dyndns_timer_conn_send(ctx, sdap_ctx->be->ev, sdap_ctx, - ctx->dyndns_ctx); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); - /* Not much we can do. Just attempt to reschedule */ - be_nsupdate_timer_schedule(sdap_ctx->be->ev, ctx->dyndns_ctx); - return; - } - tevent_req_set_callback(req, ad_dyndns_timer_connected, ctx); -} - -static void ad_dyndns_timer_connected(struct tevent_req *req) -{ - errno_t ret; - struct ad_options *ctx = tevent_req_callback_data(req, struct ad_options); - - ret = sdap_dyndns_timer_conn_recv(req); - talloc_zfree(req); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to AD: [%d](%s)\n", ret, sss_strerror(ret)); - return; - } - - return ad_dyndns_update(ctx); -} - -static struct tevent_req *ad_dyndns_update_send(struct ad_options *ctx); -static errno_t ad_dyndns_update_recv(struct tevent_req *req); -static void ad_dyndns_nsupdate_done(struct tevent_req *req); - -void ad_dyndns_update(void *pvt) -{ - struct ad_options *ctx = talloc_get_type(pvt, struct ad_options); - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; - struct tevent_req *req; - - /* Schedule timer after provider went offline */ - be_nsupdate_timer_schedule(sdap_ctx->be->ev, ctx->dyndns_ctx); - - req = ad_dyndns_update_send(ctx); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not update DNS\n"); - return; + period = dp_opt_get_int(ad_opts->dyndns_ctx->opts, DP_OPT_DYNDNS_REFRESH_INTERVAL); + if (period == 0) { + DEBUG(SSSDBG_OP_FAILURE, "Dyndns update task can't be started, " + "dyndns_refresh_interval is 0\n"); + return EINVAL; } - tevent_req_set_callback(req, ad_dyndns_nsupdate_done, NULL); -} + ret = be_ptask_create(ad_opts, be_ctx, period, ptask_first_delay, 0, 0, period, + BE_PTASK_OFFLINE_DISABLE, 0, + ad_dyndns_update_send, ad_dyndns_update_recv, ad_opts, + "Dyndns update", NULL); -static void ad_dyndns_nsupdate_done(struct tevent_req *req) -{ - int ret = ad_dyndns_update_recv(req); - talloc_free(req); if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Updating DNS entry failed [%d]: %s\n", - ret, sss_strerror(ret)); - return; + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup ptask " + "[%d]: %s\n", ret, sss_strerror(ret)); } - - DEBUG(SSSDBG_TRACE_FUNC, "DNS update finished\n"); + return ret; } -struct ad_dyndns_update_state { - struct ad_options *ad_ctx; -}; - -static void ad_dyndns_sdap_update_done(struct tevent_req *subreq); - static struct tevent_req * -ad_dyndns_update_send(struct ad_options *ctx) +ad_dyndns_update_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt) { int ret; + struct ad_options *ctx; struct ad_dyndns_update_state *state; struct tevent_req *req, *subreq; - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; - LDAPURLDesc *lud; + struct sdap_id_ctx *sdap_ctx; DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n"); + ctx = talloc_get_type(pvt, struct ad_options); + sdap_ctx = ctx->id_ctx->sdap_id_ctx; + req = tevent_req_create(ctx, &state, struct ad_dyndns_update_state); if (req == NULL) { return NULL; @@ -190,6 +143,64 @@ ad_dyndns_update_send(struct ad_options *ctx) } state->ad_ctx->dyndns_ctx->last_refresh = time(NULL); + /* Make sure to have a valid LDAP connection */ + state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache); + if (state->sdap_op == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); + ret = ENOMEM; + goto done; + } + + 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)); + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(subreq, ad_dyndns_update_connect_done, req); + ret = EOK; +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, sdap_ctx->be->ev); + } + return req; +} + +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; + struct sdap_id_ctx *sdap_ctx; + struct ad_options *ctx; + LDAPURLDesc *lud; + + 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); + talloc_zfree(subreq); + + if (ret != EOK) { + if (dp_error == DP_ERR_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " + "dynamic DNS update is skipped in offline mode.\n"); + tevent_req_error(req, 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, ERR_NETWORK_IO); + } + 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, @@ -233,19 +244,17 @@ ad_dyndns_update_send(struct ad_options *ctx) if (!subreq) { ret = EIO; DEBUG(SSSDBG_OP_FAILURE, - "sdap_id_op_connect_send failed: [%d](%s)\n", + "sdap_dyndns_update_send failed: [%d](%s)\n", ret, sss_strerror(ret)); goto done; } tevent_req_set_callback(subreq, ad_dyndns_sdap_update_done, req); - ret = EOK; done: if (ret != EOK) { tevent_req_error(req, ret); tevent_req_post(req, sdap_ctx->be->ev); } - return req; } static void ad_dyndns_sdap_update_done(struct tevent_req *subreq) diff --git a/src/providers/be_dyndns.c b/src/providers/be_dyndns.c index 4c9bbe6..bcc3e9b 100644 --- a/src/providers/be_dyndns.c +++ b/src/providers/be_dyndns.c @@ -1129,45 +1129,6 @@ be_nsupdate_recv(struct tevent_req *req, int *child_status) return EOK; } -static void be_nsupdate_timer(struct tevent_context *ev, - struct tevent_timer *te, - struct timeval current_time, - void *pvt) -{ - struct be_nsupdate_ctx *ctx = talloc_get_type(pvt, struct be_nsupdate_ctx); - - talloc_zfree(ctx->refresh_timer); - ctx->timer_callback(ctx->timer_pvt); - - /* timer_callback is responsible for calling be_nsupdate_timer_schedule - * again */ -} - -void be_nsupdate_timer_schedule(struct tevent_context *ev, - struct be_nsupdate_ctx *ctx) -{ - int refresh; - struct timeval tv; - - if (ctx->refresh_timer) { - DEBUG(SSSDBG_FUNC_DATA, "Timer already scheduled\n"); - return; - } - - refresh = dp_opt_get_int(ctx->opts, DP_OPT_DYNDNS_REFRESH_INTERVAL); - if (refresh == 0) return; - DEBUG(SSSDBG_FUNC_DATA, "Scheduling timer in %d seconds\n", refresh); - - tv = tevent_timeval_current_ofs(refresh, 0); - ctx->refresh_timer = tevent_add_timer(ev, ctx, tv, - be_nsupdate_timer, ctx); - - if (!ctx->refresh_timer) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to add dyndns refresh timer event\n"); - } -} - errno_t be_nsupdate_check(void) { @@ -1242,20 +1203,6 @@ be_nsupdate_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, return ERR_OK; } -errno_t be_nsupdate_init_timer(struct be_nsupdate_ctx *ctx, - struct tevent_context *ev, - nsupdate_timer_fn_t timer_callback, - void *timer_pvt) -{ - if (ctx == NULL) return EINVAL; - - ctx->timer_callback = timer_callback; - ctx->timer_pvt = timer_pvt; - be_nsupdate_timer_schedule(ev, ctx); - - return ERR_OK; -} - static bool match_ip(const struct sockaddr *sa, const struct sockaddr *sb) { diff --git a/src/providers/be_dyndns.h b/src/providers/be_dyndns.h index 9f39e5d..85bfb61 100644 --- a/src/providers/be_dyndns.h +++ b/src/providers/be_dyndns.h @@ -70,14 +70,6 @@ be_nsupdate_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, struct dp_option *defopts, struct be_nsupdate_ctx **_ctx); -errno_t be_nsupdate_init_timer(struct be_nsupdate_ctx *ctx, - struct tevent_context *ev, - nsupdate_timer_fn_t timer_callback, - void *timer_pvt); - -void be_nsupdate_timer_schedule(struct tevent_context *ev, - struct be_nsupdate_ctx *ctx); - errno_t sss_iface_addr_list_get(TALLOC_CTX *mem_ctx, const char *ifname, struct sss_iface_addr **_addrlist); diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index dc91077..a692b0d 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -30,12 +30,34 @@ #include "providers/data_provider.h" #include "providers/be_dyndns.h" -void ipa_dyndns_update(void *pvt); +struct ipa_dyndns_update_state { + struct ipa_options *ipa_ctx; + struct sdap_id_op *sdap_op; +}; + +static void +ipa_dyndns_sdap_update_done(struct tevent_req *subreq); + +static struct tevent_req * +ipa_dyndns_update_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt); + +static errno_t +ipa_dyndns_update_recv(struct tevent_req *req); + +static void +ipa_dyndns_update_connect_done(struct tevent_req *subreq); + errno_t ipa_dyndns_init(struct be_ctx *be_ctx, struct ipa_options *ctx) { errno_t ret; + const time_t ptask_first_delay = 10; + int period; ctx->be_res = be_ctx->be_res; if (ctx->be_res == NULL) { @@ -44,123 +66,114 @@ errno_t ipa_dyndns_init(struct be_ctx *be_ctx, return EINVAL; } - ret = be_nsupdate_init_timer(ctx->dyndns_ctx, be_ctx->ev, - ipa_dyndns_timer, ctx); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up periodic update\n"); - return ret; + period = dp_opt_get_int(ctx->dyndns_ctx->opts, DP_OPT_DYNDNS_REFRESH_INTERVAL); + if (period == 0) { + DEBUG(SSSDBG_OP_FAILURE, "Dyndns task can't be started, " + "dyndns_refresh_interval is 0\n"); + return EINVAL; } - - ret = be_add_online_cb(be_ctx, be_ctx, - ipa_dyndns_update, - ctx, NULL); + ret = be_ptask_create(ctx, be_ctx, period, ptask_first_delay, 0, 0, period, + BE_PTASK_OFFLINE_DISABLE, 0, + ipa_dyndns_update_send, ipa_dyndns_update_recv, ctx, + "Dyndns update", NULL); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up online callback\n"); - return ret; + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to setup ptask " + "[%d]: %s\n", ret, sss_strerror(ret)); } - - return EOK; + return ret; } -struct ipa_dyndns_timer_ctx { - struct sdap_id_op *sdap_op; - struct tevent_context *ev; - +static struct tevent_req * +ipa_dyndns_update_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct be_ptask *be_ptask, + void *pvt) +{ + int ret; struct ipa_options *ctx; -}; + struct ipa_dyndns_update_state *state; + struct tevent_req *req, *subreq; + struct sdap_id_ctx *sdap_ctx; -static void ipa_dyndns_timer_connected(struct tevent_req *req); + DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n"); -void ipa_dyndns_timer(void *pvt) -{ - struct ipa_options *ctx = talloc_get_type(pvt, struct ipa_options); - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; - struct tevent_req *req; + ctx = talloc_get_type(pvt, struct ipa_options); + sdap_ctx = ctx->id_ctx->sdap_id_ctx; - req = sdap_dyndns_timer_conn_send(ctx, sdap_ctx->be->ev, sdap_ctx, - ctx->dyndns_ctx); + req = tevent_req_create(ctx, &state, struct ipa_dyndns_update_state); if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); - /* Not much we can do. Just attempt to reschedule */ - be_nsupdate_timer_schedule(sdap_ctx->be->ev, ctx->dyndns_ctx); - return; + return NULL; } - tevent_req_set_callback(req, ipa_dyndns_timer_connected, ctx); -} - -static void ipa_dyndns_timer_connected(struct tevent_req *req) -{ - errno_t ret; - struct ipa_options *ctx = tevent_req_callback_data(req, - struct ipa_options); + state->ipa_ctx = ctx; - ret = sdap_dyndns_timer_conn_recv(req); - talloc_zfree(req); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to IPA: [%d](%s)\n", - ret, sss_strerror(ret)); - return; + if (ctx->dyndns_ctx->last_refresh + 60 > time(NULL) || + ctx->dyndns_ctx->timer_in_progress) { + DEBUG(SSSDBG_FUNC_DATA, "Last periodic update ran recently or timer " + "in progress, not scheduling another update\n"); + tevent_req_done(req); + tevent_req_post(req, sdap_ctx->be->ev); + return req; } + state->ipa_ctx->dyndns_ctx->last_refresh = time(NULL); - return ipa_dyndns_update(ctx); -} - -static struct tevent_req *ipa_dyndns_update_send(struct ipa_options *ctx); -static errno_t ipa_dyndns_update_recv(struct tevent_req *req); - -static void ipa_dyndns_nsupdate_done(struct tevent_req *subreq); - -void ipa_dyndns_update(void *pvt) -{ - struct ipa_options *ctx = talloc_get_type(pvt, struct ipa_options); - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; - - /* Schedule timer after provider went offline */ - be_nsupdate_timer_schedule(sdap_ctx->be->ev, ctx->dyndns_ctx); - - struct tevent_req *req = ipa_dyndns_update_send(ctx); - if (req == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not update DNS\n"); - return; + /* Make sure to have a valid LDAP connection */ + state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache); + if (state->sdap_op == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); + ret = ENOMEM; + goto done; } - tevent_req_set_callback(req, ipa_dyndns_nsupdate_done, NULL); -} -static void ipa_dyndns_nsupdate_done(struct tevent_req *req) -{ - int ret = ipa_dyndns_update_recv(req); - talloc_free(req); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Updating DNS entry failed [%d]: %s\n", + 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 = ENOMEM; + goto done; } - - DEBUG(SSSDBG_OP_FAILURE, "DNS update finished\n"); + tevent_req_set_callback(subreq, ipa_dyndns_update_connect_done, req); + ret = EOK; +done: + if (ret != EOK) { + tevent_req_error(req, ret); + tevent_req_post(req, sdap_ctx->be->ev); + } + return req; } -struct ipa_dyndns_update_state { - struct ipa_options *ipa_ctx; -}; - -static void ipa_dyndns_sdap_update_done(struct tevent_req *subreq); - -static struct tevent_req * -ipa_dyndns_update_send(struct ipa_options *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; struct ipa_dyndns_update_state *state; - struct tevent_req *req, *subreq; - struct sdap_id_ctx *sdap_ctx = ctx->id_ctx->sdap_id_ctx; + struct sdap_id_ctx *sdap_ctx; - DEBUG(SSSDBG_TRACE_FUNC, "Performing update\n"); + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ipa_dyndns_update_state); - req = tevent_req_create(ctx, &state, struct ipa_dyndns_update_state); - if (req == NULL) { - return NULL; + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + + if (ret != EOK) { + if (dp_error == DP_ERR_OFFLINE) { + DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " + "dynamic DNS update is skipped in offline mode.\n"); + tevent_req_error(req, 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, ERR_NETWORK_IO); + } + return; } - state->ipa_ctx = ctx; + + ctx = state->ipa_ctx; + sdap_ctx = ctx->id_ctx->sdap_id_ctx; /* The following three checks are here to prevent SEGFAULT * from ticket #3076. */ @@ -182,16 +195,6 @@ ipa_dyndns_update_send(struct ipa_options *ctx) goto done; } - if (ctx->dyndns_ctx->last_refresh + 60 > time(NULL) || - ctx->dyndns_ctx->timer_in_progress) { - DEBUG(SSSDBG_FUNC_DATA, "Last periodic update ran recently or timer " - "in progress, not scheduling another update\n"); - tevent_req_done(req); - tevent_req_post(req, sdap_ctx->be->ev); - return req; - } - state->ipa_ctx->dyndns_ctx->last_refresh = time(NULL); - if (strncmp(ctx->service->sdap->uri, "ldap://", 7) != 0) { DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected format of LDAP URI.\n"); @@ -228,7 +231,6 @@ done: tevent_req_error(req, ret); tevent_req_post(req, sdap_ctx->be->ev); } - return req; } static void ipa_dyndns_sdap_update_done(struct tevent_req *subreq) diff --git a/src/providers/ipa/ipa_dyndns.h b/src/providers/ipa/ipa_dyndns.h index 38a68c0..d6873b7 100644 --- a/src/providers/ipa/ipa_dyndns.h +++ b/src/providers/ipa/ipa_dyndns.h @@ -29,9 +29,6 @@ #include "providers/ipa/ipa_common.h" #include "providers/backend.h" -void ipa_dyndns_update(void *pvt); -void ipa_dyndns_timer(void *pvt); - errno_t ipa_dyndns_init(struct be_ctx *be_ctx, struct ipa_options *ctx); diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c index 20d97ca..ada9659 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -813,110 +813,3 @@ sdap_dyndns_get_addrs_recv(struct tevent_req *req, *_addresses = talloc_steal(mem_ctx, state->addresses); return EOK; } - -struct sdap_dyndns_timer_state { - struct tevent_context *ev; - struct sdap_id_ctx *sdap_ctx; - struct be_nsupdate_ctx *dyndns_ctx; - - struct sdap_id_op *sdap_op; -}; - -static void sdap_dyndns_timer_conn_done(struct tevent_req *req); - -struct tevent_req * -sdap_dyndns_timer_conn_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *sdap_ctx, - struct be_nsupdate_ctx *dyndns_ctx) -{ - struct sdap_dyndns_timer_state *state; - struct tevent_req *req; - struct tevent_req *subreq; - errno_t ret; - - req = tevent_req_create(mem_ctx, &state, struct sdap_dyndns_timer_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sdap_ctx = sdap_ctx; - state->dyndns_ctx = dyndns_ctx; - - /* In order to prevent the connection triggering an - * online callback which would in turn trigger a concurrent DNS - * update - */ - state->dyndns_ctx->timer_in_progress = true; - - /* Make sure to have a valid LDAP connection */ - state->sdap_op = sdap_id_op_create(state, state->sdap_ctx->conn->conn_cache); - if (state->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); - ret = ENOMEM; - goto fail; - } - - subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); - if (subreq == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n", - ret, sss_strerror(ret)); - ret = ENOMEM; - goto fail; - } - tevent_req_set_callback(subreq, sdap_dyndns_timer_conn_done, req); - return req; - -fail: - dyndns_ctx->timer_in_progress = false; - be_nsupdate_timer_schedule(ev, dyndns_ctx); - tevent_req_error(req, ret); - tevent_req_post(req, ev); - return req; -} - -static void -sdap_dyndns_timer_conn_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct sdap_dyndns_timer_state *state = tevent_req_data(req, - struct sdap_dyndns_timer_state); - errno_t ret; - int dp_error; - - state->dyndns_ctx->timer_in_progress = false; - - ret = sdap_id_op_connect_recv(subreq, &dp_error); - talloc_zfree(subreq); - if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, " - "dynamic DNS update is skipped in offline mode.\n"); - /* Another timer will be scheduled when provider goes online */ - tevent_req_error(req, ERR_DYNDNS_OFFLINE); - } else { - DEBUG(SSSDBG_OP_FAILURE, - "Failed to connect to LDAP server: [%d](%s)\n", - ret, sss_strerror(ret)); - - /* Just schedule another dyndns retry */ - be_nsupdate_timer_schedule(state->ev, state->dyndns_ctx); - tevent_req_error(req, ERR_NETWORK_IO); - } - return; - } - - /* All OK, schedule another refresh and let the user call its - * provider-specific update - */ - be_nsupdate_timer_schedule(state->ev, state->dyndns_ctx); - tevent_req_done(req); -} - -errno_t -sdap_dyndns_timer_conn_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - return EOK; -} diff --git a/src/providers/ldap/sdap_dyndns.h b/src/providers/ldap/sdap_dyndns.h index b31c373..c66e265 100644 --- a/src/providers/ldap/sdap_dyndns.h +++ b/src/providers/ldap/sdap_dyndns.h @@ -45,17 +45,4 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, errno_t sdap_dyndns_update_recv(struct tevent_req *req); -/* Connects to the LDAP server in order to read the address from the - * socket and be able to perform dynamic DNS updates. Reschedules the - * task automatically on errors and sets/resets the timer_in_progress - * guard in be_nsupdate_ctx. - */ -struct tevent_req * -sdap_dyndns_timer_conn_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sdap_id_ctx *sdap_ctx, - struct be_nsupdate_ctx *dyndns_ctx); - -errno_t sdap_dyndns_timer_conn_recv(struct tevent_req *req); - #endif /* SDAP_DYNDNS_H_ */ diff --git a/src/tests/cmocka/test_dyndns.c b/src/tests/cmocka/test_dyndns.c index 491b437..5d4c366 100644 --- a/src/tests/cmocka/test_dyndns.c +++ b/src/tests/cmocka/test_dyndns.c @@ -885,49 +885,6 @@ void dyndns_test_timeout(void **state) talloc_free(tmp_ctx); } -void dyndns_test_timer(void *pvt) -{ - struct dyndns_test_ctx *ctx = talloc_get_type(pvt, struct dyndns_test_ctx); - static int ncalls = 0; - - ncalls++; - if (ncalls == 1) { - be_nsupdate_timer_schedule(ctx->tctx->ev, ctx->update_ctx); - } else if (ncalls == 2) { - ctx->tctx->done = true; - } - ctx->tctx->error = ERR_OK; -} - -void dyndns_test_interval(void **state) -{ - errno_t ret; - TALLOC_CTX *tmp_ctx; - - tmp_ctx = talloc_new(global_talloc_context); - assert_non_null(tmp_ctx); - check_leaks_push(tmp_ctx); - - ret = be_nsupdate_init(tmp_ctx, dyndns_test_ctx->be_ctx, NULL, - &dyndns_test_ctx->update_ctx); - assert_int_equal(ret, EOK); - - ret = be_nsupdate_init_timer(dyndns_test_ctx->update_ctx, - dyndns_test_ctx->be_ctx->ev, - dyndns_test_timer, dyndns_test_ctx); - assert_int_equal(ret, EOK); - - /* Wait until the timer hits */ - ret = test_ev_loop(dyndns_test_ctx->tctx); - DEBUG(SSSDBG_TRACE_LIBS, - "Child request returned [%d]: %s\n", ret, strerror(ret)); - assert_int_equal(ret, ERR_OK); - - talloc_free(dyndns_test_ctx->update_ctx); - assert_true(check_leaks_pop(tmp_ctx) == true); - talloc_free(tmp_ctx); -} - /* Testsuite setup and teardown */ static int dyndns_test_setup(void **state) { @@ -1016,9 +973,6 @@ int main(int argc, const char *argv[]) cmocka_unit_test_setup_teardown(dyndns_test_timeout, dyndns_test_setup, dyndns_test_teardown), - cmocka_unit_test_setup_teardown(dyndns_test_interval, - dyndns_test_setup, - dyndns_test_teardown), /* Dynamic DNS dualstack unit tests*/ cmocka_unit_test_setup_teardown(dyndns_test_dualstack,