[SSSD] [PATCH] Add offline callback and fix info file handling (rebased for master)

Sumit Bose sbose at redhat.com
Thu May 27 14:16:36 UTC 2010


Hi,

this series of patches is basically a rebase of the previous post for
1.2. There was only conflict which git couldn't resolve on it own, but
on code changes were needed.

bye,
Sumit
-------------- next part --------------
From a0f373a9b00cd9341855835ad9ed967fd8bb8264 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 27 May 2010 09:48:57 +0200
Subject: [PATCH 01/10] Revert "Create kdcinfo and kpasswdinfo file at startup"

This reverts commit f3c31d11bf365eb6a79c4f698667915a4c81eeb7.
---
 src/providers/ipa/ipa_common.c   |    9 --------
 src/providers/krb5/krb5_common.c |   41 +-------------------------------------
 src/providers/krb5/krb5_common.h |    1 -
 3 files changed, 1 insertions(+), 50 deletions(-)

diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c
index d886983..580b66f 100644
--- a/src/providers/ipa/ipa_common.c
+++ b/src/providers/ipa/ipa_common.c
@@ -503,7 +503,6 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
     char *realm;
     int ret;
     int i;
-    struct tevent_req *req;
 
     tmp_ctx = talloc_new(memctx);
     if (!tmp_ctx) {
@@ -598,14 +597,6 @@ int ipa_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
         goto done;
     }
 
