diff options
Diffstat (limited to 'source4/smbd/process_standard.c')
-rw-r--r-- | source4/smbd/process_standard.c | 159 |
1 files changed, 40 insertions, 119 deletions
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index b0f7cf1a11..ee73cfadcf 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -1,7 +1,9 @@ /* Unix SMB/CIFS implementation. + process model: standard (1 process per client connection) - Copyright (C) Andrew Tridgell 1992-2003 + + Copyright (C) Andrew Tridgell 1992-2005 Copyright (C) James J Myers 2003 <myersjj@samba.org> Copyright (C) Stefan (metze) Metzmacher 2004 @@ -24,37 +26,31 @@ #include "events.h" #include "dlinklist.h" #include "smb_server/smb_server.h" -#include "process_model.h" /* called when the process model is selected */ -static void standard_model_init(struct server_context *server) +static void standard_model_init(struct event_context *ev) { signal(SIGCHLD, SIG_IGN); } -static void standard_model_exit(struct server_context *server, const char *reason) -{ - DEBUG(1,("standard_model_exit: reason[%s]\n",reason)); - talloc_free(server); - exit(0); -} - /* - called when a listening socket becomes readable + called when a listening socket becomes readable. */ -static void standard_accept_connection(struct event_context *ev, struct fd_event *srv_fde, - struct timeval t, uint16_t flags) +static void standard_accept_connection(struct event_context *ev, + struct socket_context *sock, + void (*new_conn)(struct event_context *, struct socket_context *, + uint32_t , void *), + void *private) { NTSTATUS status; - struct socket_context *sock; - struct server_stream_socket *stream_socket = srv_fde->private; - struct server_connection *conn; + struct socket_context *sock2; pid_t pid; + struct event_context *ev2; /* accept an incoming connection. */ - status = socket_accept(stream_socket->socket, &sock); + status = socket_accept(sock, &sock2); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("standard_accept_connection: accept: %s\n", nt_errstr(status))); @@ -65,20 +61,28 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event if (pid != 0) { /* parent or error code ... */ - - socket_destroy(sock); + talloc_free(sock2); /* go back to the event loop */ return; } - /* Child code ... */ + /* This is now the child code. We need a completely new event_context to work with */ + ev2 = event_context_init(NULL); - /* close all the listening sockets */ - event_remove_fd_all_handler(ev, server_accept_handler); + /* the service has given us a private pointer that + encapsulates the context it needs for this new connection - + everything else will be freed */ + talloc_steal(ev2, private); + talloc_steal(private, sock2); + + /* this will free all the listening sockets and all state that + is not associated with this new connection */ + talloc_free(sock); + talloc_free(ev); /* we don't care if the dup fails, as its only a select() speed optimisation */ - socket_dup(sock); + socket_dup(sock2); /* tdb needs special fork handling */ if (tdb_reopen_all() == -1) { @@ -86,31 +90,26 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event } /* Ensure that the forked children do not expose identical random streams */ - set_need_random_reseed(); - conn = server_setup_connection(ev, stream_socket, sock, t, getpid()); - if (!conn) { - DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n")); - exit(1); - return; - } + /* setup this new connection */ + new_conn(ev2, sock2, getpid(), private); - talloc_steal(conn, sock); + /* we can't return to the top level here, as that event context is gone, + so we now process events in the new event context until there are no + more to process */ + event_loop_wait(ev2); - /* return to the event loop */ + talloc_free(ev2); + exit(0); } -/* called when a SMB connection goes down */ -static void standard_terminate_connection(struct server_connection *conn, const char *reason) +/* called when a connection goes down */ +static void standard_terminate_connection(struct event_context *ev, const char *reason) { DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason)); - if (conn) { - talloc_free(conn->stream_socket->service->server); - } - /* this init_iconv() has the effect of freeing the iconv context memory, which makes leak checking easier */ init_iconv(); @@ -118,87 +117,18 @@ static void standard_terminate_connection(struct server_connection *conn, const /* the secrets db should really hang off the connection structure */ secrets_shutdown(); - /* terminate this process */ - exit(0); -} - -/* - called to create a new event context for a new task -*/ -static void standard_create_task(struct server_task *task) -{ - pid_t pid; - - pid = fork(); - - if (pid != 0) { - /* parent or error code ... */ - talloc_free(task); - /* go back to the event loop */ - return; - } - - /* Child code ... */ - - /* close all the listening sockets */ - event_remove_fd_all_handler(task->service->server->event.ctx, server_accept_handler); - - /* tdb needs special fork handling */ - if (tdb_reopen_all() == -1) { - DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n")); - } - - /* Ensure that the forked children do not expose identical random streams */ - - set_need_random_reseed(); - - task->task.id = (uint32)getpid(); - task->event.ctx = task->service->server->event.ctx; - - /* setup to receive internal messages on this connection */ - task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx); - if (!task->messaging.ctx) { - server_terminate_task(task, "messaging_init() failed"); - return; - } - - task->task.ops->task_init(task); - - server_terminate_task(task, "exit"); - return; -} - -/* - called to destroy a new event context for a new task -*/ -static void standard_terminate_task(struct server_task *task, const char *reason) -{ - DEBUG(2,("standard_terminate_task: reason[%s]\n",reason)); - - talloc_free(task); - - /* this init_iconv() has the effect of freeing the iconv context memory, - which makes leak checking easier */ - init_iconv(); - - /* the secrets db should really hang off the connection structure */ - secrets_shutdown(); + talloc_free(ev); /* terminate this process */ exit(0); } + static const struct model_ops standard_ops = { .name = "standard", - .model_init = standard_model_init, - .model_exit = standard_model_exit, - .accept_connection = standard_accept_connection, .terminate_connection = standard_terminate_connection, - - .create_task = standard_create_task, - .terminate_task = standard_terminate_task }; /* @@ -206,14 +136,5 @@ static const struct model_ops standard_ops = { */ NTSTATUS process_model_standard_init(void) { - NTSTATUS ret; - - /* register ourselves with the PROCESS_MODEL subsystem. */ - ret = register_process_model(&standard_ops); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("Failed to register process_model 'standard'!\n")); - return ret; - } - - return ret; + return register_process_model(&standard_ops); } |