summaryrefslogtreecommitdiff
path: root/source4/smbd
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-01-30 00:54:57 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:22 -0500
commit55d4d36993293fee914a009f1d8f05810e347f2b (patch)
tree587a9bafd1c8df901aad8766acb0fe9ef4c3d8c0 /source4/smbd
parent5540449f1cd9d9a6efab59f2bf47be4e1487ffc2 (diff)
downloadsamba-55d4d36993293fee914a009f1d8f05810e347f2b.tar.gz
samba-55d4d36993293fee914a009f1d8f05810e347f2b.tar.bz2
samba-55d4d36993293fee914a009f1d8f05810e347f2b.zip
r5102: This is a major simplification of the logic for controlling top level
servers in smbd. The old code still contained a fairly bit of legacy from the time when smbd was only handling SMB connection. The new code gets rid of all of the smb_server specific code in smbd/, and creates a much simpler infrastructures for new server code. Major changes include: - simplified the process model code a lot. - got rid of the top level server and service structures completely. The top level context is now the event_context. This got rid of service.h and server.h completely (they were the most confusing parts of the old code) - added service_stream.[ch] for the helper functions that are specific to stream type services (services that handle streams, and use a logically separate process per connection) - got rid of the builtin idle_handler code in the service logic, as none of the servers were using it, and it can easily be handled by a server in future by adding its own timed_event to the event context. - fixed some major memory leaks in the rpc server code. - added registration of servers, rather than hard coding our list of possible servers. This allows for servers as modules in the future. - temporarily disabled the winbind code until I add the helper functions for that type of server - added error checking on service startup. If a configured server fails to startup then smbd doesn't startup. - cleaned up the command line handling in smbd, removing unused options (This used to be commit cf6a46c3cbde7b1eb1b86bd3882b953a2de3a42e)
Diffstat (limited to 'source4/smbd')
-rw-r--r--source4/smbd/config.mk6
-rw-r--r--source4/smbd/process_model.c6
-rw-r--r--source4/smbd/process_model.h33
-rw-r--r--source4/smbd/process_single.c100
-rw-r--r--source4/smbd/process_standard.c159
-rw-r--r--source4/smbd/process_thread.c164
-rw-r--r--source4/smbd/rewrite.c70
-rw-r--r--source4/smbd/server.c173
-rw-r--r--source4/smbd/server.h49
-rw-r--r--source4/smbd/service.c394
-rw-r--r--source4/smbd/service.h165
11 files changed, 270 insertions, 1049 deletions
diff --git a/source4/smbd/config.mk b/source4/smbd/config.mk
index cd2fb4ab72..07847b7fc8 100644
--- a/source4/smbd/config.mk
+++ b/source4/smbd/config.mk
@@ -44,7 +44,8 @@ REQUIRED_SUBSYSTEMS = \
# Start SUBSYSTEM SERVICE
[SUBSYSTEM::SERVER_SERVICE]
INIT_OBJ_FILES = \
- smbd/service.o
+ smbd/service.o \
+ smbd/service_stream.o
REQUIRED_SUBSYSTEMS = \
MESSAGING
# End SUBSYSTEM SERVER
@@ -54,8 +55,7 @@ REQUIRED_SUBSYSTEMS = \
# Start BINARY smbd
[BINARY::smbd]
OBJ_FILES = \
- smbd/server.o \
- smbd/rewrite.o
+ smbd/server.o
REQUIRED_SUBSYSTEMS = \
PROCESS_MODEL \
SERVER_SERVICE \
diff --git a/source4/smbd/process_model.c b/source4/smbd/process_model.c
index f2abfd0a49..16a0075d2d 100644
--- a/source4/smbd/process_model.c
+++ b/source4/smbd/process_model.c
@@ -22,12 +22,11 @@
#include "includes.h"
#include "events.h"
#include "smb_server/smb_server.h"
-#include "smbd/process_model.h"
/*
setup the events for the chosen process model
*/
-const struct model_ops *process_model_startup(struct server_context *srv_ctx, const char *model)
+const struct model_ops *process_model_startup(struct event_context *ev, const char *model)
{
const struct model_ops *ops;
@@ -37,7 +36,7 @@ const struct model_ops *process_model_startup(struct server_context *srv_ctx, co
exit(-1);
}
- ops->model_init(srv_ctx);
+ ops->model_init(ev);
return ops;
}
@@ -107,7 +106,6 @@ const struct process_model_critical_sizes *process_model_version(void)
static const struct process_model_critical_sizes critical_sizes = {
PROCESS_MODEL_VERSION,
sizeof(struct model_ops),
- sizeof(struct smbsrv_connection),
sizeof(struct event_context),
sizeof(struct fd_event)
};
diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h
index fb9bdfd44b..943538d7b2 100644
--- a/source4/smbd/process_model.h
+++ b/source4/smbd/process_model.h
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
- process model manager - main loop
- Copyright (C) Andrew Tridgell 1992-2003
+
+ process model manager - structures
+
+ Copyright (C) Andrew Tridgell 1992-2005
Copyright (C) James J Myers 2003 <myersjj@samba.org>
Copyright (C) Stefan (metze) Metzmacher 2004-2005
@@ -20,9 +22,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#ifndef SAMBA_PROCESS_MODEL_H
-#define SAMBA_PROCESS_MODEL_H
-
/* modules can use the following to determine if the interface has changed
* please increment the version number after each interface change
* with a comment and maybe update struct process_model_critical_sizes.
@@ -37,32 +36,22 @@ struct model_ops {
const char *name;
/* called at startup when the model is selected */
- void (*model_init)(struct server_context *srv_ctx);
- /* called at th eend of the main server process */
- void (*model_exit)(struct server_context *srv_ctx, const char *reason);
-
+ void (*model_init)(struct event_context *);
/* function to accept new connection */
- void (*accept_connection)(struct event_context *, struct fd_event *,
- struct timeval t, uint16_t);
- /* function to terminate a connection */
- void (*terminate_connection)(struct server_connection *srv_conn,
- const char *reason);
-
+ void (*accept_connection)(struct event_context *, struct socket_context *,
+ void (*)(struct event_context *, struct socket_context *,
+ uint32_t , void *),
+ void *);
- /* function to create a new task event_context */
- void (*create_task)(struct server_task *task);
- /* function to exit this task */
- void (*terminate_task)(struct server_task *task, const char *reason);
+ /* function to terminate a connection */
+ void (*terminate_connection)(struct event_context *, const char *reason);
};
/* this structure is used by modules to determine the size of some critical types */
struct process_model_critical_sizes {
int interface_version;
int sizeof_model_ops;
- int sizeof_server_context;
int sizeof_event_context;
int sizeof_fd_event;
};
-
-#endif /* SAMBA_PROCESS_MODEL_H */
diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c
index 6a00ad237f..d6217d8712 100644
--- a/source4/smbd/process_single.c
+++ b/source4/smbd/process_single.c
@@ -1,6 +1,8 @@
/*
Unix SMB/CIFS implementation.
+
process model: process (1 process handles all client connections)
+
Copyright (C) Andrew Tridgell 2003
Copyright (C) James J Myers 2003 <myersjj@samba.org>
Copyright (C) Stefan (metze) Metzmacher 2004
@@ -24,121 +26,57 @@
#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 single_model_init(struct server_context *server)
-{
-}
-
-static void single_model_exit(struct server_context *server, const char *reason)
+static void single_model_init(struct event_context *ev)
{
- DEBUG(1,("single_exit_server: 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 single_accept_connection(struct event_context *ev, struct fd_event *srv_fde,
- struct timeval t, uint16_t flags)
+static void single_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;
/* accept an incoming connection. */
- status = socket_accept(stream_socket->socket, &sock);
+ status = socket_accept(sock, &sock2);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("accept_connection_single: accept: %s\n",
- nt_errstr(status)));
- return;
- }
-
- conn = server_setup_connection(ev, stream_socket, sock, t, socket_get_fd(sock));
- if (!conn) {
- DEBUG(10,("server_setup_connection failed\n"));
+ DEBUG(0,("accept_connection_single: accept: %s\n", nt_errstr(status)));
return;
}
- talloc_steal(conn, sock);
+ talloc_steal(private, sock);
- /* return to event handling */
- return;
+ new_conn(ev, sock2, socket_get_fd(sock), private);
}
-
-/* called when a SMB connection goes down */
-static void single_terminate_connection(struct server_connection *conn, const char *reason)
+/* called when a connection goes down */
+static void single_terminate_connection(struct event_context *ev, const char *reason)
{
- DEBUG(2,("single_terminate_connection: reason[%s]\n",reason));
-
- if (conn) {
- talloc_free(conn);
- }
-}
-
-/*
- called to create a new event context for a new task
-*/
-static void single_create_task(struct server_task *task)
-{
- task->task.id = (uint32_t)task;
- 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);
- return;
-}
-
-/*
- called to exit from a server_task
-*/
-static void single_terminate_task(struct server_task *task, const char *reason)
-{
- DEBUG(1,("single_exit_server: reason[%s]\n",reason));
- talloc_free(task);
- return;
}
static const struct model_ops single_ops = {
.name = "single",
-
.model_init = single_model_init,
- .model_exit = single_model_exit,
-
.accept_connection = single_accept_connection,
.terminate_connection = single_terminate_connection,
-
- .create_task = single_create_task,
- .terminate_task = single_terminate_task
};
/*
- initialise the single process model, registering ourselves with the process model subsystem
+ initialise the single process model, registering ourselves with the
+ process model subsystem
*/
NTSTATUS process_model_single_init(void)
{
- NTSTATUS ret;
-
- /* register ourselves with the PROCESS_MODEL subsystem. */
- ret = register_process_model(&single_ops);
- if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(0,("Failed to register process_model 'single'!\n"));
- return ret;
- }
-
- return ret;
+ return register_process_model(&single_ops);
}
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);
}
diff --git a/source4/smbd/process_thread.c b/source4/smbd/process_thread.c
index 8d65292cfd..6b62ca413e 100644
--- a/source4/smbd/process_thread.c
+++ b/source4/smbd/process_thread.c
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
+
thread model: standard (1 thread per client connection)
- Copyright (C) Andrew Tridgell 2003
+
+ Copyright (C) Andrew Tridgell 2003-2005
Copyright (C) James J Myers 2003 <myersjj@samba.org>
Copyright (C) Stefan (metze) Metzmacher 2004
@@ -30,89 +32,85 @@
#include "events.h"
#include "dlinklist.h"
#include "smb_server/smb_server.h"
-#include "process_model.h"
+
+struct new_conn_state {
+ struct event_context *ev;
+ struct socket_context *sock;
+ void (*new_conn)(struct event_context *, struct socket_context *, uint32_t , void *);
+ void *private;
+};
static void *thread_connection_fn(void *thread_parm)
{
- struct server_connection *conn = thread_parm;
+ struct new_conn_state *new_conn = talloc_get_type(thread_parm, struct new_conn_state);
- conn->connection.id = pthread_self();
+ new_conn->new_conn(new_conn->ev, new_conn->sock, pthread_self(), new_conn->private);
- /* wait for action */
- event_loop_wait(conn->event.ctx);
+ /* run this connection from here */
+ event_loop_wait(new_conn->ev);
+
+ talloc_free(new_conn);
-#if 0
- pthread_cleanup_pop(1); /* will invoke terminate_mt_connection() */
-#endif
return NULL;
}
/*
called when a listening socket becomes readable
*/
-static void thread_accept_connection(struct event_context *ev, struct fd_event *srv_fde,
- struct timeval t, uint16_t flags)
+static void thread_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;
int rc;
pthread_t thread_id;
pthread_attr_t thread_attr;
- struct server_stream_socket *stream_socket = srv_fde->private;
- struct server_connection *conn;
+ struct new_conn_state *state;
+ struct event_context *ev2;
- /* accept an incoming connection. */
- status = socket_accept(stream_socket->socket, &sock);
- if (!NT_STATUS_IS_OK(status)) {
- return;
- }
+ ev2 = event_context_init(ev);
+ if (ev2 == NULL) return;
- /* create new detached thread for this connection. The new
- thread gets a new event_context with a single fd_event for
- receiving from the new socket. We set that thread running
- with the main event loop, then return. When we return the
- main event_context is continued.
- */
-
- ev = event_context_init(stream_socket);
- if (!ev) {
- socket_destroy(sock);
+ state = talloc(ev2, struct new_conn_state);
+ if (state == NULL) {
+ talloc_free(ev2);
return;
}
- conn = server_setup_connection(ev, stream_socket, sock, t, -1);
- if (!conn) {
- event_context_destroy(ev);
- socket_destroy(sock);
+ state->new_conn = new_conn;
+ state->private = private;
+ state->ev = ev2;
+
+ /* accept an incoming connection. */
+ status = socket_accept(sock, &state->sock);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(ev2);
return;
}
- talloc_steal(conn, ev);
- talloc_steal(conn, sock);
+ talloc_steal(state, state->sock);
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, conn);
+ rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, state);
pthread_attr_destroy(&thread_attr);
if (rc == 0) {
DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n",
(unsigned long int)thread_id, socket_get_fd(sock)));
} else {
DEBUG(0,("accept_connection_thread: thread create failed for fd=%d, rc=%d\n", socket_get_fd(sock), rc));
- event_context_destroy(ev);
- socket_destroy(sock);
- return;
+ talloc_free(ev2);
}
}
/* called when a SMB connection goes down */
-static void thread_terminate_connection(struct server_connection *conn, const char *reason)
+static void thread_terminate_connection(struct event_context *event_ctx, const char *reason)
{
DEBUG(10,("thread_terminate_connection: reason[%s]\n",reason));
- if (conn) {
- talloc_free(conn);
- }
+ talloc_free(event_ctx);
/* terminate this thread */
pthread_exit(NULL); /* thread cleanup routine will do actual cleanup */
@@ -342,6 +340,7 @@ static void thread_log_task_id(int fd)
write(fd, s, strlen(s));
free(s);
}
+
/****************************************************************************
catch serious errors
****************************************************************************/
@@ -406,7 +405,7 @@ static void thread_fault_handler(int sig)
/*
called when the process model is selected
*/
-static void thread_model_init(struct server_context *server)
+static void thread_model_init(struct event_context *event_context)
{
struct mutex_ops m_ops;
struct debug_ops d_ops;
@@ -438,89 +437,12 @@ static void thread_model_init(struct server_context *server)
register_debug_handlers("thread", &d_ops);
}
-static void thread_model_exit(struct server_context *server, const char *reason)
-{
- DEBUG(1,("thread_model_exit: reason[%s]\n",reason));
- talloc_free(server);
- exit(0);
-}
-
-static void *thread_task_fn(void *thread_parm)
-{
- struct server_task *task = thread_parm;
-
- task->task.id = pthread_self();
-
- task->event.ctx = event_context_init(task);
- if (!task->event.ctx) {
- server_terminate_task(task, "event_context_init() failed");
- return NULL;
- }
-
- task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx);
- if (!task->messaging.ctx) {
- server_terminate_task(task, "messaging_init() failed");
- return NULL;
- }
-
- task->task.ops->task_init(task);
-
- /* wait for action */
- event_loop_wait(task->event.ctx);
-
- server_terminate_task(task, "exit");
-#if 0
- pthread_cleanup_pop(1); /* will invoke terminate_mt_connection() */
-#endif
- return NULL;
-}
-/*
- called to create a new event context for a new task
-*/
-static void thread_create_task(struct server_task *task)
-{
- int rc;
- pthread_t thread_id;
- pthread_attr_t thread_attr;
-
- pthread_attr_init(&thread_attr);
- pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, task);
- pthread_attr_destroy(&thread_attr);
- if (rc == 0) {
- DEBUG(4,("thread_create_task: created thread_id=%lu for task='%s'\n",
- (unsigned long int)thread_id, task->task.ops->name));
- } else {
- DEBUG(0,("thread_create_task: thread create failed for task='%s', rc=%d\n", task->task.ops->name, rc));
- return;
- }
- return;
-}
-
-/*
- called to destroy a new event context for a new task
-*/
-static void thread_terminate_task(struct server_task *task, const char *reason)
-{
- DEBUG(2,("thread_terminate_task: reason[%s]\n",reason));
-
- talloc_free(task);
-
- /* terminate this thread */
- pthread_exit(NULL); /* thread cleanup routine will do actual cleanup */
-}
static const struct model_ops thread_ops = {
.name = "thread",
-
.model_init = thread_model_init,
- .model_exit = thread_model_exit,
-
.accept_connection = thread_accept_connection,
.terminate_connection = thread_terminate_connection,
-
- .create_task = thread_create_task,
- .terminate_task = thread_terminate_task
};
/*
diff --git a/source4/smbd/rewrite.c b/source4/smbd/rewrite.c
deleted file mode 100644
index 7128a0ad0d..0000000000
--- a/source4/smbd/rewrite.c
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "includes.h"
-#include "dynconfig.h"
-
-
-/*
- * initialize an smb process. Guaranteed to be called only once per
- * smbd instance (so it can assume it is starting from scratch, and
- * delete temporary files etc)
- */
-void smbd_process_init(void)
-{
- /* possibly reload the services file. */
- reload_services(NULL, True);
-
- if (*lp_rootdir()) {
- if (sys_chroot(lp_rootdir()) == 0)
- DEBUG(2,("Changed root to %s\n", lp_rootdir()));
- }
-
- service_cleanup_tmp_files();
-}
-
-void init_subsystems(void)
-{
- /* Do *not* remove this, until you have removed
- * passdb/secrets.c, and proved that Samba still builds... */
-
- /* Setup the SECRETS subsystem */
- if (!secrets_init()) {
- exit(1);
- }
-
- smbd_init_subsystems;
-}
-
-/****************************************************************************
- Reload the services file.
-**************************************************************************/
-BOOL reload_services(struct smbsrv_connection *smb, BOOL test)
-{
- BOOL ret;
-
- if (lp_loaded()) {
- pstring fname;
- pstrcpy(fname,lp_configfile());
- if (file_exist(fname, NULL) &&
- !strcsequal(fname, dyn_CONFIGFILE)) {
- pstrcpy(dyn_CONFIGFILE, fname);
- test = False;
- }
- }
-
- reopen_logs();
-
- if (test && !lp_file_list_changed())
- return(True);
-
- ret = lp_load(dyn_CONFIGFILE, False, False, True);
-
- /* perhaps the config filename is now set */
- if (!test)
- reload_services(smb, True);
-
- reopen_logs();
-
- load_interfaces();
-
- return(ret);
-}
-
diff --git a/source4/smbd/server.c b/source4/smbd/server.c
index 3c4c40fe1c..57f835970e 100644
--- a/source4/smbd/server.c
+++ b/source4/smbd/server.c
@@ -1,7 +1,9 @@
/*
Unix SMB/CIFS implementation.
+
Main SMB server routines
- Copyright (C) Andrew Tridgell 1992-1998
+
+ Copyright (C) Andrew Tridgell 1992-2005
Copyright (C) Martin Pool 2002
Copyright (C) Jelmer Vernooij 2002
Copyright (C) James J Myers 2003 <myersjj@samba.org>
@@ -23,56 +25,56 @@
#include "includes.h"
#include "version.h"
+#include "dynconfig.h"
#include "lib/cmdline/popt_common.h"
+#include "system/dir.h"
-/****************************************************************************
- main server.
-****************************************************************************/
-static int binary_smbd_main(int argc,const char *argv[])
+
+/*
+ cleanup temporary files. This is the new alternative to
+ TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
+ efficient on unix systems due to the lack of scaling of the byte
+ range locking system. So instead of putting the burden on tdb to
+ cleanup tmp files, this function deletes them.
+*/
+static void cleanup_tmp_files(void)
{
- BOOL is_daemon = False;
- BOOL interactive = False;
- BOOL Fork = True;
- BOOL log_stdout = False;
- int opt;
- poptContext pc;
- struct server_context *server;
- const char *model = "standard";
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- POPT_COMMON_SAMBA
- {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" , NULL },
- {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)", NULL},
- {"foreground", 'F', POPT_ARG_VAL, &Fork, True, "Run daemon in foreground (for daemontools & etc)" , NULL },
- {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout", NULL },
- {"port", 'p', POPT_ARG_STRING, NULL, 0, "Listen on the specified ports", "PORTS"},
- {"model", 'M', POPT_ARG_STRING, &model, True, "Select process model", "MODEL"},
- POPT_COMMON_VERSION
- POPT_TABLEEND
- };
-
- pc = poptGetContext("smbd", argc, argv, long_options, 0);
-
- while((opt = poptGetNextOpt(pc)) != -1) {
- switch (opt) {
- case 'p':
- lp_set_cmdline("smb ports", poptGetOptArg(pc));
- break;
- }
- }
- poptFreeContext(pc);
+ char *path;
+ DIR *dir;
+ struct dirent *de;
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
+
+ path = smbd_tmp_path(mem_ctx, NULL);
- if (interactive) {
- Fork = False;
- log_stdout = True;
+ dir = opendir(path);
+ if (!dir) {
+ talloc_free(mem_ctx);
+ return;
}
- if (log_stdout && Fork) {
- DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
- exit(1);
+ for (de=readdir(dir);de;de=readdir(dir)) {
+ char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
+ int ret = unlink(fname);
+ if (ret == -1 &&
+ errno != ENOENT &&
+ errno != EISDIR &&
+ errno != EISDIR) {
+ DEBUG(0,("Unabled to delete '%s' - %s\n",
+ fname, strerror(errno)));
+ smb_panic("unable to cleanup tmp files");
+ }
+ talloc_free(fname);
}
- setup_logging(argv[0], log_stdout?DEBUG_STDOUT:DEBUG_FILE);
+ closedir(dir);
+
+ talloc_free(mem_ctx);
+}
+/*
+ setup signal masks
+*/
+static void setup_signals(void)
+{
fault_setup(NULL);
/* we are never interested in SIGPIPE */
@@ -93,6 +95,39 @@ static int binary_smbd_main(int argc,const char *argv[])
BlockSignals(False, SIGHUP);
BlockSignals(False, SIGUSR1);
BlockSignals(False, SIGTERM);
+}
+
+
+/*
+ main server.
+*/
+static int binary_smbd_main(int argc, const char *argv[])
+{
+ BOOL interactive = False;
+ int opt;
+ poptContext pc;
+ struct event_context *event_ctx;
+ NTSTATUS status;
+ const char *model = "standard";
+ struct poptOption long_options[] = {
+ POPT_AUTOHELP
+ POPT_COMMON_SAMBA
+ {"interactive", 'i', POPT_ARG_VAL, &interactive, True,
+ "Run interactive (not a daemon)", NULL},
+ {"model", 'M', POPT_ARG_STRING, &model, True,
+ "Select process model", "MODEL"},
+ POPT_COMMON_VERSION
+ POPT_TABLEEND
+ };
+
+ pc = poptGetContext("smbd", argc, argv, long_options, 0);
+
+ while((opt = poptGetNextOpt(pc)) != -1) /* noop */ ;
+
+ poptFreeContext(pc);
+
+ setup_logging(argv[0], interactive?DEBUG_STDOUT:DEBUG_FILE);
+ setup_signals();
/* we want total control over the permissions on created files,
so set our umask to 0 */
@@ -108,49 +143,51 @@ static int binary_smbd_main(int argc,const char *argv[])
exit(1);
}
- if (!reload_services(NULL, False))
- return(-1);
-
- if (!is_daemon && !is_a_socket(0)) {
- if (!interactive)
- DEBUG(0,("standard input is not a socket, assuming -D option\n"));
+ lp_load(dyn_CONFIGFILE, False, False, True);
- /*
- * Setting is_daemon here prevents us from eventually calling
- * the open_sockets_inetd()
- */
-
- is_daemon = True;
- }
+ reopen_logs();
+ load_interfaces();
- if (is_daemon && !interactive) {
+ if (!interactive) {
DEBUG(3,("Becoming a daemon.\n"));
- become_daemon(Fork);
+ become_daemon(True);
}
+ cleanup_tmp_files();
+
if (!directory_exist(lp_lockdir(), NULL)) {
mkdir(lp_lockdir(), 0755);
}
- if (is_daemon) {
- pidfile_create("smbd");
+ pidfile_create("smbd");
+
+ /* Do *not* remove this, until you have removed
+ * passdb/secrets.c, and proved that Samba still builds... */
+ /* Setup the SECRETS subsystem */
+ if (!secrets_init()) {
+ exit(1);
}
- init_subsystems();
+ smbd_init_subsystems;
- smbd_process_init();
+ /* the event context is the top level structure in smbd. Everything else
+ should hang off that */
+ event_ctx = event_context_init(NULL);
DEBUG(0,("Using %s process model\n", model));
- server = server_service_startup(model, lp_server_services());
- if (!server) {
- DEBUG(0,("Starting Services failed.\n"));
+ status = server_service_startup(event_ctx, model, lp_server_services());
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
return 1;
}
- /* wait for events */
- event_loop_wait(server->event.ctx);
+ /* wait for events - this is where smbd sits for most of its
+ life */
+ event_loop_wait(event_ctx);
- server_service_shutdown(server, "exit");
+ /* as everything hangs off this event context, freeing it
+ should initiate a clean shutdown of all services */
+ talloc_free(event_ctx);
return 0;
}
diff --git a/source4/smbd/server.h b/source4/smbd/server.h
deleted file mode 100644
index 6021df12c5..0000000000
--- a/source4/smbd/server.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Stefan (metze) Metzmacher 2004
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _SERVER_H
-#define _SERVER_H
-
-struct server_service;
-struct event_context;
-
-struct server_context {
- struct {
- struct event_context *ctx;
- } event;
-
- struct {
- const struct model_ops *ops;
- } model;
-
- struct server_service *service_list;
-};
-
-/* size of listen() backlog in smbd */
-#define SERVER_LISTEN_BACKLOG 10
-
-/* the range of ports to try for dcerpc over tcp endpoints */
-#define SERVER_TCP_LOW_PORT 1024
-#define SERVER_TCP_HIGH_PORT 1300
-
-/* the default idle time of a service */
-#define SERVER_DEFAULT_IDLE_TIME 300
-
-#endif /* _SERVER_H */
diff --git a/source4/smbd/service.c b/source4/smbd/service.c
index 2d532b638d..ab377dc29b 100644
--- a/source4/smbd/service.c
+++ b/source4/smbd/service.c
@@ -3,7 +3,7 @@
SERVER SERVICE code
- Copyright (C) Andrew Tridgell 2003
+ Copyright (C) Andrew Tridgell 2003-2005
Copyright (C) Stefan (metze) Metzmacher 2004
This program is free software; you can redistribute it and/or modify
@@ -22,377 +22,77 @@
*/
#include "includes.h"
-#include "events.h"
-#include "system/dir.h"
#include "dlinklist.h"
#include "process_model.h"
-struct server_context *server_service_startup(const char *model, const char **server_services)
-{
- int i;
- struct server_context *server;
-
- if (!server_services) {
- DEBUG(0,("server_service_startup: no endpoint servers configured\n"));
- return NULL;
- }
-
- server = talloc_zero(NULL, struct server_context);
- if (!server) {
- return NULL;
- }
-
- server->model.ops = process_model_startup(server, model);
- if (!server->model.ops) {
- DEBUG(0,("process_model_startup('%s') failed\n", model));
- return NULL;
- }
-
- server->event.ctx = event_context_init(server);
- if (!server->event.ctx) {
- DEBUG(0,("event_context_init() failed\n"));
- return NULL;
- }
-
- for (i=0;server_services[i];i++) {
- const struct server_service_ops *service_ops;
- struct server_service *service;
-
- service_ops = server_service_byname(server_services[i]);
- if (!service_ops) {
- DEBUG(0,("process_model_startup: failed to find server service = '%s'\n", server_services[i]));
- return NULL;
- }
-
- service = talloc_zero(server, struct server_service);
- if (!service) {
- return NULL;
- }
-
- service->service.ops = service_ops;
- service->server = server;
-
- /* TODO: service_init() should return a result */
- service->service.ops->service_init(service);
-
- DLIST_ADD(server->service_list, service);
- }
-
- return server;
-}
-
-void server_service_shutdown(struct server_context *server, const char *reason)
-{
- server->model.ops->model_exit(server, reason);
-}
-
/*
- setup a listen stream socket
- if you pass *port == 0, then a port > 1024 is used
- */
-struct server_stream_socket *service_setup_stream_socket(struct server_service *service,
- const struct server_stream_ops *stream_ops,
- const char *family,
- const char *sock_addr,
- uint16_t *port)
-{
- NTSTATUS status;
- struct server_stream_socket *stream_socket;
- struct socket_context *sock;
- struct fd_event fde;
- int i;
-
- status = socket_create(family, SOCKET_TYPE_STREAM, &sock, 0);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Failed to open socket on %s:%u - %s\n",
- sock_addr, *port, nt_errstr(status)));
- return NULL;
- }
-
- /* ready to listen */
- status = socket_set_option(sock, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n",
- nt_errstr(status)));
- socket_destroy(sock);
- return NULL;
- }
- status = socket_set_option(sock, lp_socket_options(), NULL);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n",
- nt_errstr(status)));
- socket_destroy(sock);
- return NULL;
- }
-
- /* TODO: set socket ACL's here when they're implemented */
-
- if (*port == 0) {
- for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
- status = socket_listen(sock, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
- if (NT_STATUS_IS_OK(status)) {
- *port = i;
- break;
- }
- }
- } else {
- status = socket_listen(sock, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
- }
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Failed to listen on %s:%u - %s\n",
- sock_addr, *port, nt_errstr(status)));
- socket_destroy(sock);
- return NULL;
- }
-
- stream_socket = talloc_zero(service, struct server_stream_socket);
- if (!stream_socket) {
- DEBUG(0,("talloc(mem_ctx, struct server_stream_socket) failed\n"));
- socket_destroy(sock);
- return NULL;
- }
-
- /* we are only interested in read events on the listen socket */
- fde.fd = socket_get_fd(sock);
- fde.flags = EVENT_FD_READ;
- fde.private = stream_socket;
- fde.handler = server_accept_handler;
-
- stream_socket->stream.ops = stream_ops;
- stream_socket->service = service;
- stream_socket->socket = sock;
- stream_socket->event.ctx = service->server->event.ctx;
- stream_socket->event.fde = event_add_fd(stream_socket->event.ctx,
- &fde, stream_socket);
- if (!stream_socket->event.fde) {
- socket_destroy(sock);
- return NULL;
- }
-
- talloc_steal(stream_socket, sock);
-
- if (stream_socket->stream.ops->socket_init) {
- stream_socket->stream.ops->socket_init(stream_socket);
- }
-
- return stream_socket;
-}
-
-/*
- destructor that handles necessary event context changes
- */
-static int server_connection_destructor(void *ptr)
-{
- struct server_connection *conn = ptr;
-
- if (conn->stream_socket &&
- conn->stream_socket->stream.ops->close_connection) {
- /* don't remove this! the stream service needs to free it's data
- * before we destroy the server_connection
- */
- conn->stream_socket->stream.ops->close_connection(conn, "shutdown");
- }
-
- return 0;
-}
-
-struct server_connection *server_setup_connection(struct event_context *ev,
- struct server_stream_socket *stream_socket,
- struct socket_context *sock,
- struct timeval t,
- servid_t server_id)
-{
- struct fd_event fde;
- struct timed_event idle;
- struct server_connection *srv_conn;
-
- srv_conn = talloc(stream_socket, struct server_connection);
- if (!srv_conn) {
- DEBUG(0,("talloc(mem_ctx, struct server_connection) failed\n"));
- return NULL;
- }
-
- ZERO_STRUCTP(srv_conn);
-
- fde.private = srv_conn;
- fde.fd = socket_get_fd(sock);
- fde.flags = EVENT_FD_READ;
- fde.handler = server_io_handler;
-
- idle.private = srv_conn;
- idle.next_event = timeval_add(&t, SERVER_DEFAULT_IDLE_TIME, 0);
- idle.handler = server_idle_handler;
-
- srv_conn->event.ctx = ev;
- srv_conn->event.fde = &fde;
- srv_conn->event.idle = &idle;
- srv_conn->event.idle_time = timeval_set(SERVER_DEFAULT_IDLE_TIME, 0);
-
- srv_conn->stream_socket = stream_socket;
- srv_conn->socket = sock;
- srv_conn->connection.id = server_id;
-
- /* create a server context and add it to out event
- handling */
- stream_socket->stream.ops->accept_connection(srv_conn);
-
- /* accpect_connection() of the service may changed idle.next_event */
- srv_conn->event.fde = event_add_fd(ev, &fde, srv_conn);
- srv_conn->event.idle = event_add_timed(ev, &idle, srv_conn);
-
- talloc_set_destructor(srv_conn, server_connection_destructor);
-
- if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
- server_terminate_connection(srv_conn, "denied by access rules");
- return NULL;
- }
-
- /* setup to receive internal messages on this connection */
- srv_conn->messaging.ctx = messaging_init(srv_conn, srv_conn->connection.id, ev);
- if (!srv_conn->messaging.ctx) {
- server_terminate_connection(srv_conn, "messaging_init() failed");
- return NULL;
- }
-
- return srv_conn;
-}
+ a linked list of registered servers
+*/
+static struct registered_server {
+ struct registered_server *next, *prev;
+ const char *service_name;
+ NTSTATUS (*service_init)(struct event_context *, const struct model_ops *);
+} *registered_servers;
/*
- close the socket and shutdown a server_context
+ register a server service.
*/
-void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
-{
- DEBUG(2,("server_terminate_connection\n"));
- srv_conn->stream_socket->service->server->model.ops->terminate_connection(srv_conn, reason);
-}
-
-void server_accept_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
+NTSTATUS register_server_service(const char *name,
+ NTSTATUS (*service_init)(struct event_context *, const struct model_ops *))
{
- struct server_stream_socket *stream_socket = talloc_get_type(fde->private,
- struct server_stream_socket);
-
- stream_socket->service->server->model.ops->accept_connection(ev, fde, t, flags);
+ struct registered_server *srv;
+ srv = talloc(talloc_autofree_context(), struct registered_server);
+ NT_STATUS_HAVE_NO_MEMORY(srv);
+ srv->service_name = name;
+ srv->service_init = service_init;
+ DLIST_ADD_END(registered_servers, srv, struct registered_server *);
+ return NT_STATUS_OK;
}
-void server_io_handler(struct event_context *ev, struct fd_event *fde,
- struct timeval t, uint16_t flags)
-{
- struct server_connection *conn = talloc_get_type(fde->private,
- struct server_connection);
-
- conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
-
- if (flags & EVENT_FD_WRITE) {
- conn->stream_socket->stream.ops->send_handler(conn, t, flags);
- return;
- }
-
- if (flags & EVENT_FD_READ) {
- conn->stream_socket->stream.ops->recv_handler(conn, t, flags);
- }
-
-}
-
-void server_idle_handler(struct event_context *ev, struct timed_event *idle,
- struct timeval t)
-{
- struct server_connection *conn = talloc_get_type(idle->private,
- struct server_connection);
-
- /* Not all services provide an idle handler */
- if (conn->stream_socket->stream.ops->idle_handler) {
- conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
- conn->stream_socket->stream.ops->idle_handler(conn, t);
- }
-}
-
-void server_terminate_task(struct server_task *task, const char *reason)
-{
- task->service->server->model.ops->terminate_task(task, reason);
- return;
-}
-
-void server_run_task(struct server_service *service, const struct server_task_ops *ops)
-{
- struct server_task *task;
-
- task = talloc_zero(service, struct server_task);
- if (!task) {
- return;
- }
- task->service = service;
- task->task.ops = ops;
-
- service->server->model.ops->create_task(task);
- return;
-}
/*
- return the operations structure for a named backend of the specified type
+ initialise a server service
*/
-const struct server_service_ops *server_service_byname(const char *name)
+static NTSTATUS server_service_init(const char *name,
+ struct event_context *event_ctx,
+ const struct model_ops *model_ops)
{
- if (strcmp("smb",name)==0) {
- return smbsrv_get_ops();
- }
- if (strcmp("rpc",name)==0) {
- return dcesrv_get_ops();
- }
- if (strcmp("ldap",name)==0) {
- return ldapsrv_get_ops();
- }
- if (strcmp("winbind",name)==0) {
- return winbind_get_ops();
- }
- if (strcmp("winbind_task",name)==0) {
- return winbind_task_get_ops();
+ struct registered_server *srv;
+ for (srv=registered_servers; srv; srv=srv->next) {
+ if (strcasecmp(name, srv->service_name) == 0) {
+ return srv->service_init(event_ctx, model_ops);
+ }
}
- return NULL;
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
-NTSTATUS register_server_service_ops(const void *_ops)
-{
- return NT_STATUS_NOT_IMPLEMENTED;
-}
/*
- cleanup temporary files. This is the new alternative to
- TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
- efficient on unix systems due to the lack of scaling of the byte
- range locking system. So instead of putting the burden on tdb to
- cleanup tmp files, this function deletes them.
+ startup all of our server services
*/
-void service_cleanup_tmp_files(void)
+NTSTATUS server_service_startup(struct event_context *event_ctx,
+ const char *model, const char **server_services)
{
- char *path;
- DIR *dir;
- struct dirent *de;
- TALLOC_CTX *mem_ctx = talloc_init("service_cleanup_tmp_files");
+ int i;
+ const struct model_ops *model_ops;
- path = smbd_tmp_path(mem_ctx, NULL);
+ if (!server_services) {
+ DEBUG(0,("server_service_startup: no endpoint servers configured\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
- dir = opendir(path);
- if (!dir) {
- talloc_free(mem_ctx);
- return;
+ model_ops = process_model_startup(event_ctx, model);
+ if (!model_ops) {
+ DEBUG(0,("process_model_startup('%s') failed\n", model));
+ return NT_STATUS_INTERNAL_ERROR;
}
- for (de=readdir(dir);de;de=readdir(dir)) {
- char *fname = talloc_asprintf(mem_ctx, "%s/%s", path, de->d_name);
- int ret = unlink(fname);
- if (ret == -1 &&
- errno != ENOENT &&
- errno != EISDIR &&
- errno != EISDIR) {
- DEBUG(0,("Unabled to delete '%s' - %s\n",
- fname, strerror(errno)));
- smb_panic("unable to cleanup tmp files");
- }
- talloc_free(fname);
+ for (i=0;server_services[i];i++) {
+ NTSTATUS status;
+
+ status = server_service_init(server_services[i], event_ctx, model_ops);
+ NT_STATUS_NOT_OK_RETURN(status);
}
- closedir(dir);
- talloc_free(mem_ctx);
+ return NT_STATUS_OK;
}
diff --git a/source4/smbd/service.h b/source4/smbd/service.h
deleted file mode 100644
index d5335b1cef..0000000000
--- a/source4/smbd/service.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- SERVER SERVICE code
-
- Copyright (C) Stefan (metze) Metzmacher 2004
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _SERVER_SERVICE_H
-#define _SERVER_SERVICE_H
-
-struct event_context;
-struct model_ops;
-struct server_context;
-
-struct server_connection;
-struct server_service;
-
-/* modules can use the following to determine if the interface has changed
- * please increment the version number after each interface change
- * with a comment and maybe update struct process_model_critical_sizes.
- */
-/* version 1 - initial version - metze */
-#define SERVER_SERVICE_VERSION 1
-
-struct server_service_ops {
- /* the name of the server_service */
- const char *name;
-
- /* called at startup when the server_service is selected */
- void (*service_init)(struct server_service *service);
-};
-
-struct server_stream_socket;
-
-struct server_stream_ops {
- /* the name of the server_service */
- const char *name;
-
- /* called at startup when the server_service is selected */
- void (*socket_init)(struct server_stream_socket *socket);
-
- /* function to accept new connection */
- void (*accept_connection)(struct server_connection *);
-
- void (*recv_handler)(struct server_connection *, struct timeval, uint16_t);
-
- void (*send_handler)(struct server_connection *, struct timeval, uint16_t);
-
- /* function to be called when the server is idle */
- void (*idle_handler)(struct server_connection *, struct timeval);
-
- /* function to close a connection */
- void (*close_connection)(struct server_connection *, const char *reason);
-};
-
-struct socket_context;
-
-struct server_stream_socket {
- struct server_stream_socket *next,*prev;
- struct {
- const struct server_stream_ops *ops;
- void *private_data;
- } stream;
-
- struct {
- struct event_context *ctx;
- struct fd_event *fde;
- } event;
-
- struct socket_context *socket;
-
- struct server_service *service;
-};
-
-struct server_service {
- struct server_service *next,*prev;
- struct {
- const struct server_service_ops *ops;
- void *private_data;
- } service;
-
- struct server_context *server;
-};
-
-/* the concept of whether two operations are on the same server
- connection or different connections is an important one in SMB, especially
- for locking and share modes. We will use a servid_t to distinguish different
- connections
-
- this means that (for example) a unique open file is distinguished by the triple
- of
- servid_t server;
- uint16 tid;
- uint16 fnum;
-*/
-typedef uint32_t servid_t;
-
-struct server_connection {
- struct server_connection *next,*prev;
- struct {
- void *private_data;
- servid_t id;
- } connection;
-
- struct {
- struct event_context *ctx;
- struct fd_event *fde;
- struct timed_event *idle;
- struct timeval idle_time;
- } event;
-
- struct socket_context *socket;
-
- struct server_stream_socket *stream_socket;
-
- struct {
- struct messaging_context *ctx;
- } messaging;
-};
-
-struct server_task;
-
-struct server_task_ops {
- /* the name of the server_task */
- const char *name;
-
- /* called at startup when the server_task is selected */
- void (*task_init)(struct server_task *task);
-};
-
-struct server_task {
- struct server_task *next,*prev;
- struct {
- const struct server_task_ops *ops;
- void *private_data;
- servid_t id;
- } task;
-
- struct {
- struct event_context *ctx;
- } event;
-
- struct {
- struct messaging_context *ctx;
- } messaging;
-
- struct server_service *service;
-};
-
-#endif /* _SERVER_SERVICE_H */