-    req = be_resolve_server_send(memctx, ctx->ev, ctx, "IPA");
-    if (req == NULL) {
-        DEBUG(1, ("be_resolve_server_send failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-    tevent_req_set_callback(req, krb5_init_resolve_done, service->krb5_service);
-
     ret = EOK;
 
 done:
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index da7627c..f038557 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -31,8 +31,6 @@
 #include "providers/dp_backend.h"
 #include "providers/krb5/krb5_common.h"
 
-#define DUMMY_ADDRESS "255.255.255.255"
-
 struct dp_option default_krb5_opts[] = {
     { "krb5_kdcip", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
@@ -290,6 +288,7 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server)
     return;
 }
 
+
 int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
                       const char *service_name, const char *servers,
                       const char *realm, struct krb5_service **_service)
@@ -304,7 +303,6 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
     char *server_spec;
     char *endptr;
     struct servent *servent;
-    struct tevent_req *req;
 
     tmp_ctx = talloc_new(memctx);
     if (!tmp_ctx) {
@@ -427,14 +425,6 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
         goto done;
     }
 
-    req = be_resolve_server_send(memctx, ctx->ev, ctx, service_name);
-    if (req == NULL) {
-        DEBUG(1, ("be_resolve_server_send failed.\n"));
-        ret = ENOMEM;
-        goto done;
-    }
-    tevent_req_set_callback(req, krb5_init_resolve_done, service);
-
     ret = EOK;
 
 done:
@@ -485,32 +475,3 @@ void krb5_finalize(struct tevent_context *ev,
 
     sig_term(signum);
 }
-
-void krb5_init_resolve_done(struct tevent_req *req)
-{
-    struct krb5_service *krb5_service  = tevent_req_callback_data(req,
-                                                           struct krb5_service);
-    int ret;
-    struct fo_server *srv;
-    const char *service_name;
-
-    ret = be_resolve_server_recv(req, &srv);
-    talloc_zfree(req);
-    if (ret) {
-        DEBUG(1, ("be_resolve_server request failed [%d][%s]. "
-                  "Creating dummy info file.\n", ret, strerror(ret)));
-
-        service_name = krb5_service->name;
-        if (strcmp(service_name, "IPA") == 0) {
-            service_name = SSS_KRB5KDC_FO_SRV;
-        }
-        ret = write_krb5info_file(krb5_service->realm, DUMMY_ADDRESS,
-                                  service_name);
-        if (ret != EOK) {
-            DEBUG(2, ("write_krb5info_file failed, "
-                      "authentication might fail.\n"));
-        }
-    }
-
-    return;
-}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index dd7fdf2..87d6168 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -83,5 +83,4 @@ void krb5_finalize(struct tevent_context *ev,
                    int count,
                    void *siginfo,
                    void *private_data);
-void krb5_init_resolve_done(struct tevent_req *req);
 #endif /* __KRB5_COMMON_H__ */
-- 
1.6.6.1

-------------- next part --------------
From f627af5afc87f12d1731dbd6205631afa25d9cd6 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 10:18:33 +0200
Subject: [PATCH 02/10] Refactor data provider callbacks

---
 src/Makefile.am                         |    1 +
 src/providers/data_provider_be.c        |  137 -----------------------
 src/providers/data_provider_callbacks.c |  182 +++++++++++++++++++++++++++++++
 src/providers/dp_backend.h              |   10 +-
 4 files changed, 188 insertions(+), 142 deletions(-)
 create mode 100644 src/providers/data_provider_callbacks.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 86c497e..c7a10e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -399,6 +399,7 @@ sssd_be_SOURCES = \
     providers/data_provider_be.c \
     providers/data_provider_fo.c \
     providers/data_provider_opts.c \
+    providers/data_provider_callbacks.c \
     $(SSSD_FAILOVER_OBJ) \
     $(SSSD_UTIL_OBJ)
 sssd_be_LDADD = $(SSSD_LIBS) $(CARES_LIBS)
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index f952fab..b437af5 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -169,143 +169,6 @@ void be_mark_offline(struct be_ctx *ctx)
     ctx->run_online_cb = true;
 }
 
-
-struct be_conn_online_cb {
-    struct be_conn_online_cb *prev;
-    struct be_conn_online_cb *next;
-
-    be_conn_online_callback_t cb;
-    void *pvt;
-
-    struct be_ctx *be;
-};
-
-static int online_cb_destructor(TALLOC_CTX *ptr);
-int be_add_online_cb(TALLOC_CTX *mem_ctx,
-                     struct be_ctx *ctx,
-                     be_conn_online_callback_t cb,
-                     void *pvt,
-                     struct be_conn_online_cb **online_cb)
-{
-    struct be_conn_online_cb *on_cb;
-
-    if (!ctx || !cb) {
-        return EINVAL;
-    }
-
-    on_cb = talloc(mem_ctx, struct be_conn_online_cb);
-    if (!on_cb) {
-        return ENOMEM;
-    }
-
-    on_cb->cb = cb;
-    on_cb->pvt = pvt;
-    on_cb->be = ctx;
-
-    DLIST_ADD(ctx->online_cb_list, on_cb);
-
-    talloc_set_destructor((TALLOC_CTX *)on_cb, online_cb_destructor);
-
-    /* Make sure we run the callback for the first
-     * connection after startup.
-     */
-    ctx->run_online_cb = true;
-
-    if (online_cb) {
-        *online_cb = on_cb;
-    }
-
-    return EOK;
-}
-
-static int online_cb_destructor(TALLOC_CTX *ptr)
-{
-    struct be_conn_online_cb *cb =
-            talloc_get_type(ptr, struct be_conn_online_cb);
-    DLIST_REMOVE(cb->be->online_cb_list, cb);
-    return 0;
-}
-
-
-struct be_online_cb_ctx {
-    struct be_ctx *be;
-    struct be_conn_online_cb *callback;
-};
-
-static void be_run_online_cb_step(struct tevent_context *ev,
-                                  struct tevent_timer *te,
-                                  struct timeval current_time,
-                                  void *pvt);
-void be_run_online_cb(struct be_ctx *be) {
-    struct timeval soon;
-    struct tevent_timer *te;
-    struct be_online_cb_ctx *cb_ctx;
-
-    if (be->run_online_cb && be->online_cb_list) {
-        /* Reset the flag. We only want to run these
-         * callbacks when transitioning to online
-         */
-        be->run_online_cb = false;
-
-        DEBUG(3, ("Going online. Running callbacks.\n"));
-
-        cb_ctx = talloc(be, struct be_online_cb_ctx);
-        if (!cb_ctx) {
-            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
-            return;
-        }
-        cb_ctx->be = be;
-        cb_ctx->callback = be->online_cb_list;
-
-        /* Delay 30ms so we don't block any other events */
-        soon = tevent_timeval_current_ofs(0, 30000);
-        te = tevent_add_timer(be->ev, cb_ctx, soon,
-                              be_run_online_cb_step,
-                              cb_ctx);
-        if (!te) {
-            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
-            talloc_free(cb_ctx);
-        }
-    }
-}
-
-static void be_run_online_cb_step(struct tevent_context *ev,
-                                  struct tevent_timer *te,
-                                  struct timeval current_time,
-                                  void *pvt)
-{
-    struct be_online_cb_ctx *cb_ctx =
-            talloc_get_type(pvt, struct be_online_cb_ctx);
-    struct tevent_timer *tev;
-    struct timeval soon;
-
-    /* Call the callback */
-    cb_ctx->callback->cb(cb_ctx->callback->pvt);
-
-    if (cb_ctx->callback->next) {
-        cb_ctx->callback = cb_ctx->callback->next;
-
-        /* Delay 30ms so we don't block any other events */
-        soon = tevent_timeval_current_ofs(0, 30000);
-        tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
-                               be_run_online_cb_step,
-                               cb_ctx);
-        if (!te) {
-            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
-            goto final;
-        }
-        return;
-    }
-
-final:
-    /* Steal the timer event onto the be_ctx so it doesn't
-     * get freed with the cb_ctx
-     */
-    talloc_steal(cb_ctx->be, te);
-    talloc_free(cb_ctx);
-}
-
-
 static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
 {
     struct be_client *becli;
diff --git a/src/providers/data_provider_callbacks.c b/src/providers/data_provider_callbacks.c
new file mode 100644
index 0000000..00bc8fd
--- /dev/null
+++ b/src/providers/data_provider_callbacks.c
@@ -0,0 +1,182 @@
+/*
+    SSSD
+
+    Data Provider Process - Callback
+
+    Authors:
+
+        Stephen Gallagher <sgallagh at redhat.com>
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2010 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "util/util.h"
+#include "providers/dp_backend.h"
+
+struct be_cb {
+    struct be_cb *prev;
+    struct be_cb *next;
+
+    be_callback_t cb;
+    void *pvt;
+
+    struct be_cb *list;
+    struct be_ctx *be;
+};
+
+struct be_cb_ctx {
+    struct be_ctx *be;
+    struct be_cb *callback;
+};
+
+static int cb_destructor(TALLOC_CTX *ptr)
+{
+    struct be_cb *cb = talloc_get_type(ptr, struct be_cb);
+    DLIST_REMOVE(cb->list, cb);
+    return 0;
+}
+
+static int be_add_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
+                     be_callback_t cb, void *pvt, struct be_cb **cb_list,
+                     struct be_cb **return_cb)
+{
+    struct be_cb *new_cb;
+
+    if (!ctx || !cb) {
+        return EINVAL;
+    }
+
+    new_cb = talloc(mem_ctx, struct be_cb);
+    if (!new_cb) {
+        return ENOMEM;
+    }
+
+    new_cb->cb = cb;
+    new_cb->pvt = pvt;
+    new_cb->list = *cb_list;
+    new_cb->be = ctx;
+
+    DLIST_ADD(*cb_list, new_cb);
+
+    talloc_set_destructor((TALLOC_CTX *) new_cb, cb_destructor);
+
+    if (return_cb) {
+        *return_cb = new_cb;
+    }
+
+    return EOK;
+}
+
+static void be_run_cb_step(struct tevent_context *ev, struct tevent_timer *te,
+                           struct timeval current_time, void *pvt)
+{
+    struct be_cb_ctx *cb_ctx = talloc_get_type(pvt, struct be_cb_ctx);
+    struct tevent_timer *tev;
+    struct timeval soon;
+
+    /* Call the callback */
+    cb_ctx->callback->cb(cb_ctx->callback->pvt);
+
+    if (cb_ctx->callback->next) {
+        cb_ctx->callback = cb_ctx->callback->next;
+
+        /* Delay 30ms so we don't block any other events */
+        soon = tevent_timeval_current_ofs(0, 30000);
+        tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
+                               be_run_cb_step,
+                               cb_ctx);
+        if (!te) {
+            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
+            goto final;
+        }
+        return;
+    }
+
+final:
+    /* Steal the timer event onto the be_ctx so it doesn't
+     * get freed with the cb_ctx
+     */
+    talloc_steal(cb_ctx->be, te);
+    talloc_free(cb_ctx);
+}
+
+static errno_t be_run_cb(struct be_ctx *be, struct be_cb *cb_list) {
+    struct timeval soon;
+    struct tevent_timer *te;
+    struct be_cb_ctx *cb_ctx;
+
+    cb_ctx = talloc(be, struct be_cb_ctx);
+    if (!cb_ctx) {
+        DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
+        return ENOMEM;
+    }
+    cb_ctx->be = be;
+    cb_ctx->callback = cb_list;
+
+    /* Delay 30ms so we don't block any other events */
+    soon = tevent_timeval_current_ofs(0, 30000);
+    te = tevent_add_timer(be->ev, cb_ctx, soon,
+                          be_run_cb_step,
+                          cb_ctx);
+    if (!te) {
+        DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
+        talloc_free(cb_ctx);
+        return ENOMEM;
+    }
+
+    return EOK;
+}
+
+int be_add_online_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
+                     void *pvt, struct be_cb **online_cb)
+{
+    int ret;
+
+    ret = be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->online_cb_list, online_cb);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_cb failed.\n"));
+        return ret;
+    }
+
+    /* Make sure we run the callback for the first
+     * connection after startup.
+     */
+    ctx->run_online_cb = true;
+
+    return EOK;
+}
+
+void be_run_online_cb(struct be_ctx *be) {
+    int ret;
+
+    if (be->run_online_cb && be->online_cb_list) {
+        /* Reset the flag. We only want to run these
+         * callbacks when transitioning to online
+         */
+        be->run_online_cb = false;
+
+        DEBUG(3, ("Going online. Running callbacks.\n"));
+
+        ret = be_run_cb(be, be->online_cb_list);
+        if (ret != EOK) {
+            DEBUG(1, ("be_run_cb failed.\n"));
+        }
+
+    } else {
+        DEBUG(9, ("Online call back list is empty, nothing to do.\n"));
+    }
+}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index ec0510e..43d79ba 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -40,7 +40,7 @@ typedef void (*be_shutdown_fn)(void *);
 typedef void (*be_req_fn_t)(struct be_req *);
 typedef void (*be_async_callback_t)(struct be_req *, int, int, const char *);
 
