diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/include/messages.h | 36 | ||||
-rw-r--r-- | source3/lib/messages.c | 425 | ||||
-rw-r--r-- | source3/lib/messages_local.c | 431 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 4 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_dual.c | 10 |
6 files changed, 492 insertions, 416 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index a071bc2a7f..4a01c7d454 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -261,7 +261,7 @@ TALLOC_OBJ = lib/talloc/talloc.o LIB_WITHOUT_PROTO_OBJ = $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) $(TALLOC_OBJ) \ - lib/messages.o librpc/gen_ndr/ndr_messaging.o + lib/messages.o librpc/gen_ndr/ndr_messaging.o lib/messages_local.o LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/interface.o lib/md4.o \ diff --git a/source3/include/messages.h b/source3/include/messages.h index 46c4660936..cde104e897 100644 --- a/source3/include/messages.h +++ b/source3/include/messages.h @@ -22,6 +22,10 @@ #ifndef _MESSAGES_H_ #define _MESSAGES_H_ +/* change the message version with any incompatible changes in the protocol */ +#define MESSAGE_VERSION 2 + + #define MSG_TYPE_MASK 0xFFFF /* general messages */ @@ -115,15 +119,41 @@ struct server_id { }; struct messaging_context; +struct messaging_rec; struct data_blob; +/* + * struct messaging_context belongs to messages.c, but because we still have + * messaging_dispatch, we need it here. Once we get rid of signals for + * notifying processes, this will go. + */ + +struct messaging_context { + struct server_id id; + struct event_context *event_ctx; + struct messaging_callback *callbacks; + + struct messaging_backend *local; +}; + +struct messaging_backend { + NTSTATUS (*send_fn)(struct messaging_context *msg_ctx, + struct server_id pid, int msg_type, + const struct data_blob *data, + struct messaging_backend *backend); + void *private_data; +}; + +NTSTATUS messaging_tdb_init(struct messaging_context *msg_ctx, + TALLOC_CTX *mem_ctx, + struct messaging_backend **presult); void message_dispatch(struct messaging_context *msg_ctx); + + BOOL message_send_all(struct messaging_context *msg_ctx, int msg_type, const void *buf, size_t len, int *n_sent); -void message_block(void); -void message_unblock(void); struct event_context *messaging_event_context(struct messaging_context *msg_ctx); struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, struct server_id server_id, @@ -144,5 +174,7 @@ NTSTATUS messaging_send(struct messaging_context *msg_ctx, NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx, struct server_id server, uint32_t msg_type, const uint8 *buf, size_t len); +void messaging_dispatch_rec(struct messaging_context *msg_ctx, + struct messaging_rec *rec); #endif diff --git a/source3/lib/messages.c b/source3/lib/messages.c index e1434ff01f..056286f89a 100644 --- a/source3/lib/messages.c +++ b/source3/lib/messages.c @@ -50,12 +50,6 @@ #include "librpc/gen_ndr/messaging.h" #include "librpc/gen_ndr/ndr_messaging.h" -/* the locking database handle */ -static int received_signal; - -/* change the message version with any incompatible changes in the protocol */ -#define MESSAGE_VERSION 2 - struct messaging_callback { struct messaging_callback *prev, *next; uint32 msg_type; @@ -65,25 +59,6 @@ struct messaging_callback { void *private_data; }; -struct messaging_context { - TDB_CONTEXT *tdb; - struct server_id id; - struct event_context *event_ctx; - struct messaging_callback *callbacks; - - -}; - -/**************************************************************************** - Notifications come in as signals. -****************************************************************************/ - -static void sig_usr1(void) -{ - received_signal = 1; - sys_select_signal(SIGUSR1); -} - /**************************************************************************** A useful function for testing the message system. ****************************************************************************/ @@ -102,362 +77,6 @@ static void ping_message(struct messaging_context *msg_ctx, } /**************************************************************************** - Initialise the messaging functions. -****************************************************************************/ - -static BOOL message_tdb_init(struct messaging_context *msg_ctx) -{ - sec_init(); - - msg_ctx->tdb = tdb_open_log(lock_path("messages.tdb"), - 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR|O_CREAT,0600); - - if (!msg_ctx->tdb) { - DEBUG(0,("ERROR: Failed to initialise messages database\n")); - return False; - } - - /* Activate the per-hashchain freelist */ - tdb_set_max_dead(msg_ctx->tdb, 5); - - CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1); - - return True; -} - -/******************************************************************* - Form a static tdb key from a pid. -******************************************************************/ - -static TDB_DATA message_key_pid(struct server_id pid) -{ - static char key[20]; - TDB_DATA kbuf; - - slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid)); - - kbuf.dptr = (uint8 *)key; - kbuf.dsize = strlen(key)+1; - return kbuf; -} - -/* - Fetch the messaging array for a process - */ - -static NTSTATUS messaging_tdb_fetch(TDB_CONTEXT *msg_tdb, - TDB_DATA key, - TALLOC_CTX *mem_ctx, - struct messaging_array **presult) -{ - struct messaging_array *result; - TDB_DATA data; - DATA_BLOB blob; - NTSTATUS status; - - if (!(result = TALLOC_ZERO_P(mem_ctx, struct messaging_array))) { - return NT_STATUS_NO_MEMORY; - } - - data = tdb_fetch(msg_tdb, key); - - if (data.dptr == NULL) { - *presult = result; - return NT_STATUS_OK; - } - - blob = data_blob_const(data.dptr, data.dsize); - - status = ndr_pull_struct_blob( - &blob, result, result, - (ndr_pull_flags_fn_t)ndr_pull_messaging_array); - - SAFE_FREE(data.dptr); - - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(result); - return status; - } - - if (DEBUGLEVEL >= 10) { - DEBUG(10, ("messaging_tdb_fetch:\n")); - NDR_PRINT_DEBUG(messaging_array, result); - } - - *presult = result; - return NT_STATUS_OK; -} - -/* - Store a messaging array for a pid -*/ - -static NTSTATUS messaging_tdb_store(TDB_CONTEXT *msg_tdb, - TDB_DATA key, - struct messaging_array *array) -{ - TDB_DATA data; - DATA_BLOB blob; - NTSTATUS status; - TALLOC_CTX *mem_ctx; - int ret; - - if (array->num_messages == 0) { - tdb_delete(msg_tdb, key); - return NT_STATUS_OK; - } - - if (!(mem_ctx = talloc_new(array))) { - return NT_STATUS_NO_MEMORY; - } - - status = ndr_push_struct_blob( - &blob, mem_ctx, array, - (ndr_push_flags_fn_t)ndr_push_messaging_array); - - if (!NT_STATUS_IS_OK(status)) { - talloc_free(mem_ctx); - return status; - } - - if (DEBUGLEVEL >= 10) { - DEBUG(10, ("messaging_tdb_store:\n")); - NDR_PRINT_DEBUG(messaging_array, array); - } - - data.dptr = blob.data; - data.dsize = blob.length; - - ret = tdb_store(msg_tdb, key, data, TDB_REPLACE); - TALLOC_FREE(mem_ctx); - - return (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION; -} - -/**************************************************************************** - Notify a process that it has a message. If the process doesn't exist - then delete its record in the database. -****************************************************************************/ - -static NTSTATUS message_notify(struct server_id procid) -{ - pid_t pid = procid.pid; - int ret; - uid_t euid = geteuid(); - - /* - * Doing kill with a non-positive pid causes messages to be - * sent to places we don't want. - */ - - SMB_ASSERT(pid > 0); - - if (euid != 0) { - /* If we're not root become so to send the message. */ - save_re_uid(); - set_effective_uid(0); - } - - ret = kill(pid, SIGUSR1); - - if (euid != 0) { - /* Go back to who we were. */ - int saved_errno = errno; - restore_re_uid_fromroot(); - errno = saved_errno; - } - - if (ret == 0) { - return NT_STATUS_OK; - } - - /* - * Something has gone wrong - */ - - DEBUG(2,("message to process %d failed - %s\n", (int)pid, - strerror(errno))); - - /* - * No call to map_nt_error_from_unix -- don't want to link in - * errormap.o into lots of utils. - */ - - if (errno == ESRCH) return NT_STATUS_INVALID_HANDLE; - if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER; - if (errno == EPERM) return NT_STATUS_ACCESS_DENIED; - return NT_STATUS_UNSUCCESSFUL; -} - -/**************************************************************************** - Send a message to a particular pid. -****************************************************************************/ - -static NTSTATUS messaging_tdb_send(struct messaging_context *msg_ctx, - struct server_id pid, int msg_type, - const DATA_BLOB *data) -{ - struct messaging_array *msg_array; - struct messaging_rec *rec; - TALLOC_CTX *mem_ctx; - NTSTATUS status; - TDB_DATA key = message_key_pid(pid); - - /* NULL pointer means implicit length zero. */ - if (!data->data) { - SMB_ASSERT(data->length == 0); - } - - /* - * Doing kill with a non-positive pid causes messages to be - * sent to places we don't want. - */ - - SMB_ASSERT(procid_to_pid(&pid) > 0); - - if (!(mem_ctx = talloc_init("message_send_pid"))) { - return NT_STATUS_NO_MEMORY; - } - - if (tdb_chainlock(msg_ctx->tdb, key) == -1) { - TALLOC_FREE(mem_ctx); - return NT_STATUS_LOCK_NOT_GRANTED; - } - - status = messaging_tdb_fetch(msg_ctx->tdb, key, mem_ctx, &msg_array); - - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - if ((msg_type & MSG_FLAG_LOWPRIORITY) - && (msg_array->num_messages > 1000)) { - DEBUG(5, ("Dropping message for PID %s\n", - procid_str_static(&pid))); - status = NT_STATUS_INSUFFICIENT_RESOURCES; - goto done; - } - - if (!(rec = TALLOC_REALLOC_ARRAY(mem_ctx, msg_array->messages, - struct messaging_rec, - msg_array->num_messages+1))) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - rec[msg_array->num_messages].msg_version = MESSAGE_VERSION; - rec[msg_array->num_messages].msg_type = msg_type & MSG_TYPE_MASK; - rec[msg_array->num_messages].dest = pid; - rec[msg_array->num_messages].src = procid_self(); - rec[msg_array->num_messages].buf = *data; - - msg_array->messages = rec; - msg_array->num_messages += 1; - - status = messaging_tdb_store(msg_ctx->tdb, key, msg_array); - - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - - status = message_notify(pid); - - if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { - DEBUG(2, ("pid %s doesn't exist - deleting messages record\n", - procid_str_static(&pid))); - tdb_delete(msg_ctx->tdb, message_key_pid(pid)); - } - - done: - tdb_chainunlock(msg_ctx->tdb, key); - TALLOC_FREE(mem_ctx); - return status; -} - -/**************************************************************************** - Retrieve all messages for the current process. -****************************************************************************/ - -static NTSTATUS retrieve_all_messages(TDB_CONTEXT *msg_tdb, - TALLOC_CTX *mem_ctx, - struct messaging_array **presult) -{ - struct messaging_array *result; - TDB_DATA key = message_key_pid(procid_self()); - NTSTATUS status; - - if (tdb_chainlock(msg_tdb, key) == -1) { - return NT_STATUS_LOCK_NOT_GRANTED; - } - - status = messaging_tdb_fetch(msg_tdb, key, mem_ctx, &result); - - /* - * We delete the record here, tdb_set_max_dead keeps it around - */ - tdb_delete(msg_tdb, key); - tdb_chainunlock(msg_tdb, key); - - if (NT_STATUS_IS_OK(status)) { - *presult = result; - } - - return status; -} - -/* - Dispatch one messsaging_rec -*/ -static void messaging_dispatch_rec(struct messaging_context *msg_ctx, - struct messaging_rec *rec) -{ - struct messaging_callback *cb, *next; - - for (cb = msg_ctx->callbacks; cb != NULL; cb = next) { - next = cb->next; - if (cb->msg_type == rec->msg_type) { - cb->fn(msg_ctx, cb->private_data, rec->msg_type, - rec->src, &rec->buf); - return; - } - } - return; -} - -/**************************************************************************** - Receive and dispatch any messages pending for this process. - JRA changed Dec 13 2006. Only one message handler now permitted per type. - *NOTE*: Dispatch functions must be able to cope with incoming - messages on an *odd* byte boundary. -****************************************************************************/ - -void message_dispatch(struct messaging_context *msg_ctx) -{ - struct messaging_array *msg_array = NULL; - uint32 i; - - if (!received_signal) - return; - - DEBUG(10, ("message_dispatch: received_signal = %d\n", - received_signal)); - - received_signal = 0; - - if (!NT_STATUS_IS_OK(retrieve_all_messages(msg_ctx->tdb, NULL, - &msg_array))) { - return; - } - - for (i=0; i<msg_array->num_messages; i++) { - messaging_dispatch_rec(msg_ctx, &msg_array->messages[i]); - } - - TALLOC_FREE(msg_array); -} - -/**************************************************************************** Register/replace a dispatch function for a particular message type. JRA changed Dec 13 2006. Only one message handler now permitted per type. *NOTE*: Dispatch functions must be able to cope with incoming @@ -564,21 +183,6 @@ BOOL message_send_all(struct messaging_context *msg_ctx, return True; } -/* - * Block and unblock receiving of messages. Allows removal of race conditions - * when doing a fork and changing message disposition. - */ - -void message_block(void) -{ - BlockSignals(True, SIGUSR1); -} - -void message_unblock(void) -{ - BlockSignals(False, SIGUSR1); -} - struct event_context *messaging_event_context(struct messaging_context *msg_ctx) { return msg_ctx->event_ctx; @@ -589,6 +193,7 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, struct event_context *ev) { struct messaging_context *ctx; + NTSTATUS status; if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) { return NULL; @@ -597,8 +202,10 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, ctx->id = server_id; ctx->event_ctx = ev; - if (!message_tdb_init(ctx)) { - DEBUG(0, ("message_init failed: %s\n", strerror(errno))); + status = messaging_tdb_init(ctx, ctx, &ctx->local); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("message_init failed: %s\n", nt_errstr(status))); TALLOC_FREE(ctx); } @@ -677,7 +284,8 @@ NTSTATUS messaging_send(struct messaging_context *msg_ctx, struct server_id server, uint32_t msg_type, const DATA_BLOB *data) { - return messaging_tdb_send(msg_ctx, server, msg_type, data); + return msg_ctx->local->send_fn(msg_ctx, server, msg_type, data, + msg_ctx->local); } NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx, @@ -688,4 +296,23 @@ NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx, return messaging_send(msg_ctx, server, msg_type, &blob); } +/* + Dispatch one messsaging_rec +*/ +void messaging_dispatch_rec(struct messaging_context *msg_ctx, + struct messaging_rec *rec) +{ + struct messaging_callback *cb, *next; + + for (cb = msg_ctx->callbacks; cb != NULL; cb = next) { + next = cb->next; + if (cb->msg_type == rec->msg_type) { + cb->fn(msg_ctx, cb->private_data, rec->msg_type, + rec->src, &rec->buf); + return; + } + } + return; +} + /** @} **/ diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c new file mode 100644 index 0000000000..b459ce0238 --- /dev/null +++ b/source3/lib/messages_local.c @@ -0,0 +1,431 @@ +/* + Unix SMB/CIFS implementation. + Samba internal messaging functions + Copyright (C) 2007 by Volker Lendecke + + 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. +*/ + +/** + @defgroup messages Internal messaging framework + @{ + @file messages.c + + @brief Module for internal messaging between Samba daemons. + + The idea is that if a part of Samba wants to do communication with + another Samba process then it will do a message_register() of a + dispatch function, and use message_send_pid() to send messages to + that process. + + The dispatch function is given the pid of the sender, and it can + use that to reply by message_send_pid(). See ping_message() for a + simple example. + + @caution Dispatch functions must be able to cope with incoming + messages on an *odd* byte boundary. + + This system doesn't have any inherent size limitations but is not + very efficient for large messages or when messages are sent in very + quick succession. + +*/ + +#include "includes.h" +#include "librpc/gen_ndr/messaging.h" +#include "librpc/gen_ndr/ndr_messaging.h" + +/* the locking database handle */ +static int received_signal; + +static NTSTATUS messaging_tdb_send(struct messaging_context *msg_ctx, + struct server_id pid, int msg_type, + const DATA_BLOB *data, + struct messaging_backend *backend); + +/**************************************************************************** + Notifications come in as signals. +****************************************************************************/ + +static void sig_usr1(void) +{ + received_signal = 1; + sys_select_signal(SIGUSR1); +} + +static int messaging_tdb_destructor(struct messaging_backend *tdb_ctx) +{ + TDB_CONTEXT *tdb = (TDB_CONTEXT *)tdb_ctx->private_data; + tdb_close(tdb); + return 0; +} + +/**************************************************************************** + Initialise the messaging functions. +****************************************************************************/ + +NTSTATUS messaging_tdb_init(struct messaging_context *msg_ctx, + TALLOC_CTX *mem_ctx, + struct messaging_backend **presult) +{ + struct messaging_backend *result; + TDB_CONTEXT *tdb; + + if (!(result = TALLOC_P(mem_ctx, struct messaging_backend))) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + tdb = tdb_open_log(lock_path("messages.tdb"), + 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR|O_CREAT,0600); + + if (!tdb) { + DEBUG(0,("ERROR: Failed to initialise messages database\n")); + TALLOC_FREE(result); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + sec_init(); + + /* Activate the per-hashchain freelist */ + tdb_set_max_dead(tdb, 5); + + CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1); + + result->private_data = (void *)tdb; + result->send_fn = messaging_tdb_send; + + talloc_set_destructor(result, messaging_tdb_destructor); + + *presult = result; + return NT_STATUS_OK; +} + +/******************************************************************* + Form a static tdb key from a pid. +******************************************************************/ + +static TDB_DATA message_key_pid(struct server_id pid) +{ + static char key[20]; + TDB_DATA kbuf; + + slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid)); + + kbuf.dptr = (uint8 *)key; + kbuf.dsize = strlen(key)+1; + return kbuf; +} + +/* + Fetch the messaging array for a process + */ + +static NTSTATUS messaging_tdb_fetch(TDB_CONTEXT *msg_tdb, + TDB_DATA key, + TALLOC_CTX *mem_ctx, + struct messaging_array **presult) +{ + struct messaging_array *result; + TDB_DATA data; + DATA_BLOB blob; + NTSTATUS status; + + if (!(result = TALLOC_ZERO_P(mem_ctx, struct messaging_array))) { + return NT_STATUS_NO_MEMORY; + } + + data = tdb_fetch(msg_tdb, key); + + if (data.dptr == NULL) { + *presult = result; + return NT_STATUS_OK; + } + + blob = data_blob_const(data.dptr, data.dsize); + + status = ndr_pull_struct_blob( + &blob, result, result, + (ndr_pull_flags_fn_t)ndr_pull_messaging_array); + + SAFE_FREE(data.dptr); + + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(result); + return status; + } + + if (DEBUGLEVEL >= 10) { + DEBUG(10, ("messaging_tdb_fetch:\n")); + NDR_PRINT_DEBUG(messaging_array, result); + } + + *presult = result; + return NT_STATUS_OK; +} + +/* + Store a messaging array for a pid +*/ + +static NTSTATUS messaging_tdb_store(TDB_CONTEXT *msg_tdb, + TDB_DATA key, + struct messaging_array *array) +{ + TDB_DATA data; + DATA_BLOB blob; + NTSTATUS status; + TALLOC_CTX *mem_ctx; + int ret; + + if (array->num_messages == 0) { + tdb_delete(msg_tdb, key); + return NT_STATUS_OK; + } + + if (!(mem_ctx = talloc_new(array))) { + return NT_STATUS_NO_MEMORY; + } + + status = ndr_push_struct_blob( + &blob, mem_ctx, array, + (ndr_push_flags_fn_t)ndr_push_messaging_array); + + if (!NT_STATUS_IS_OK(status)) { + talloc_free(mem_ctx); + return status; + } + + if (DEBUGLEVEL >= 10) { + DEBUG(10, ("messaging_tdb_store:\n")); + NDR_PRINT_DEBUG(messaging_array, array); + } + + data.dptr = blob.data; + data.dsize = blob.length; + + ret = tdb_store(msg_tdb, key, data, TDB_REPLACE); + TALLOC_FREE(mem_ctx); + + return (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION; +} + +/**************************************************************************** + Notify a process that it has a message. If the process doesn't exist + then delete its record in the database. +****************************************************************************/ + +static NTSTATUS message_notify(struct server_id procid) +{ + pid_t pid = procid.pid; + int ret; + uid_t euid = geteuid(); + + /* + * Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. + */ + + SMB_ASSERT(pid > 0); + + if (euid != 0) { + /* If we're not root become so to send the message. */ + save_re_uid(); + set_effective_uid(0); + } + + ret = kill(pid, SIGUSR1); + + if (euid != 0) { + /* Go back to who we were. */ + int saved_errno = errno; + restore_re_uid_fromroot(); + errno = saved_errno; + } + + if (ret == 0) { + return NT_STATUS_OK; + } + + /* + * Something has gone wrong + */ + + DEBUG(2,("message to process %d failed - %s\n", (int)pid, + strerror(errno))); + + /* + * No call to map_nt_error_from_unix -- don't want to link in + * errormap.o into lots of utils. + */ + + if (errno == ESRCH) return NT_STATUS_INVALID_HANDLE; + if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER; + if (errno == EPERM) return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + Send a message to a particular pid. +****************************************************************************/ + +static NTSTATUS messaging_tdb_send(struct messaging_context *msg_ctx, + struct server_id pid, int msg_type, + const DATA_BLOB *data, + struct messaging_backend *backend) +{ + struct messaging_array *msg_array; + struct messaging_rec *rec; + TALLOC_CTX *mem_ctx; + NTSTATUS status; + TDB_DATA key = message_key_pid(pid); + TDB_CONTEXT *tdb = (TDB_CONTEXT *)backend->private_data; + + /* NULL pointer means implicit length zero. */ + if (!data->data) { + SMB_ASSERT(data->length == 0); + } + + /* + * Doing kill with a non-positive pid causes messages to be + * sent to places we don't want. + */ + + SMB_ASSERT(procid_to_pid(&pid) > 0); + + if (!(mem_ctx = talloc_init("message_send_pid"))) { + return NT_STATUS_NO_MEMORY; + } + + if (tdb_chainlock(tdb, key) == -1) { + TALLOC_FREE(mem_ctx); + return NT_STATUS_LOCK_NOT_GRANTED; + } + + status = messaging_tdb_fetch(tdb, key, mem_ctx, &msg_array); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if ((msg_type & MSG_FLAG_LOWPRIORITY) + && (msg_array->num_messages > 1000)) { + DEBUG(5, ("Dropping message for PID %s\n", + procid_str_static(&pid))); + status = NT_STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + + if (!(rec = TALLOC_REALLOC_ARRAY(mem_ctx, msg_array->messages, + struct messaging_rec, + msg_array->num_messages+1))) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + rec[msg_array->num_messages].msg_version = MESSAGE_VERSION; + rec[msg_array->num_messages].msg_type = msg_type & MSG_TYPE_MASK; + rec[msg_array->num_messages].dest = pid; + rec[msg_array->num_messages].src = procid_self(); + rec[msg_array->num_messages].buf = *data; + + msg_array->messages = rec; + msg_array->num_messages += 1; + + status = messaging_tdb_store(tdb, key, msg_array); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = message_notify(pid); + + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) { + DEBUG(2, ("pid %s doesn't exist - deleting messages record\n", + procid_str_static(&pid))); + tdb_delete(tdb, message_key_pid(pid)); + } + + done: + tdb_chainunlock(tdb, key); + TALLOC_FREE(mem_ctx); + return status; +} + +/**************************************************************************** + Retrieve all messages for the current process. +****************************************************************************/ + +static NTSTATUS retrieve_all_messages(TDB_CONTEXT *msg_tdb, + TALLOC_CTX *mem_ctx, + struct messaging_array **presult) +{ + struct messaging_array *result; + TDB_DATA key = message_key_pid(procid_self()); + NTSTATUS status; + + if (tdb_chainlock(msg_tdb, key) == -1) { + return NT_STATUS_LOCK_NOT_GRANTED; + } + + status = messaging_tdb_fetch(msg_tdb, key, mem_ctx, &result); + + /* + * We delete the record here, tdb_set_max_dead keeps it around + */ + tdb_delete(msg_tdb, key); + tdb_chainunlock(msg_tdb, key); + + if (NT_STATUS_IS_OK(status)) { + *presult = result; + } + + return status; +} + +/**************************************************************************** + Receive and dispatch any messages pending for this process. + JRA changed Dec 13 2006. Only one message handler now permitted per type. + *NOTE*: Dispatch functions must be able to cope with incoming + messages on an *odd* byte boundary. +****************************************************************************/ + +void message_dispatch(struct messaging_context *msg_ctx) +{ + struct messaging_array *msg_array = NULL; + TDB_CONTEXT *tdb = (TDB_CONTEXT *)(msg_ctx->local->private_data); + uint32 i; + + if (!received_signal) + return; + + DEBUG(10, ("message_dispatch: received_signal = %d\n", + received_signal)); + + received_signal = 0; + + if (!NT_STATUS_IS_OK(retrieve_all_messages(tdb, NULL, &msg_array))) { + return; + } + + for (i=0; i<msg_array->num_messages; i++) { + messaging_dispatch_rec(msg_ctx, &msg_array->messages[i]); + } + + TALLOC_FREE(msg_array); +} + +/** @} **/ diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 1e9292b690..ba91239a73 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -178,13 +178,10 @@ static BOOL fork_child_dc_connect(struct winbindd_domain *domain) /* Stop zombies */ CatchChild(); - message_block(); - child_pid = sys_fork(); if (child_pid == -1) { DEBUG(0, ("fork_child_dc_connect: Could not fork: %s\n", strerror(errno))); - message_unblock(); return False; } @@ -196,7 +193,6 @@ static BOOL fork_child_dc_connect(struct winbindd_domain *domain) messaging_register(winbind_messaging_context(), NULL, MSG_WINBIND_FAILED_TO_GO_ONLINE, msg_failed_to_go_online); - message_unblock(); return True; } diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index 2e8ad154db..c65499f606 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -839,15 +839,10 @@ static BOOL fork_domain_child(struct winbindd_child *child) /* Stop zombies */ CatchChild(); - /* Ensure we don't process messages whilst we're - changing the disposition for the child. */ - message_block(); - child->pid = sys_fork(); if (child->pid == -1) { DEBUG(0, ("Could not fork: %s\n", strerror(errno))); - message_unblock(); return False; } @@ -860,8 +855,6 @@ static BOOL fork_domain_child(struct winbindd_child *child) child->event.flags = 0; child->requests = NULL; add_fd_event(&child->event); - /* We're ok with online/offline messages now. */ - message_unblock(); return True; } @@ -895,9 +888,6 @@ static BOOL fork_domain_child(struct winbindd_child *child) messaging_deregister(winbind_messaging_context(), MSG_WINBIND_ONLINESTATUS, NULL); - /* The child is ok with online/offline messages now. */ - message_unblock(); - /* Handle online/offline messages. */ messaging_register(winbind_messaging_context(), NULL, MSG_WINBIND_OFFLINE, child_msg_offline); |