s3:smbd: introduce 'struct smbXsrv_client' in order to prepare multi-channel support
authorStefan Metzmacher <metze@samba.org>
Tue, 20 May 2014 17:47:13 +0000 (19:47 +0200)
committerMichael Adam <obnox@samba.org>
Fri, 19 Sep 2014 07:15:11 +0000 (09:15 +0200)
This structure is supposed to hold the global state shared between
multiple connections from the same client.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
source3/librpc/idl/smbXsrv.idl
source3/smbd/globals.c
source3/smbd/globals.h
source3/smbd/process.c
source3/smbd/server_exit.c

index ca5c3f3fde984242d02271bf6bf66e39f3caee7a..ed242c3710a4cb88d80b78c5e7407f357e45bdef 100644 (file)
@@ -77,6 +77,27 @@ interface smbXsrv
                [in] smbXsrv_version_globalB blob
                );
 
+       /* client */
+
+       typedef struct {
+               [ignore] struct tevent_context          *ev_ctx;
+               [ignore] struct messaging_context       *msg_ctx;
+
+               /*
+                * There's just one 'sconn' per client.
+                * It holds the FSA layer details, which are global
+                * per client (process).
+                */
+               [ignore] struct smbd_server_connection  *sconn;
+
+               /*
+                * For now this is only one connection!
+                * With multi-channel support we'll get more than
+                * one in future.
+                */
+               [ignore] struct smbXsrv_connection      *connections;
+       } smbXsrv_client;
+
        /* sessions */
 
        typedef struct {
index e03c7c4180bcb8057f431fb483d370d65ba50aac..c9da6db9c63107ff220d600034875621bfc76933 100644 (file)
@@ -90,7 +90,7 @@ struct smbd_parent_context *am_parent = NULL;
 struct memcache *smbd_memcache_ctx = NULL;
 bool exit_firsttime = true;
 
-struct smbXsrv_connection *global_smbXsrv_connection = NULL;
+struct smbXsrv_client *global_smbXsrv_client = NULL;
 
 struct memcache *smbd_memcache(void)
 {
index 5a8e3bd7462ad80b9d3d1d01650cbea9de4d60ef..20bd13676bc0ed877a7ff5d9a8087282fbaf3726 100644 (file)
@@ -330,7 +330,13 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
                                struct file_id id,
                                struct deferred_open_record *open_rec);
 
+struct smbXsrv_client;
+
 struct smbXsrv_connection {
+       struct smbXsrv_connection *prev, *next;
+
+       struct smbXsrv_client *client;
+
        struct smbd_server_connection *sconn;
 
        const struct tsocket_address *local_address;
@@ -854,8 +860,9 @@ struct smbd_server_connection {
        struct tevent_fd *asys_fde;
 
        struct smbXsrv_connection *conn;
+       struct smbXsrv_client *client;
 };
 
-extern struct smbXsrv_connection *global_smbXsrv_connection;
+extern struct smbXsrv_client *global_smbXsrv_client;
 
 void smbd_init_globals(void);
index e0af9fe6c8ae188deb77b187e47328f1dfd05ef4..eebe9c04a6a04003b3786f4bf8c07cc9813702d1 100644 (file)
@@ -3551,6 +3551,7 @@ void smbd_process(struct tevent_context *ev_ctx,
                  bool interactive)
 {
        TALLOC_CTX *frame = talloc_stackframe();
+       struct smbXsrv_client *client;
        struct smbXsrv_connection *xconn;
        struct smbd_server_connection *sconn;
        struct sockaddr_storage ss_srv;
@@ -3568,32 +3569,50 @@ void smbd_process(struct tevent_context *ev_ctx,
        int ret;
        int tmp;
 
-       xconn = talloc_zero(ev_ctx, struct smbXsrv_connection);
+       client = talloc_zero(ev_ctx, struct smbXsrv_client);
+       if (client == NULL) {
+               DEBUG(0,("talloc_zero(struct smbXsrv_client)\n"));
+               exit_server_cleanly("talloc_zero(struct smbXsrv_client).\n");
+       }
+
+       /*
+        * TODO: remove this...:-)
+        */
+       global_smbXsrv_client = client;
+
+       client->ev_ctx = ev_ctx;
+       client->msg_ctx = msg_ctx;
+
+       sconn = talloc_zero(client, struct smbd_server_connection);
+       if (sconn == NULL) {
+               exit_server("failed to create smbd_server_connection");
+       }
+
+       client->sconn = sconn;
+       sconn->client = client;
+
+       sconn->ev_ctx = ev_ctx;
+       sconn->msg_ctx = msg_ctx;
+
+       xconn = talloc_zero(client, struct smbXsrv_connection);
        if (xconn == NULL) {
                DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n"));
                exit_server_cleanly("talloc_zero(struct smbXsrv_connection).\n");
        }
+       /* for now we only have one connection */
+       DLIST_ADD_END(client->connections, xconn, NULL);
+       xconn->client = client;
 
        xconn->ev_ctx = ev_ctx;
        xconn->msg_ctx = msg_ctx;
        xconn->transport.sock = sock_fd;
        smbd_echo_init(xconn);
 
-       sconn = talloc_zero(xconn, struct smbd_server_connection);
-       if (!sconn) {
-               exit_server("failed to create smbd_server_connection");
-       }
-
-       xconn->sconn = sconn;
-       sconn->conn = xconn;
-
        /*
         * TODO: remove this...:-)
         */
-       global_smbXsrv_connection = xconn;
-
-       sconn->ev_ctx = ev_ctx;
-       sconn->msg_ctx = msg_ctx;
+       xconn->sconn = sconn;
+       sconn->conn = xconn;
 
        if (!interactive) {
                smbd_setup_sig_term_handler(sconn);
@@ -3867,10 +3886,10 @@ void smbd_process(struct tevent_context *ev_ctx,
                exit_server("failed to create smbd_server_connection fde");
        }
 
-       sconn->conn->local_address = sconn->local_address;
-       sconn->conn->remote_address = sconn->remote_address;
-       sconn->conn->remote_hostname = sconn->remote_hostname;
-       sconn->conn->protocol = PROTOCOL_NONE;
+       xconn->local_address = sconn->local_address;
+       xconn->remote_address = sconn->remote_address;
+       xconn->remote_hostname = sconn->remote_hostname;
+       xconn->protocol = PROTOCOL_NONE;
 
        TALLOC_FREE(frame);
 
index c708cb65d7be86f27fc063a753efb9af52fe018c..d48a8f283d298248f1c769f48866b7b6271000ec 100644 (file)
@@ -85,12 +85,17 @@ static void exit_server_common(enum server_exit_reason how,
 static void exit_server_common(enum server_exit_reason how,
        const char *reason)
 {
-       struct smbXsrv_connection *xconn = global_smbXsrv_connection;
+       struct smbXsrv_client *client = global_smbXsrv_client;
+       struct smbXsrv_connection *xconn = NULL;
        struct smbd_server_connection *sconn = NULL;
        struct messaging_context *msg_ctx = server_messaging_context();
 
-       if (xconn != NULL) {
-               sconn = xconn->sconn;
+       if (client != NULL) {
+               sconn = client->sconn;
+               /*
+                * Here we typically have just one connection
+                */
+               xconn = client->connections;
        }
 
        if (!exit_firsttime)
@@ -99,9 +104,11 @@ static void exit_server_common(enum server_exit_reason how,
 
        change_to_root_user();
 
-       if (sconn) {
-               NTSTATUS status;
-
+       if (xconn != NULL) {
+               /*
+                * This is typically the disconnect for the only
+                * (or with multi-channel last) connection of the client
+                */
                if (NT_STATUS_IS_OK(xconn->transport.status)) {
                        switch (how) {
                        case SERVER_EXIT_ABNORMAL:
@@ -114,11 +121,21 @@ static void exit_server_common(enum server_exit_reason how,
                }
 
                TALLOC_FREE(xconn->smb1.negprot.auth_context);
+       }
+
+       change_to_root_user();
 
+       if (sconn != NULL) {
                if (lp_log_writeable_files_on_exit()) {
                        bool found = false;
                        files_forall(sconn, log_writeable_file_fn, &found);
                }
+       }
+
+       change_to_root_user();
+
+       if (xconn != NULL) {
+               NTSTATUS status;
 
                /*
                 * Note: this is a no-op for smb2 as
@@ -145,10 +162,10 @@ static void exit_server_common(enum server_exit_reason how,
                        how = SERVER_EXIT_ABNORMAL;
                        reason = "smbXsrv_session_logoff_all failed";
                }
-
-               change_to_root_user();
        }
 
+       change_to_root_user();
+
        /* 3 second timeout. */
        print_notify_send_messages(msg_ctx, 3);
 
@@ -200,9 +217,17 @@ static void exit_server_common(enum server_exit_reason how,
         * we need to force the order of freeing the following,
         * because smbd_msg_ctx is not a talloc child of smbd_server_conn.
         */
+       if (client != NULL) {
+               for (; xconn != NULL; xconn = xconn->next) {
+                       DLIST_REMOVE(client->connections, xconn);
+                       talloc_free(xconn);
+               }
+               TALLOC_FREE(client->sconn);
+       }
        sconn = NULL;
        xconn = NULL;
-       TALLOC_FREE(global_smbXsrv_connection);
+       client = NULL;
+       TALLOC_FREE(global_smbXsrv_client);
        server_messaging_context_free();
        server_event_context_free();
        TALLOC_FREE(smbd_memcache_ctx);