-typedef void (*be_conn_online_callback_t)(void *);
+typedef void (*be_callback_t)(void *);
 
 enum bet_type {
     BET_NULL = 0,
@@ -83,7 +83,7 @@ struct be_client {
 
 struct be_failover_ctx;
 
-struct be_conn_online_cb;
+struct be_cb;
 
 struct be_ctx {
     struct tevent_context *ev;
@@ -97,7 +97,7 @@ struct be_ctx {
     /* Functions to be invoked when the
      * backend goes online
      */
-    struct be_conn_online_cb *online_cb_list;
+    struct be_cb *online_cb_list;
     bool run_online_cb;
 
     struct be_offline_status offstat;
@@ -143,9 +143,9 @@ void be_mark_offline(struct be_ctx *ctx);
 
 int be_add_online_cb(TALLOC_CTX *mem_ctx,
                      struct be_ctx *ctx,
-                     be_conn_online_callback_t cb,
+                     be_callback_t cb,
                      void *pvt,
-                     struct be_conn_online_cb **online_cb);
+                     struct be_cb **online_cb);
 void be_run_online_cb(struct be_ctx *be);
 
 /* from data_provider_fo.c */
-- 
1.6.6.1

-------------- next part --------------
From faa661ba90fcb2408a02a2ddf371bb2adfbe2987 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 10:57:19 +0200
Subject: [PATCH 03/10] Add offline callbacks

---
 src/providers/data_provider_be.c        |    1 +
 src/providers/data_provider_callbacks.c |   22 ++++++++++++++++++++++
 src/providers/dp_backend.h              |   10 +++++++++-
 3 files changed, 32 insertions(+), 1 deletions(-)

diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index b437af5..c2fb0ad 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -167,6 +167,7 @@ void be_mark_offline(struct be_ctx *ctx)
     ctx->offstat.went_offline = time(NULL);
     ctx->offstat.offline = true;
     ctx->run_online_cb = true;
+    be_run_offline_cb(ctx);
 }
 
 static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
diff --git a/src/providers/data_provider_callbacks.c b/src/providers/data_provider_callbacks.c
index 00bc8fd..5552713 100644
--- a/src/providers/data_provider_callbacks.c
+++ b/src/providers/data_provider_callbacks.c
@@ -180,3 +180,25 @@ void be_run_online_cb(struct be_ctx *be) {
         DEBUG(9, ("Online call back list is empty, nothing to do.\n"));
     }
 }
+
+int be_add_offline_cb(TALLOC_CTX *mem_ctx, struct be_ctx *ctx, be_callback_t cb,
+                      void *pvt, struct be_cb **offline_cb)
+{
+    return be_add_cb(mem_ctx, ctx, cb, pvt, &ctx->offline_cb_list, offline_cb);
+}
+
+void be_run_offline_cb(struct be_ctx *be) {
+    int ret;
+
+    if (be->offline_cb_list) {
+        DEBUG(3, ("Going offline. Running callbacks.\n"));
+
+        ret = be_run_cb(be, be->offline_cb_list);
+        if (ret != EOK) {
+            DEBUG(1, ("be_run_cb failed.\n"));
+        }
+
+    } else {
+        DEBUG(9, ("Offline call back list is empty, nothing to do.\n"));
+    }
+}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 43d79ba..fc5e558 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -95,10 +95,11 @@ struct be_ctx {
     struct be_failover_ctx *be_fo;
 
     /* Functions to be invoked when the
-     * backend goes online
+     * backend goes online or offline
      */
     struct be_cb *online_cb_list;
     bool run_online_cb;
+    struct be_cb *offline_cb_list;
 
     struct be_offline_status offstat;
 
@@ -148,6 +149,13 @@ int be_add_online_cb(TALLOC_CTX *mem_ctx,
                      struct be_cb **online_cb);
 void be_run_online_cb(struct be_ctx *be);
 
+int be_add_offline_cb(TALLOC_CTX *mem_ctx,
+                     struct be_ctx *ctx,
+                     be_callback_t cb,
+                     void *pvt,
+                     struct be_cb **online_cb);
+void be_run_offline_cb(struct be_ctx *be);
+
 /* from data_provider_fo.c */
 typedef void (be_svc_callback_fn_t)(void *, struct fo_server *);
 
-- 
1.6.6.1

-------------- next part --------------
From e5e095e23133a1830e8a404c2e3618704633db74 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 11:35:11 +0200
Subject: [PATCH 04/10] Refactor krb5_finalize()

---
 src/providers/krb5/krb5_common.c |   39 ++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index f038557..dfcb502 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -435,22 +435,19 @@ done:
     return ret;
 }
 
-void krb5_finalize(struct tevent_context *ev,
-                   struct tevent_signal *se,
-                   int signum,
-                   int count,
-                   void *siginfo,
-                   void *private_data)
+
+static errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm)
 {
-    char *realm = (char *)private_data;
     int ret;
     errno_t err;
     char *file;
 
-    file = talloc_asprintf(se, KDCINFO_TMPL, realm);
+    file = talloc_asprintf(mem_ctx, KDCINFO_TMPL, realm);
     if(file == NULL) {
-        sig_term(signum);
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        return ENOMEM;
     }
+
     errno = 0;
     ret = unlink(file);
     if (ret == -1) {
@@ -459,10 +456,10 @@ void krb5_finalize(struct tevent_context *ev,
                   err, strerror(err)));
     }
 
