summaryrefslogtreecommitdiff
path: root/src/providers/ipa
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2013-04-09 17:40:40 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-05-03 20:25:46 +0200
commit5a4239490c7fb7d732180a9d40f27f0247c56631 (patch)
tree5d118934b4a922a1c549f1cc96b31c09ee60be64 /src/providers/ipa
parent04868f1573f4b26ef34610b6d7069172f93bd8ab (diff)
downloadsssd-5a4239490c7fb7d732180a9d40f27f0247c56631.tar.gz
sssd-5a4239490c7fb7d732180a9d40f27f0247c56631.tar.bz2
sssd-5a4239490c7fb7d732180a9d40f27f0247c56631.zip
dyndns: new option dyndns_refresh_interval
This new options adds the possibility of updating the DNS entries periodically regardless if they have changed or not. This feature will be useful mainly in AD environments where the Windows clients periodically update their DNS records.
Diffstat (limited to 'src/providers/ipa')
-rw-r--r--src/providers/ipa/ipa_common.c4
-rw-r--r--src/providers/ipa/ipa_dyndns.c107
-rw-r--r--src/providers/ipa/ipa_dyndns.h3
-rw-r--r--src/providers/ipa/ipa_opts.h1
4 files changed, 114 insertions, 1 deletions
diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index 51750b2a..baece274 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -28,6 +28,7 @@
#include "db/sysdb_selinux.h"
#include "providers/ipa/ipa_common.h"
+#include "providers/ipa/ipa_dyndns.h"
#include "providers/ldap/sdap_async_private.h"
#include "providers/dp_dyndns.h"
#include "util/sss_krb5.h"
@@ -1018,7 +1019,8 @@ errno_t ipa_get_dyndns_options(struct be_ctx *be_ctx,
bool update;
int ttl;
- ret = be_nsupdate_init(ctx, be_ctx, ipa_dyndns_opts, &ctx->dyndns_ctx);
+ ret = be_nsupdate_init(ctx, be_ctx, ipa_dyndns_opts, ipa_dyndns_timer,
+ ctx, &ctx->dyndns_ctx);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("Cannot initialize IPA dyndns opts [%d]: %s\n",
diff --git a/src/providers/ipa/ipa_dyndns.c b/src/providers/ipa/ipa_dyndns.c
index 8023b533..52b8051b 100644
--- a/src/providers/ipa/ipa_dyndns.c
+++ b/src/providers/ipa/ipa_dyndns.c
@@ -55,6 +55,98 @@ errno_t ipa_dyndns_init(struct be_ctx *be_ctx,
return EOK;
}
+struct ipa_dyndns_timer_ctx {
+ struct sdap_id_op *sdap_op;
+ struct tevent_context *ev;
+
+ struct ipa_options *ctx;
+};
+
+static void ipa_dyndns_timer_connected(struct tevent_req *req);
+
+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) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
+ /* Not much we can do */
+ 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);
+}
+
+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;
+
+ ctx = timer_ctx->ctx;
+ ev = timer_ctx->ev;
+ ctx->dyndns_ctx->timer_in_progress = false;
+
+ ret = sdap_id_op_connect_recv(req, &dp_error);
+ 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);
+ }
+ 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);
+}
+
static struct tevent_req *ipa_dyndns_update_send(struct ipa_options *ctx);
static errno_t ipa_dyndns_update_recv(struct tevent_req *req);
@@ -63,6 +155,11 @@ 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"));
@@ -109,6 +206,16 @@ ipa_dyndns_update_send(struct ipa_options *ctx)
}
state->ipa_ctx = ctx;
+ 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);
+
dns_zone = dp_opt_get_string(ctx->basic, IPA_DOMAIN);
if (!dns_zone) {
ret = EIO;
diff --git a/src/providers/ipa/ipa_dyndns.h b/src/providers/ipa/ipa_dyndns.h
index d86c6634..ced3f097 100644
--- a/src/providers/ipa/ipa_dyndns.h
+++ b/src/providers/ipa/ipa_dyndns.h
@@ -25,6 +25,9 @@
#ifndef IPA_DYNDNS_H_
#define IPA_DYNDNS_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/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index 392fcd86..57911082 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -53,6 +53,7 @@ struct dp_option ipa_basic_opts[] = {
struct dp_option ipa_dyndns_opts[] = {
{ "dyndns_update", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+ { "dyndns_refresh_interval", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER },
{ "dyndns_iface", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "dyndns_ttl", DP_OPT_NUMBER, { .number = 1200 }, NULL_NUMBER },
DP_OPTION_TERMINATOR