>From 3928975199d038a5f941051224c27601266bb03b Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 30 Apr 2013 18:55:29 +0200 Subject: [PATCH 1/2] Split out the common code from timed DNS updates --- src/providers/ipa/ipa_dyndns.c | 72 +++++--------------------- src/providers/ldap/sdap_dyndns.c | 108 +++++++++++++++++++++++++++++++++++++++ src/providers/ldap/sdap_dyndns.h | 13 +++++ 3 files changed, 133 insertions(+), 60 deletions(-) diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c index b752f116f5149f1c576a017afd1091a225d8277a..81dae94a5029be39501ff321db07cd18439395f5 100644 --- a/src/providers/ipa/ipa_dyndns.c +++ b/src/providers/ipa/ipa_dyndns.c @@ -69,81 +69,33 @@ 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; - struct ipa_dyndns_timer_ctx *timer_ctx; - errno_t ret; - timer_ctx = talloc_zero(ctx, struct ipa_dyndns_timer_ctx); - if (timer_ctx == NULL) { + 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 */ + /* Not much we can do. Just attempt to reschedule */ + be_nsupdate_timer_schedule(sdap_ctx->be->ev, ctx->dyndns_ctx); return; } - timer_ctx->ev = sdap_ctx->be->ev; - timer_ctx->ctx = ctx; - - /* In order to prevent the connection triggering an - * online callback which would in turn trigger a concurrent DNS - * update - */ - ctx->dyndns_ctx->timer_in_progress = true; - - /* Make sure to have a valid LDAP connection */ - timer_ctx->sdap_op = sdap_id_op_create(timer_ctx, sdap_ctx->conn_cache); - if (timer_ctx->sdap_op == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed\n")); - goto fail; - } - - req = sdap_id_op_connect_send(timer_ctx->sdap_op, timer_ctx, &ret); - if (req == NULL) { - DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_connect_send failed: [%d](%s)\n", - ret, sss_strerror(ret))); - goto fail; - } - tevent_req_set_callback(req, ipa_dyndns_timer_connected, timer_ctx); - return; - -fail: - ctx->dyndns_ctx->timer_in_progress = false; - be_nsupdate_timer_schedule(timer_ctx->ev, ctx->dyndns_ctx); - talloc_free(timer_ctx); + tevent_req_set_callback(req, ipa_dyndns_timer_connected, ctx); } static void ipa_dyndns_timer_connected(struct tevent_req *req) { errno_t ret; - int dp_error; - struct ipa_dyndns_timer_ctx *timer_ctx = tevent_req_callback_data(req, - struct ipa_dyndns_timer_ctx); - struct tevent_context *ev; - struct ipa_options *ctx; + struct ipa_options *ctx = tevent_req_callback_data(req, + struct ipa_options); - ctx = timer_ctx->ctx; - ev = timer_ctx->ev; - ctx->dyndns_ctx->timer_in_progress = false; - - ret = sdap_id_op_connect_recv(req, &dp_error); + ret = sdap_dyndns_timer_conn_recv(req); talloc_zfree(req); - talloc_free(timer_ctx); if (ret != EOK) { - if (dp_error == DP_ERR_OFFLINE) { - DEBUG(SSSDBG_MINOR_FAILURE, ("No IPA server is available, " - "dynamic DNS update is skipped in offline mode.\n")); - /* Another timer will be scheduled when provider goes online - * and ipa_dyndns_update() is called */ - } 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(ev, ctx->dyndns_ctx); - } + DEBUG(SSSDBG_OP_FAILURE, + ("Failed to connect to IPA: [%d](%s)\n", + ret, sss_strerror(ret))); return; } - /* all OK just call ipa_dyndns_update and schedule another refresh */ - be_nsupdate_timer_schedule(ev, ctx->dyndns_ctx); return ipa_dyndns_update(ctx); } diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c index 98d9d15122233073e79669c10cfa0ac9a4f2b659..22d9e7911b1bd5a00967a76dc9fcdbf5b3e340e4 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -627,3 +627,111 @@ 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_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 66de64a59c9b5408641b7f4c32a3e1dc814c80af..7aaff5d2c69fbda55fff5208c97b953b970c55cc 100644 --- a/src/providers/ldap/sdap_dyndns.h +++ b/src/providers/ldap/sdap_dyndns.h @@ -47,4 +47,17 @@ 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_ */ -- 1.8.2.1