-    errno = 0;
-    file = talloc_asprintf(se, KPASSWDINFO_TMPL, realm);
+    file = talloc_asprintf(mem_ctx, KPASSWDINFO_TMPL, realm);
     if(file == NULL) {
-        sig_term(signum);
+        DEBUG(1, ("talloc_asprintf failed.\n"));
+        return ENOMEM;
     }
 
     errno = 0;
@@ -473,5 +470,23 @@ void krb5_finalize(struct tevent_context *ev,
                   err, strerror(err)));
     }
 
+    return EOK;
+}
+
+void krb5_finalize(struct tevent_context *ev,
+                   struct tevent_signal *se,
+                   int signum,
+                   int count,
+                   void *siginfo,
+                   void *private_data)
+{
+    char *realm = (char *)private_data;
+    int ret;
+
+    ret = remove_krb5_info_files(se, realm);
+    if (ret != EOK) {
+        DEBUG(1, ("remove_krb5_info_files failed.\n"));
+    }
+
     sig_term(signum);
 }
-- 
1.6.6.1

-------------- next part --------------
From 0206496813ae9d77f0915028e582ff8d6709eb5e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 18 May 2010 11:11:52 +0200
Subject: [PATCH 05/10] Add run_callbacks flag

---
 src/providers/data_provider_fo.c |   25 +++++++++++++++++++++++--
 src/providers/dp_backend.h       |    2 ++
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 14ebbdb..56a072a 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -42,6 +42,7 @@ struct be_svc_data {
     struct fo_service *fo_service;
 
     struct fo_server *last_good_srv;
+    bool run_callbacks;
 
     struct be_svc_callback *callbacks;
 };
