diff options
-rw-r--r-- | source3/librpc/idl/smbXsrv.idl | 21 | ||||
-rw-r--r-- | source3/smbd/globals.c | 2 | ||||
-rw-r--r-- | source3/smbd/globals.h | 9 | ||||
-rw-r--r-- | source3/smbd/process.c | 53 | ||||
-rw-r--r-- | source3/smbd/server_exit.c | 43 |
5 files changed, 100 insertions, 28 deletions
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index ca5c3f3fde..ed242c3710 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -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 { diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index e03c7c4180..c9da6db9c6 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -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) { diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 5a8e3bd746..20bd13676b 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -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); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index e0af9fe6c8..eebe9c04a6 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -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); diff --git a/source3/smbd/server_exit.c b/source3/smbd/server_exit.c index c708cb65d7..d48a8f283d 100644 --- a/source3/smbd/server_exit.c +++ b/source3/smbd/server_exit.c @@ -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); |