s3:smbd: move pending_auth_data list to struct smbd_server_connection
[kai/samba.git] / source3 / smbd / dmapi.c
index 8d43e0a9d1e9f51aa23c6a3a60560f3f7b6c1227..8c3939f99aaa8d13ae78c27c269fdcfba7d6e068 100644 (file)
@@ -19,6 +19,7 @@
 */
 
 #include "includes.h"
+#include "smbd/globals.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_DMAPI
@@ -46,15 +47,17 @@ const void * dmapi_get_current_session(void) { return NULL; }
 #define DMAPI_SESSION_NAME "samba"
 #define DMAPI_TRACE 10
 
-static dm_sessid_t samba_dmapi_session = DM_NO_SESSION;
-static unsigned session_num;
+struct smbd_dmapi_context {
+       dm_sessid_t session;
+       unsigned session_num;
+};
 
 /* 
    Initialise DMAPI session. The session is persistant kernel state, 
    so it might already exist, in which case we merely want to 
    reconnect to it. This function should be called as root.
 */
-static int dmapi_init_session(void)
+static int dmapi_init_session(struct smbd_dmapi_context *ctx)
 {
        char    buf[DM_SESSION_INFO_LEN];
        size_t  buflen;
@@ -66,11 +69,11 @@ static int dmapi_init_session(void)
 
        int i, err;
 
-       if (session_num == 0) {
-               session_name = DMAPI_SESSION_NAME;
+       if (ctx->session_num == 0) {
+               session_name = talloc_strdup(tmp_ctx, DMAPI_SESSION_NAME);
        } else {
                session_name = talloc_asprintf(tmp_ctx, "%s%u", DMAPI_SESSION_NAME,
-                                              session_num);
+                                              ctx->session_num);
        }
 
        if (session_name == NULL) {
@@ -116,7 +119,7 @@ static int dmapi_init_session(void)
                err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen);
                buf[sizeof(buf) - 1] = '\0';
                if (err == 0 && strcmp(session_name, buf) == 0) {
-                       samba_dmapi_session = sessions[i];
+                       ctx->session = sessions[i];
                        DEBUGADD(DMAPI_TRACE,
                                ("attached to existing DMAPI session "
                                 "named '%s'\n", buf));
@@ -125,15 +128,15 @@ static int dmapi_init_session(void)
        }
 
        /* No session already defined. */
-       if (samba_dmapi_session == DM_NO_SESSION) {
+       if (ctx->session == DM_NO_SESSION) {
                err = dm_create_session(DM_NO_SESSION, 
                                        session_name,
-                                       &samba_dmapi_session);
+                                       &ctx->session);
                if (err < 0) {
                        DEBUGADD(DMAPI_TRACE,
                                ("failed to create new DMAPI session: %s\n",
                                strerror(errno)));
-                       samba_dmapi_session = DM_NO_SESSION;
+                       ctx->session = DM_NO_SESSION;
                        talloc_free(tmp_ctx);
                        return -1;
                }
@@ -142,7 +145,7 @@ static int dmapi_init_session(void)
                          session_name, version));
        }
 
-       if (samba_dmapi_session != DM_NO_SESSION) {
+       if (ctx->session != DM_NO_SESSION) {
                set_effective_capability(DMAPI_ACCESS_CAPABILITY);
        }
 
@@ -165,11 +168,15 @@ static int dmapi_init_session(void)
 */
 const void *dmapi_get_current_session(void)
 {
-       if (samba_dmapi_session == DM_NO_SESSION) {
+       if (!dmapi_ctx) {
                return NULL;
        }
 
-       return (void *)&samba_dmapi_session;
+       if (dmapi_ctx->session == DM_NO_SESSION) {
+               return NULL;
+       }
+
+       return (void *)&dmapi_ctx->session;
 }
        
 /*
@@ -180,17 +187,22 @@ const void *dmapi_get_current_session(void)
 
 bool dmapi_have_session(void)
 {
-       static bool initialized;
-       if (!initialized) {
-               initialized = true;
+       if (!dmapi_ctx) {
+               dmapi_ctx = talloc(talloc_autofree_context(),
+                                  struct smbd_dmapi_context);
+               if (!dmapi_ctx) {
+                       exit_server("unable to allocate smbd_dmapi_context");
+               }
+               dmapi_ctx->session = DM_NO_SESSION;
+               dmapi_ctx->session_num = 0;
 
                become_root();
-               dmapi_init_session();
+               dmapi_init_session(dmapi_ctx);
                unbecome_root();
 
        }
 
-       return samba_dmapi_session != DM_NO_SESSION;
+       return dmapi_ctx->session != DM_NO_SESSION;
 }
 
 /*
@@ -198,20 +210,47 @@ bool dmapi_have_session(void)
   session you are using is invalid. This destroys the existing session
   and creates a new one.
  */
-BOOL dmapi_new_session(void)
+bool dmapi_new_session(void)
 {
        if (dmapi_have_session()) {
                /* try to destroy the old one - this may not succeed */
-               dm_destroy_session(samba_dmapi_session);
+               dm_destroy_session(dmapi_ctx->session);
        }
-       samba_dmapi_session = DM_NO_SESSION;
+       dmapi_ctx->session = DM_NO_SESSION;
        become_root();
-       session_num++;
-       dmapi_init_session();
+       dmapi_ctx->session_num++;
+       dmapi_init_session(dmapi_ctx);
        unbecome_root();
-       return samba_dmapi_session != DM_NO_SESSION;    
+       return dmapi_ctx->session != DM_NO_SESSION;
 }
 
+/* 
+    only call this when exiting from master smbd process. DMAPI sessions
+    are long-lived kernel resources we ought to share across smbd processes.
+    However, we must free them when all smbd processes are finished to
+    allow other subsystems clean up properly. Not freeing DMAPI session
+    blocks certain HSM implementations from proper shutdown.
+*/
+bool dmapi_destroy_session(void)
+{
+       if (!dmapi_ctx) {
+               return true;
+       }
+       if (dmapi_ctx->session != DM_NO_SESSION) {
+               become_root();
+               if (0 == dm_destroy_session(dmapi_ctx->session)) {
+                       dmapi_ctx->session_num--;
+                       dmapi_ctx->session = DM_NO_SESSION;
+               } else {
+                       DEBUG(0,("Couldn't destroy DMAPI session: %s\n",
+                                strerror(errno)));
+               }
+               unbecome_root();
+       }
+       return dmapi_ctx->session == DM_NO_SESSION;
+}
+
+
 /* 
    This is default implementation of dmapi_file_flags() that is 
    called from VFS is_offline() call to know whether file is offline.