@@ -414,9 +415,11 @@ static void be_resolve_server_done(struct tevent_req *subreq)
                   fo_get_server_name(state->srv), ipaddr));
     }
 
-    /* now call all svc callbacks if server changed */
-    if (state->srv != state->svc->last_good_srv) {
+    /* now call all svc callbacks if server changed or if it is explicitly
+     * requested */
+    if (state->srv != state->svc->last_good_srv || state->svc->run_callbacks) {
         state->svc->last_good_srv = state->srv;
+        state->svc->run_callbacks = false;
 
         DLIST_FOR_EACH(callback, state->svc->callbacks) {
             callback->fn(callback->private_data, state->srv);
@@ -440,3 +443,21 @@ int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv)
     return EOK;
 }
 
+int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
+                                        const char *service_name)
+{
+    struct be_svc_data *svc;
+
+    DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
+        if (strcmp(svc->name, service_name) == 0) {
+            break;
+        }
+    }
+    if (NULL == svc) {
+        return ENOENT;
+    }
+
+    svc->run_callbacks = true;
+
+    return EOK;
+}
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index fc5e558..0668859 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -177,4 +177,6 @@ struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
                                           const char *service_name);
 int be_resolve_server_recv(struct tevent_req *req, struct fo_server **srv);
 
+int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
+                                        const char *service_name);
 #endif /* __DP_BACKEND_H___ */
-- 
1.6.6.1

-------------- next part --------------
From 7db4dbaa31abc5849e3afc146c7967378e6a6411 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 12:04:36 +0200
Subject: [PATCH 06/10] Add callback to remove krb5 info files when going offline

---
 src/Makefile.am                  |    1 +
 src/providers/ipa/ipa_init.c     |    6 ++
 src/providers/krb5/krb5_auth.h   |   40 ----------------
 src/providers/krb5/krb5_common.c |   97 ++++++++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_common.h |   52 ++++++++++++++++++++
 src/providers/krb5/krb5_init.c   |    7 +++
 6 files changed, 163 insertions(+), 40 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index c7a10e7..cb0685c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -515,6 +515,7 @@ krb5_utils_tests_SOURCES = \
     providers/krb5/krb5_common.c \
     providers/data_provider_fo.c \
     providers/data_provider_opts.c \
+    providers/data_provider_callbacks.c \
     $(SSSD_FAILOVER_OBJ) \
     $(SSSD_UTIL_OBJ)
 krb5_utils_tests_CFLAGS = \
diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 0e72b1f..60501ce 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -287,6 +287,12 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = krb5_install_offline_callback(bectx, krb5_auth_ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_offline_callback failed.\n"));
+        goto done;
+    }
+
     if (debug_to_file != 0) {
         ret = open_debug_file_ex("krb5_child", &debug_filep);
         if (ret != EOK) {
diff --git a/src/providers/krb5/krb5_auth.h b/src/providers/krb5/krb5_auth.h
index ec54f73..293375d 100644
--- a/src/providers/krb5/krb5_auth.h
+++ b/src/providers/krb5/krb5_auth.h
@@ -37,8 +37,6 @@
 
 #define ILLEGAL_PATH_PATTERN "//|/\\./|/\\.\\./"
 
-typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
-
 struct krb5child_req {
     pid_t child_pid;
     int read_from_child_fd;
@@ -62,44 +60,6 @@ struct krb5child_req {
     bool valid_tgt_present;
 };
 
-struct fo_service;
-struct deferred_auth_ctx;
-
-struct krb5_ctx {
-    /* opts taken from kinit */
-    /* in seconds */
-    krb5_deltat starttime;
-    krb5_deltat lifetime;
-    krb5_deltat rlife;
-
-    int forwardable;
-    int proxiable;
-    int addresses;
-
-    int not_forwardable;
-    int not_proxiable;
-    int no_addresses;
-
-    int verbose;
-
-    char* principal_name;
-    char* service_name;
-    char* keytab_name;
-    char* k5_cache_name;
-    char* k4_cache_name;
-
-    action_type action;
-
-    struct dp_option *opts;
-    struct krb5_service *service;
-    struct krb5_service *kpasswd_service;
-    int child_debug_fd;
-
-    pcre *illegal_path_re;
-
-    struct deferred_auth_ctx *deferred_auth_ctx;
-};
-
 void krb5_pam_handler(struct be_req *be_req);
 
 struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index dfcb502..f63f516 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -473,6 +473,46 @@ static errno_t remove_krb5_info_files(TALLOC_CTX *mem_ctx, const char *realm)
     return EOK;
 }
 
+void remove_krb5_info_files_callback(void *pvt)
+{
+    int ret;
+    TALLOC_CTX *tmp_ctx = NULL;
+    struct remove_info_files_ctx *ctx = talloc_get_type(pvt,
+                                                  struct remove_info_files_ctx);
+
+    ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
+                                              ctx->kdc_service_name);
+    if (ret != EOK) {
+        DEBUG(1, ("be_fo_run_callbacks_at_next_request failed, "
+                  "krb5 info files will not be removed, because "
+                  "it is unclear if they will be recreated properly.\n"));
+        return;
+    }
+    if (ctx->kpasswd_service_name != NULL) {
+        ret = be_fo_run_callbacks_at_next_request(ctx->be_ctx,
+                                            ctx->kpasswd_service_name);
+        if (ret != EOK) {
+            DEBUG(1, ("be_fo_run_callbacks_at_next_request failed, "
+                      "krb5 info files will not be removed, because "
+                      "it is unclear if they will be recreated properly.\n"));
+            return;
+        }
+    }
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        DEBUG(1, ("talloc_new failed, cannot remove krb5 info files.\n"));
+        return;
+    }
+
+    ret = remove_krb5_info_files(tmp_ctx, ctx->realm);
+    if (ret != EOK) {
+        DEBUG(1, ("remove_krb5_info_files failed.\n"));
+    }
+
+    talloc_zfree(tmp_ctx);
+}
+
 void krb5_finalize(struct tevent_context *ev,
                    struct tevent_signal *se,
                    int signum,
@@ -490,3 +530,60 @@ void krb5_finalize(struct tevent_context *ev,
 
     sig_term(signum);
 }
+
+errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
+                                      struct krb5_ctx *krb5_ctx)
+{
+    int ret;
+    struct remove_info_files_ctx *ctx;
+    const char *krb5_realm;
+
+    if (krb5_ctx->service == NULL || krb5_ctx->service->name == NULL) {
+        DEBUG(1, ("Missing KDC service name!\n"));
+        return EINVAL;
+    }
+
+    ctx = talloc_zero(krb5_ctx, struct remove_info_files_ctx);
+    if (ctx == NULL) {
+        DEBUG(1, ("talloc_zfree failed.\n"));
+        return ENOMEM;
+    }
+
+    krb5_realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
+    if (krb5_realm == NULL) {
+        DEBUG(1, ("Missing krb5_realm option!\n"));
+        ret = EINVAL;
+        goto done;
+    }
+
+    ctx->realm = talloc_strdup(ctx, krb5_realm);
+    if (ctx->realm == NULL) {
+        DEBUG(1, ("talloc_strdup failed!\n"));
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ctx->be_ctx = be_ctx;
+    ctx->kdc_service_name = krb5_ctx->service->name;
+    if (krb5_ctx->kpasswd_service == NULL) {
+        ctx->kpasswd_service_name =NULL;
+    } else {
+        ctx->kpasswd_service_name = krb5_ctx->kpasswd_service->name;
+    }
+
+    ret = be_add_offline_cb(ctx, be_ctx, remove_krb5_info_files_callback, ctx,
+                            NULL);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_offline_cb failed.\n"));
+        goto done;
+    }
+
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        talloc_zfree(ctx);
+    }
+
+    return ret;
+}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index 87d6168..f9b6195 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -58,12 +58,59 @@ enum krb5_opts {
     KRB5_OPTS
 };
 
+typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type;
+
 struct krb5_service {
     char *name;
     char *address;
     char *realm;
 };
 
+struct fo_service;
+struct deferred_auth_ctx;
+
+struct krb5_ctx {
+    /* opts taken from kinit */
+    /* in seconds */
+    krb5_deltat starttime;
+    krb5_deltat lifetime;
+    krb5_deltat rlife;
+
+    int forwardable;
+    int proxiable;
+    int addresses;
+
+    int not_forwardable;
+    int not_proxiable;
+    int no_addresses;
+
+    int verbose;
+
+    char* principal_name;
+    char* service_name;
+    char* keytab_name;
+    char* k5_cache_name;
+    char* k4_cache_name;
+
+    action_type action;
+
+    struct dp_option *opts;
+    struct krb5_service *service;
+    struct krb5_service *kpasswd_service;
+    int child_debug_fd;
+
+    pcre *illegal_path_re;
+
+    struct deferred_auth_ctx *deferred_auth_ctx;
+};
+
+struct remove_info_files_ctx {
+    char *realm;
+    struct be_ctx *be_ctx;
+    const char *kdc_service_name;
+    const char *kpasswd_service_name;
+};
+
 errno_t check_and_export_options(struct dp_option *opts,
                                  struct sss_domain_info *dom);
 
@@ -77,10 +124,15 @@ int krb5_service_init(TALLOC_CTX *memctx, struct be_ctx *ctx,
                       const char *service_name, const char *servers,
                       const char *realm, struct krb5_service **_service);
 
+void remove_krb5_info_files_callback(void *pvt);
+
 void krb5_finalize(struct tevent_context *ev,
                    struct tevent_signal *se,
                    int signum,
                    int count,
                    void *siginfo,
                    void *private_data);
+
+errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
+                                      struct krb5_ctx *krb_ctx);
 #endif /* __KRB5_COMMON_H__ */
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index d0c8be5..481b088 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -149,6 +149,13 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
         goto fail;
     }
     talloc_steal(sige, sig_realm);
