summaryrefslogtreecommitdiff
path: root/source4/smbd/process_standard.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/smbd/process_standard.c')
-rw-r--r--source4/smbd/process_standard.c115
1 files changed, 88 insertions, 27 deletions
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c
index 3612c6a7f4..b0f7cf1a11 100644
--- a/source4/smbd/process_standard.c
+++ b/source4/smbd/process_standard.c
@@ -29,10 +29,16 @@
/*
called when the process model is selected
*/
-static void standard_model_startup(void)
+static void standard_model_init(struct server_context *server)
{
signal(SIGCHLD, SIG_IGN);
- smbd_process_init();
+}
+
+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);
}
/*
@@ -43,12 +49,12 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
{
NTSTATUS status;
struct socket_context *sock;
- struct server_socket *server_socket = srv_fde->private;
+ struct server_stream_socket *stream_socket = srv_fde->private;
struct server_connection *conn;
pid_t pid;
/* accept an incoming connection. */
- status = socket_accept(server_socket->socket, &sock);
+ status = socket_accept(stream_socket->socket, &sock);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("standard_accept_connection: accept: %s\n",
nt_errstr(status)));
@@ -68,7 +74,7 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
/* Child code ... */
/* close all the listening sockets */
- service_close_listening_sockets(server_socket->service->srv_ctx);
+ event_remove_fd_all_handler(ev, server_accept_handler);
/* we don't care if the dup fails, as its only a select()
speed optimisation */
@@ -83,16 +89,15 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
set_need_random_reseed();
- conn = server_setup_connection(ev, server_socket, sock, t, getpid());
+ 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;
}
talloc_steal(conn, sock);
- DLIST_ADD(server_socket->connection_list,conn);
-
/* return to the event loop */
}
@@ -103,7 +108,7 @@ static void standard_terminate_connection(struct server_connection *conn, const
DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason));
if (conn) {
- talloc_free(conn->service->srv_ctx);
+ talloc_free(conn->stream_socket->service->server);
}
/* this init_iconv() has the effect of freeing the iconv context memory,
@@ -117,38 +122,94 @@ static void standard_terminate_connection(struct server_connection *conn, const
exit(0);
}
-static int standard_get_id(struct smbsrv_request *req)
+/*
+ called to create a new event context for a new task
+*/
+static void standard_create_task(struct server_task *task)
{
- return (int)req->smb_conn->pid;
+ 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;
}
-static void standard_exit_server(struct server_context *srv_ctx, const char *reason)
+/*
+ called to destroy a new event context for a new task
+*/
+static void standard_terminate_task(struct server_task *task, const char *reason)
{
- DEBUG(1,("standard_exit_server: reason[%s]\n",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();
+
+ /* 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
+};
+
/*
initialise the standard process model, registering ourselves with the process model subsystem
*/
NTSTATUS process_model_standard_init(void)
{
NTSTATUS ret;
- struct model_ops ops;
-
- ZERO_STRUCT(ops);
-
- /* fill in our name */
- ops.name = "standard";
-
- /* fill in all the operations */
- ops.model_startup = standard_model_startup;
- ops.accept_connection = standard_accept_connection;
- ops.terminate_connection = standard_terminate_connection;
- ops.exit_server = standard_exit_server;
- ops.get_id = standard_get_id;
/* register ourselves with the PROCESS_MODEL subsystem. */
- ret = register_process_model(&ops);
+ ret = register_process_model(&standard_ops);
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(0,("Failed to register process_model 'standard'!\n"));
return ret;