[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 {
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)
{
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;
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);
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;
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);
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);
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)
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:
}
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
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);
* 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);