mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
r5104: - added support for task based servers. These are servers that within
themselves are run as a single process, but run as a child of the main process when smbd is run in the standard model, and run as part of the main process when in the single mode. - rewrote the winbind template code to use the new task services. Also fixed the packet queueing - got rid of event_context_merge() as it is no longer needed
This commit is contained in:
parent
3c5a7650a9
commit
339964a596
@ -40,6 +40,7 @@ sub smb_build_main($)
|
||||
"smb_server/config.mk",
|
||||
"rpc_server/config.mk",
|
||||
"ldap_server/config.mk",
|
||||
"winbind/config.mk",
|
||||
"libcli/auth/gensec.mk",
|
||||
"libcli/auth/config.mk",
|
||||
"libcli/ldap/config.mk",
|
||||
|
@ -154,5 +154,6 @@ struct nbt_name_status;
|
||||
|
||||
struct messaging_context;
|
||||
struct stream_connection;
|
||||
struct task_server;
|
||||
struct model_ops;
|
||||
struct stream_server_ops;
|
||||
|
@ -110,32 +110,6 @@ static void calc_maxfd(struct event_context *ev)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
move the event structures from ev2 into ev, upping the reference
|
||||
count on ev. The event context ev2 is then destroyed.
|
||||
|
||||
this is used by modules that need to call on the events of a lower module
|
||||
*/
|
||||
struct event_context *event_context_merge(struct event_context *ev,
|
||||
struct event_context *ev2)
|
||||
{
|
||||
DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *);
|
||||
DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *);
|
||||
DLIST_CONCATENATE(ev->loop_events, ev2->loop_events, struct loop_event *);
|
||||
|
||||
ev2->fd_events = NULL;
|
||||
ev2->timed_events = NULL;
|
||||
ev2->loop_events = NULL;
|
||||
|
||||
talloc_steal(ev->events, ev2->events);
|
||||
|
||||
event_context_destroy(ev2);
|
||||
|
||||
calc_maxfd(ev);
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
/* to mark the ev->maxfd invalid
|
||||
* this means we need to recalculate it
|
||||
*/
|
||||
|
@ -45,7 +45,8 @@ REQUIRED_SUBSYSTEMS = \
|
||||
[SUBSYSTEM::SERVER_SERVICE]
|
||||
INIT_OBJ_FILES = \
|
||||
smbd/service.o \
|
||||
smbd/service_stream.o
|
||||
smbd/service_stream.o \
|
||||
smbd/service_task.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
MESSAGING
|
||||
# End SUBSYSTEM SERVER
|
||||
|
@ -44,8 +44,14 @@ struct model_ops {
|
||||
uint32_t , void *),
|
||||
void *);
|
||||
|
||||
/* function to terminate a connection */
|
||||
void (*terminate_connection)(struct event_context *, const char *reason);
|
||||
/* function to create a task */
|
||||
void (*new_task)(struct event_context *,
|
||||
void (*)(struct event_context *, uint32_t, void *),
|
||||
void *);
|
||||
|
||||
/* function to terminate a task */
|
||||
void (*terminate)(struct event_context *, const char *reason);
|
||||
|
||||
};
|
||||
|
||||
/* this structure is used by modules to determine the size of some critical types */
|
||||
|
@ -59,17 +59,29 @@ static void single_accept_connection(struct event_context *ev,
|
||||
new_conn(ev, sock2, socket_get_fd(sock), private);
|
||||
}
|
||||
|
||||
/*
|
||||
called to startup a new task
|
||||
*/
|
||||
static void single_new_task(struct event_context *ev,
|
||||
void (*new_task)(struct event_context *, uint32_t, void *),
|
||||
void *private)
|
||||
{
|
||||
static uint32_t taskid = 0x10000000;
|
||||
new_task(ev, taskid++, private);
|
||||
}
|
||||
|
||||
/* called when a connection goes down */
|
||||
static void single_terminate_connection(struct event_context *ev, const char *reason)
|
||||
|
||||
/* called when a task goes down */
|
||||
static void single_terminate(struct event_context *ev, const char *reason)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct model_ops single_ops = {
|
||||
.name = "single",
|
||||
.model_init = single_model_init,
|
||||
.new_task = single_new_task,
|
||||
.accept_connection = single_accept_connection,
|
||||
.terminate_connection = single_terminate_connection,
|
||||
.terminate = single_terminate,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -104,11 +104,60 @@ static void standard_accept_connection(struct event_context *ev,
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/* called when a connection goes down */
|
||||
static void standard_terminate_connection(struct event_context *ev, const char *reason)
|
||||
/*
|
||||
called to create a new server task
|
||||
*/
|
||||
static void standard_new_task(struct event_context *ev,
|
||||
void (*new_task)(struct event_context *, uint32_t , void *),
|
||||
void *private)
|
||||
{
|
||||
DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason));
|
||||
pid_t pid;
|
||||
struct event_context *ev2;
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid != 0) {
|
||||
/* parent or error code ... go back to the event loop */
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is now the child code. We need a completely new event_context to work with */
|
||||
ev2 = event_context_init(NULL);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* this will free all the listening sockets and all state that
|
||||
is not associated with this new connection */
|
||||
talloc_free(ev);
|
||||
|
||||
/* 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();
|
||||
|
||||
/* setup this new connection */
|
||||
new_task(ev2, getpid(), private);
|
||||
|
||||
/* 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);
|
||||
|
||||
talloc_free(ev2);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/* called when a task goes down */
|
||||
static void standard_terminate(struct event_context *ev, const char *reason)
|
||||
{
|
||||
DEBUG(2,("standard_terminate: reason[%s]\n",reason));
|
||||
|
||||
/* this init_iconv() has the effect of freeing the iconv context memory,
|
||||
which makes leak checking easier */
|
||||
@ -128,7 +177,8 @@ static const struct model_ops standard_ops = {
|
||||
.name = "standard",
|
||||
.model_init = standard_model_init,
|
||||
.accept_connection = standard_accept_connection,
|
||||
.terminate_connection = standard_terminate_connection,
|
||||
.new_task = standard_new_task,
|
||||
.terminate = standard_terminate,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -105,10 +105,70 @@ static void thread_accept_connection(struct event_context *ev,
|
||||
}
|
||||
}
|
||||
|
||||
/* called when a SMB connection goes down */
|
||||
static void thread_terminate_connection(struct event_context *event_ctx, const char *reason)
|
||||
|
||||
struct new_task_state {
|
||||
struct event_context *ev;
|
||||
void (*new_task)(struct event_context *, uint32_t , void *);
|
||||
void *private;
|
||||
};
|
||||
|
||||
static void *thread_task_fn(void *thread_parm)
|
||||
{
|
||||
DEBUG(10,("thread_terminate_connection: reason[%s]\n",reason));
|
||||
struct new_task_state *new_task = talloc_get_type(thread_parm, struct new_task_state);
|
||||
|
||||
new_task->new_task(new_task->ev, pthread_self(), new_task->private);
|
||||
|
||||
/* run this connection from here */
|
||||
event_loop_wait(new_task->ev);
|
||||
|
||||
talloc_free(new_task);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
called when a new task is needed
|
||||
*/
|
||||
static void thread_new_task(struct event_context *ev,
|
||||
void (*new_task)(struct event_context *, uint32_t , void *),
|
||||
void *private)
|
||||
{
|
||||
int rc;
|
||||
pthread_t thread_id;
|
||||
pthread_attr_t thread_attr;
|
||||
struct new_task_state *state;
|
||||
struct event_context *ev2;
|
||||
|
||||
ev2 = event_context_init(ev);
|
||||
if (ev2 == NULL) return;
|
||||
|
||||
state = talloc(ev2, struct new_task_state);
|
||||
if (state == NULL) {
|
||||
talloc_free(ev2);
|
||||
return;
|
||||
}
|
||||
|
||||
state->new_task = new_task;
|
||||
state->private = private;
|
||||
state->ev = ev2;
|
||||
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, state);
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
if (rc == 0) {
|
||||
DEBUG(4,("thread_new_task: created thread_id=%lu\n",
|
||||
(unsigned long int)thread_id));
|
||||
} else {
|
||||
DEBUG(0,("thread_new_task: thread create failed rc=%d\n", rc));
|
||||
talloc_free(ev2);
|
||||
}
|
||||
}
|
||||
|
||||
/* called when a task goes down */
|
||||
static void thread_terminate(struct event_context *event_ctx, const char *reason)
|
||||
{
|
||||
DEBUG(10,("thread_terminate: reason[%s]\n",reason));
|
||||
|
||||
talloc_free(event_ctx);
|
||||
|
||||
@ -442,7 +502,8 @@ static const struct model_ops thread_ops = {
|
||||
.name = "thread",
|
||||
.model_init = thread_model_init,
|
||||
.accept_connection = thread_accept_connection,
|
||||
.terminate_connection = thread_terminate_connection,
|
||||
.new_task = thread_new_task,
|
||||
.terminate = thread_terminate,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
hepler functions for stream based servers
|
||||
helper functions for stream based servers
|
||||
|
||||
Copyright (C) Andrew Tridgell 2003-2005
|
||||
Copyright (C) Stefan (metze) Metzmacher 2004
|
||||
@ -54,7 +54,7 @@ void stream_terminate_connection(struct stream_connection *srv_conn, const char
|
||||
struct event_ctx *event_ctx = srv_conn->event.ctx;
|
||||
const struct model_ops *model_ops = srv_conn->model_ops;
|
||||
talloc_free(srv_conn);
|
||||
model_ops->terminate_connection(event_ctx, reason);
|
||||
model_ops->terminate(event_ctx, reason);
|
||||
}
|
||||
|
||||
/*
|
||||
|
90
source/smbd/service_task.c
Normal file
90
source/smbd/service_task.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
helper functions for task based servers (nbtd, winbind etc)
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "process_model.h"
|
||||
#include "events.h"
|
||||
#include "smbd/service_task.h"
|
||||
|
||||
/*
|
||||
terminate a task service
|
||||
*/
|
||||
void task_terminate(struct task_server *task, const char *reason)
|
||||
{
|
||||
struct event_ctx *event_ctx = task->event_ctx;
|
||||
const struct model_ops *model_ops = task->model_ops;
|
||||
talloc_free(task);
|
||||
model_ops->terminate(event_ctx, reason);
|
||||
}
|
||||
|
||||
/* used for the callback from the process model code */
|
||||
struct task_state {
|
||||
void (*task_init)(struct task_server *);
|
||||
const struct model_ops *model_ops;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
called by the process model code when the new task starts up. This then calls
|
||||
the server specific startup code
|
||||
*/
|
||||
static void task_server_callback(struct event_context *event_ctx, uint32_t server_id, void *private)
|
||||
{
|
||||
struct task_state *state = talloc_get_type(private, struct task_state);
|
||||
struct task_server *task;
|
||||
|
||||
task = talloc(event_ctx, struct task_server);
|
||||
if (task == NULL) return;
|
||||
|
||||
task->event_ctx = event_ctx;
|
||||
task->model_ops = state->model_ops;
|
||||
task->server_id = server_id;
|
||||
|
||||
task->msg_ctx = messaging_init(task, task->server_id, task->event_ctx);
|
||||
if (!task->msg_ctx) {
|
||||
task_terminate(task, "messaging_init() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
state->task_init(task);
|
||||
}
|
||||
|
||||
/*
|
||||
startup a task based server
|
||||
*/
|
||||
NTSTATUS task_server_startup(struct event_context *event_ctx,
|
||||
const struct model_ops *model_ops,
|
||||
void (*task_init)(struct task_server *))
|
||||
{
|
||||
struct task_state *state;
|
||||
|
||||
state = talloc(event_ctx, struct task_state);
|
||||
NT_STATUS_HAVE_NO_MEMORY(state);
|
||||
|
||||
state->task_init = task_init;
|
||||
state->model_ops = model_ops;
|
||||
|
||||
model_ops->new_task(event_ctx, task_server_callback, state);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
30
source/smbd/service_task.h
Normal file
30
source/smbd/service_task.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
structures for task based servers
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
|
||||
struct task_server {
|
||||
struct event_context *event_ctx;
|
||||
const struct model_ops *model_ops;
|
||||
struct messaging_context *msg_ctx;
|
||||
uint32_t server_id;
|
||||
};
|
||||
|
@ -3,6 +3,7 @@
|
||||
Main winbindd server routines
|
||||
|
||||
Copyright (C) Stefan Metzmacher 2005
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
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
|
||||
@ -20,8 +21,10 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "dlinklist.h"
|
||||
#include "events.h"
|
||||
#include "system/time.h"
|
||||
#include "smbd/service_task.h"
|
||||
#include "smbd/service_stream.h"
|
||||
|
||||
#define WINBINDD_DIR "/tmp/.winbindd/"
|
||||
#define WINBINDD_ECHO_SOCKET WINBINDD_DIR"echo"
|
||||
@ -29,201 +32,163 @@
|
||||
#define WINBINDD_ECHO_ADDR WINBINDD_ADDR_PREFIX"1"
|
||||
#define WINBINDD_ECHO_PORT 55555
|
||||
|
||||
static void winbind_accept(struct server_connection *conn)
|
||||
/*
|
||||
state of an open winbind connection
|
||||
*/
|
||||
struct wbserver_connection {
|
||||
DATA_BLOB blob;
|
||||
struct send_queue {
|
||||
struct send_queue *next, *prev;
|
||||
DATA_BLOB blob;
|
||||
} *queue;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
called when we get a new connection
|
||||
*/
|
||||
static void winbind_accept(struct stream_connection *conn)
|
||||
{
|
||||
DEBUG(10,("winbind_accept:\n"));
|
||||
struct wbserver_connection *wbconn;
|
||||
|
||||
wbconn = talloc_zero(conn, struct wbserver_connection);
|
||||
wbconn->blob = data_blob_talloc(wbconn, NULL, 1024);
|
||||
|
||||
conn->private = wbconn;
|
||||
}
|
||||
|
||||
static DATA_BLOB tmp_blob;
|
||||
|
||||
static void winbind_recv(struct server_connection *conn, struct timeval t, uint16_t flags)
|
||||
/*
|
||||
receive some data on a winbind connection
|
||||
*/
|
||||
static void winbind_recv(struct stream_connection *conn, struct timeval t, uint16_t flags)
|
||||
{
|
||||
|
||||
|
||||
struct wbserver_connection *wbconn = talloc_get_type(conn->private, struct wbserver_connection);
|
||||
NTSTATUS status;
|
||||
size_t nread;
|
||||
struct send_queue *q;
|
||||
|
||||
if (!tmp_blob.data) {
|
||||
tmp_blob = data_blob_talloc(conn, NULL, 1024);
|
||||
if (tmp_blob.data == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
tmp_blob.length = 1024;
|
||||
status = socket_recv(conn->socket, tmp_blob.data, tmp_blob.length, &nread, 0);
|
||||
status = socket_recv(conn->socket, wbconn->blob.data, wbconn->blob.length, &nread, 0);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
DEBUG(10,("socket_recv: %s\n",nt_errstr(status)));
|
||||
talloc_free(tmp_blob.data);
|
||||
server_terminate_connection(conn, "socket_recv: failed\n");
|
||||
stream_terminate_connection(conn, "socket_recv: failed\n");
|
||||
return;
|
||||
}
|
||||
tmp_blob.length = nread;
|
||||
#if 0
|
||||
DEBUG(0,("winbind_recv:\n"));
|
||||
dump_data(0, tmp_blob.data, tmp_blob.length);
|
||||
#endif
|
||||
|
||||
/* just reflect the data back down the socket */
|
||||
q = talloc(wbconn, struct send_queue);
|
||||
if (q == NULL) {
|
||||
stream_terminate_connection(conn, "winbind_recv: out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
q->blob = data_blob_talloc(q, wbconn->blob.data, nread);
|
||||
if (q->blob.data == NULL) {
|
||||
stream_terminate_connection(conn, "winbind_recv: out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DLIST_ADD_END(wbconn->queue, q, struct send_queue *);
|
||||
|
||||
conn->event.fde->flags |= EVENT_FD_WRITE;
|
||||
}
|
||||
|
||||
static void winbind_send(struct server_connection *conn, struct timeval t, uint16_t flags)
|
||||
/*
|
||||
called when we can write to a connection
|
||||
*/
|
||||
static void winbind_send(struct stream_connection *conn, struct timeval t, uint16_t flags)
|
||||
{
|
||||
NTSTATUS status;
|
||||
size_t sendlen;
|
||||
struct wbserver_connection *wbconn = talloc_get_type(conn->private, struct wbserver_connection);
|
||||
|
||||
if (tmp_blob.length > 1 && tmp_blob.data[0] == (uint8_t)'q') {
|
||||
while (wbconn->queue) {
|
||||
struct send_queue *q = wbconn->queue;
|
||||
NTSTATUS status;
|
||||
size_t sendlen;
|
||||
|
||||
status = socket_send(conn->socket, &q->blob, &sendlen, 0);
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
|
||||
stream_terminate_connection(conn, "socket_send: failed\n");
|
||||
return;
|
||||
}
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
q->blob.length -= sendlen;
|
||||
q->blob.data += sendlen;
|
||||
|
||||
if (q->blob.length == 0) {
|
||||
DLIST_REMOVE(wbconn->queue, q);
|
||||
talloc_free(q);
|
||||
}
|
||||
}
|
||||
|
||||
status = socket_send(conn->socket, &tmp_blob, &sendlen, 0);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(10,("socket_send() %s\n",nt_errstr(status)));
|
||||
server_terminate_connection(conn, "socket_send: failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tmp_blob.length > 1 && tmp_blob.data[0] == (uint8_t)'q') {
|
||||
server_terminate_connection(conn, "winbind_send: user quit\n");
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
DEBUG(0,("winbind_send:\n"));
|
||||
dump_data(0, tmp_blob.data, tmp_blob.length);
|
||||
#endif
|
||||
tmp_blob.length -= sendlen;
|
||||
|
||||
if (tmp_blob.length == 0) {
|
||||
conn->event.fde->flags &= ~EVENT_FD_WRITE;
|
||||
}
|
||||
conn->event.fde->flags &= ~EVENT_FD_WRITE;
|
||||
}
|
||||
|
||||
static void winbind_idle(struct server_connection *conn, struct timeval t)
|
||||
{
|
||||
DEBUG(1,("winbind_idle: not implemented!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
static void winbind_close(struct server_connection *conn, const char *reason)
|
||||
{
|
||||
DEBUG(10,("winbind_close: %s\n", reason));
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int winbind_task_server_contect_destructor(void *ptr)
|
||||
{
|
||||
struct server_context *server = ptr;
|
||||
|
||||
server_service_shutdown(server, "exit");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void winbind_server_task_init(struct server_task *task)
|
||||
{
|
||||
const char *wb_task_service[] = { "winbind_task", NULL };
|
||||
struct server_context *server;
|
||||
|
||||
DEBUG(1,("winbindsrv_task_init\n"));
|
||||
server = server_service_startup("single", wb_task_service);
|
||||
if (!server) {
|
||||
DEBUG(0,("Starting Services (winbind_task) failed.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
task->task.private_data = talloc_steal(task, server);
|
||||
|
||||
task->event.ctx = event_context_merge(task->event.ctx, server->event.ctx);
|
||||
server->event.ctx = talloc_reference(server, task->event.ctx);
|
||||
|
||||
talloc_set_destructor(server, winbind_task_server_contect_destructor);
|
||||
|
||||
/* wait for events */
|
||||
event_loop_wait(task->event.ctx);
|
||||
}
|
||||
|
||||
static const struct server_task_ops winbind_srver_task_ops = {
|
||||
.name = "winbind_server_task",
|
||||
.task_init = winbind_server_task_init
|
||||
};
|
||||
|
||||
static const struct server_task_ops *winbind_srver_task_get_ops(void)
|
||||
{
|
||||
return &winbind_srver_task_ops;
|
||||
}
|
||||
|
||||
static const struct server_stream_ops winbind_stream_ops = {
|
||||
.name = "winbind",
|
||||
.socket_init = NULL,
|
||||
static const struct stream_server_ops winbind_stream_ops = {
|
||||
.name = "smb",
|
||||
.accept_connection = winbind_accept,
|
||||
.recv_handler = winbind_recv,
|
||||
.send_handler = winbind_send,
|
||||
.idle_handler = winbind_idle,
|
||||
.close_connection = winbind_close
|
||||
};
|
||||
|
||||
static const struct server_stream_ops *winbind_get_stream_ops(void)
|
||||
/*
|
||||
startup the winbind task
|
||||
*/
|
||||
static void winbind_task_init(struct task_server *task)
|
||||
{
|
||||
return &winbind_stream_ops;
|
||||
}
|
||||
|
||||
static void winbind_task_init(struct server_service *service)
|
||||
{
|
||||
struct server_stream_socket *stream_socket;
|
||||
uint16_t port = 1;
|
||||
const struct model_ops *model_ops;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(1,("winbind_task_init\n"));
|
||||
/* within the winbind task we want to be a single process, so
|
||||
ask for the single process model ops and pass these to the
|
||||
stream_setup_socket() call. */
|
||||
model_ops = process_model_byname("single");
|
||||
if (!model_ops) {
|
||||
task_terminate(task, "Can't find 'single' process model_ops");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure the directory for NCALRPC exists */
|
||||
if (!directory_exist(WINBINDD_DIR, NULL)) {
|
||||
mkdir(WINBINDD_DIR, 0755);
|
||||
}
|
||||
|
||||
stream_socket = service_setup_stream_socket(service, winbind_get_stream_ops(), "unix", WINBINDD_ECHO_SOCKET, &port);
|
||||
if (!stream_socket) {
|
||||
DEBUG(0,("service_setup_stream_socket(path=%s) failed\n",WINBINDD_ECHO_SOCKET));
|
||||
status = stream_setup_socket(task->event_ctx, model_ops, &winbind_stream_ops,
|
||||
"unix", WINBINDD_ECHO_SOCKET, &port, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("service_setup_stream_socket(path=%s) failed - %s\n",
|
||||
WINBINDD_ECHO_SOCKET, nt_errstr(status)));
|
||||
task_terminate(task, "winbind Failed to find to ECHO unix socket");
|
||||
return;
|
||||
}
|
||||
|
||||
port = WINBINDD_ECHO_PORT;
|
||||
stream_socket = service_setup_stream_socket(service, winbind_get_stream_ops(), "ipv4", WINBINDD_ECHO_ADDR, &port);
|
||||
if (!stream_socket) {
|
||||
DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed\n",WINBINDD_ECHO_ADDR, port));
|
||||
|
||||
status = stream_setup_socket(task->event_ctx, model_ops, &winbind_stream_ops,
|
||||
"ipv4", WINBINDD_ECHO_ADDR, &port, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed - %s\n",
|
||||
WINBINDD_ECHO_ADDR, port, nt_errstr(status)));
|
||||
task_terminate(task, "winbind Failed to find to ECHO tcp socket");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct server_service_ops winbind_task_ops = {
|
||||
.name = "winbind_task",
|
||||
.service_init = winbind_task_init,
|
||||
};
|
||||
|
||||
const struct server_service_ops *winbind_task_get_ops(void)
|
||||
/*
|
||||
initialise the winbind server
|
||||
*/
|
||||
static NTSTATUS winbind_init(struct event_context *event_ctx, const struct model_ops *model_ops)
|
||||
{
|
||||
return &winbind_task_ops;
|
||||
}
|
||||
|
||||
static void winbind_init(struct server_service *service)
|
||||
{
|
||||
DEBUG(1,("winbind_init\n"));
|
||||
|
||||
server_run_task(service, winbind_srver_task_get_ops());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct server_service_ops winbind_ops = {
|
||||
.name = "winbind",
|
||||
.service_init = winbind_init,
|
||||
};
|
||||
|
||||
const struct server_service_ops *winbind_get_ops(void)
|
||||
{
|
||||
return &winbind_ops;
|
||||
return task_server_startup(event_ctx, model_ops, winbind_task_init);
|
||||
}
|
||||
|
||||
/*
|
||||
register ourselves as a available server
|
||||
*/
|
||||
NTSTATUS server_service_winbind_init(void)
|
||||
{
|
||||
return NT_STATUS_OK;
|
||||
return register_server_service("winbind", winbind_init);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user