+
+    ret = krb5_install_offline_callback(bectx, ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_offline_callback failed.\n"));
+        goto fail;
+    }
+
     if (debug_to_file != 0) {
         ret = open_debug_file_ex("krb5_child", &debug_filep);
         if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From ca12093ca0205000b23ca10933a5a09352b3000e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 14 May 2010 12:16:59 +0200
Subject: [PATCH 07/10] Krb5 locator plugin returns KRB5_PLUGIN_NO_HANDLE

To allow a fallback to the setting in krb5.conf the locator plugin
returns KRB5_PLUGIN_NO_HANDLE in nearly all error conditions. Only if the
call back fails the error code of the callback is returned.
---
 src/krb5_plugin/sssd_krb5_locator_plugin.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/krb5_plugin/sssd_krb5_locator_plugin.c b/src/krb5_plugin/sssd_krb5_locator_plugin.c
index 153145b..dfc9c19 100644
--- a/src/krb5_plugin/sssd_krb5_locator_plugin.c
+++ b/src/krb5_plugin/sssd_krb5_locator_plugin.c
@@ -223,7 +223,7 @@ krb5_error_code sssd_krb5_locator_init(krb5_context context,
     const char *dummy;
 
     ctx = calloc(1,sizeof(struct sssd_ctx));
-    if (ctx == NULL) return ENOMEM;
+    if (ctx == NULL) return KRB5_PLUGIN_NO_HANDLE;
 
     dummy = getenv(SSSD_KRB5_LOCATOR_DEBUG);
     if (dummy == NULL) {
@@ -280,7 +280,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
         ctx->sssd_realm = strdup(realm);
         if (ctx->sssd_realm == NULL) {
             PLUGIN_DEBUG(("strdup failed.\n"));
-            return ENOMEM;
+            return KRB5_PLUGIN_NO_HANDLE;
         }
 
         ret = get_krb5info(realm, ctx, locate_service_kdc);
@@ -326,7 +326,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
         case locate_service_krb524:
             return KRB5_PLUGIN_NO_HANDLE;
         default:
-            return EINVAL;
+            return KRB5_PLUGIN_NO_HANDLE;
     }
 
     switch (family) {
@@ -343,7 +343,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
         case SOCK_DGRAM:
             break;
         default:
-            return EINVAL;
+            return KRB5_PLUGIN_NO_HANDLE;
     }
 
     if (strcmp(realm, ctx->sssd_realm) != 0)
@@ -353,7 +353,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
     ret = snprintf(port_str, PORT_STR_SIZE-1, "%u", port);
     if (ret < 0 || ret >= (PORT_STR_SIZE-1)) {
         PLUGIN_DEBUG(("snprintf failed.\n"));
-        return EFAULT;
+        return KRB5_PLUGIN_NO_HANDLE;
     }
 
     memset(&ai_hints, 0, sizeof(struct addrinfo));
@@ -368,7 +368,7 @@ krb5_error_code sssd_krb5_locator_lookup(void *private_data,
             PLUGIN_DEBUG(("getaddrinfo failed [%d][%s].\n", errno,
                                                             strerror(errno)));
         }
-        return EFAULT;
+        return KRB5_PLUGIN_NO_HANDLE;
     }
 
     PLUGIN_DEBUG(("addr[%s:%s] family[%d] socktype[%d]\n", addr, port_str,
-- 
1.6.6.1

-------------- next part --------------
From 14e1c8cc46f6171d4d000c901bb213bf2d4f7468 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 17 May 2010 13:23:32 +0200
Subject: [PATCH 08/10] Refactor krb5 SIGTERM handler installation

---
 src/providers/krb5/krb5_common.c |   33 +++++++++++++++++++++++++++++++++
 src/providers/krb5/krb5_common.h |    3 +++
 src/providers/krb5/krb5_init.c   |   17 +++--------------
 3 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c
index f63f516..c78f0e6 100644
--- a/src/providers/krb5/krb5_common.c
+++ b/src/providers/krb5/krb5_common.c
@@ -587,3 +587,36 @@ done:
 
     return ret;
 }
+
+errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
+                                     struct krb5_ctx *krb5_ctx)
+{
+    const char *krb5_realm;
+    char *sig_realm;
+    struct tevent_signal *sige;
+
+    BlockSignals(false, SIGTERM);
+
+    krb5_realm = dp_opt_get_cstring(krb5_ctx->opts, KRB5_REALM);
+    if (krb5_realm == NULL) {
+        DEBUG(1, ("Missing krb5_realm option!\n"));
+        return EINVAL;
+    }
+
+    sig_realm = talloc_strdup(krb5_ctx, krb5_realm);
+    if (sig_realm == NULL) {
+        DEBUG(1, ("talloc_strdup failed!\n"));
+        return ENOMEM;
+    }
+
+    sige = tevent_add_signal(ev, krb5_ctx, SIGTERM, SA_SIGINFO, krb5_finalize,
+                             sig_realm);
+    if (sige == NULL) {
+        DEBUG(1, ("tevent_add_signal failed.\n"));
+        talloc_free(sig_realm);
+        return ENOMEM;
+    }
+    talloc_steal(sige, sig_realm);
+
+    return EOK;
+}
diff --git a/src/providers/krb5/krb5_common.h b/src/providers/krb5/krb5_common.h
index f9b6195..342481e 100644
--- a/src/providers/krb5/krb5_common.h
+++ b/src/providers/krb5/krb5_common.h
@@ -135,4 +135,7 @@ void krb5_finalize(struct tevent_context *ev,
 
 errno_t krb5_install_offline_callback(struct be_ctx *be_ctx,
                                       struct krb5_ctx *krb_ctx);
+
+errno_t krb5_install_sigterm_handler(struct tevent_context *ev,
+                                     struct krb5_ctx *krb5_ctx);
 #endif /* __KRB5_COMMON_H__ */
diff --git a/src/providers/krb5/krb5_init.c b/src/providers/krb5/krb5_init.c
index 481b088..c457dc5 100644
--- a/src/providers/krb5/krb5_init.c
+++ b/src/providers/krb5/krb5_init.c
@@ -48,14 +48,12 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
 {
     struct krb5_ctx *ctx = NULL;
     int ret;
-    struct tevent_signal *sige;
     unsigned v;
     FILE *debug_filep;
     const char *krb5_servers;
     const char *krb5_kpasswd_servers;
     const char *krb5_realm;
     const char *errstr;
-    char *sig_realm;
     int errval;
     int errpos;
 
@@ -135,20 +133,11 @@ int sssm_krb5_auth_init(struct be_ctx *bectx,
         goto fail;
     }
 
-    BlockSignals(false, SIGTERM);
-    sig_realm = talloc_strdup(ctx, krb5_realm);
-    if (sig_realm == NULL) {
-        ret = ENOMEM;
-        goto fail;
-    }
-    sige = tevent_add_signal(bectx->ev, ctx, SIGTERM, SA_SIGINFO,
-                             krb5_finalize, sig_realm);
-    if (sige == NULL) {
-        DEBUG(1, ("tevent_add_signal failed.\n"));
-        ret = ENOMEM;
+    ret = krb5_install_sigterm_handler(bectx->ev, ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_sigterm_handler failed.\n"));
         goto fail;
     }
-    talloc_steal(sige, sig_realm);
 
     ret = krb5_install_offline_callback(bectx, ctx);
     if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From be6eb5f64dee7a2def69db095f2cce4425511150 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 17 May 2010 10:00:32 +0200
Subject: [PATCH 09/10] Add krb5 SIGTERM handler to ipa auth provider

---
 src/providers/ipa/ipa_init.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 60501ce..59e479e 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -293,6 +293,12 @@ int sssm_ipa_auth_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = krb5_install_sigterm_handler(bectx->ev, krb5_auth_ctx);
+    if (ret != EOK) {
+        DEBUG(1, ("krb5_install_sigterm_handler failed.\n"));
+        goto done;
+    }
+
     if (debug_to_file != 0) {
         ret = open_debug_file_ex("krb5_child", &debug_filep);
         if (ret != EOK) {
-- 
1.6.6.1

-------------- next part --------------
From e29fac0a76f69a32fd3a8b5ab3b153170e83c4b0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Tue, 18 May 2010 12:18:13 +0200
Subject: [PATCH 10/10] Add offline callback to disconnect global SDAP handle

---
 src/providers/ipa/ipa_init.c     |    7 +++++++
 src/providers/ldap/ldap_common.c |   10 +++++++++-
 src/providers/ldap/ldap_common.h |    1 +
 src/providers/ldap/ldap_init.c   |    7 +++++++
 4 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 59e479e..f3fa610 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -175,6 +175,13 @@ int sssm_ipa_id_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = be_add_offline_cb(ctx, bectx, sdap_gsh_disconnect_callback, ctx,
+                            NULL);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_offline_cb failed.\n"));
+        goto done;
+    }
+
     ret = sdap_id_setup_tasks(ctx);
     if (ret != EOK) {
         goto done;
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index d145084..f972671 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -6,7 +6,7 @@
     Authors:
         Simo Sorce <ssorce at redhat.com>
 
-    Copyright (C) 2008-2009 Red Hat
+    Copyright (C) 2008-2010 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
@@ -675,3 +675,11 @@ done:
     return ret;
 }
 
+void sdap_gsh_disconnect_callback(void *pvt)
+{
+    struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx);
+
+    if (ctx->gsh) {
+        ctx->gsh->connected = false;
+    }
+}
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 2fec7e2..1ee7378 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -117,4 +117,5 @@ int groups_get_recv(struct tevent_req *req);
 /* setup child logging */
 int setup_child(struct sdap_id_ctx *ctx);
 
+void sdap_gsh_disconnect_callback(void *pvt);
 #endif /* _LDAP_COMMON_H_ */
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index 396dbfd..5c6f4b7 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -105,6 +105,13 @@ int sssm_ldap_id_init(struct be_ctx *bectx,
         goto done;
     }
 
+    ret = be_add_offline_cb(ctx, bectx, sdap_gsh_disconnect_callback, ctx,
+                            NULL);
+    if (ret != EOK) {
+        DEBUG(1, ("be_add_offline_cb failed.\n"));
+        goto done;
+    }
+
     ret = sdap_id_setup_tasks(ctx);
     if (ret != EOK) {
         goto done;
-- 
1.6.6.1



More information about the sssd-devel mailing list