2 Unix SMB/CIFS implementation.
3 Samba internal messaging functions
4 Copyright (C) Andrew Tridgell 2000
5 Copyright (C) 2001 by Martin Pool
6 Copyright (C) 2002 by Jeremy Allison
7 Copyright (C) 2007 by Volker Lendecke
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 @defgroup messages Internal messaging framework
29 @brief Module for internal messaging between Samba daemons.
31 The idea is that if a part of Samba wants to do communication with
32 another Samba process then it will do a message_register() of a
33 dispatch function, and use message_send_pid() to send messages to
36 The dispatch function is given the pid of the sender, and it can
37 use that to reply by message_send_pid(). See ping_message() for a
40 @caution Dispatch functions must be able to cope with incoming
41 messages on an *odd* byte boundary.
43 This system doesn't have any inherent size limitations but is not
44 very efficient for large messages or when messages are sent in very
50 #include "librpc/gen_ndr/messaging.h"
51 #include "librpc/gen_ndr/ndr_messaging.h"
53 /* the locking database handle */
54 static int received_signal;
56 /* change the message version with any incompatible changes in the protocol */
57 #define MESSAGE_VERSION 2
59 struct messaging_callback {
60 struct messaging_callback *prev, *next;
62 void (*fn)(struct messaging_context *msg, void *private_data,
64 struct server_id server_id, DATA_BLOB *data);
68 struct messaging_context {
71 struct event_context *event_ctx;
72 struct messaging_callback *callbacks;
75 /****************************************************************************
76 Notifications come in as signals.
77 ****************************************************************************/
79 static void sig_usr1(void)
82 sys_select_signal(SIGUSR1);
85 static NTSTATUS messaging_tdb_send(TDB_CONTEXT *msg_tdb,
86 struct server_id pid, int msg_type,
87 const void *buf, size_t len);
89 /****************************************************************************
90 A useful function for testing the message system.
91 ****************************************************************************/
93 static void ping_message(struct messaging_context *msg_ctx,
99 const char *msg = data->data ? (const char *)data->data : "none";
101 DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
102 procid_str_static(&src), msg));
103 messaging_send(msg_ctx, src, MSG_PONG, data);
106 /****************************************************************************
107 Initialise the messaging functions.
108 ****************************************************************************/
110 static BOOL message_init(struct messaging_context *msg_ctx)
114 msg_ctx->tdb = tdb_open_log(lock_path("messages.tdb"),
115 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
116 O_RDWR|O_CREAT,0600);
119 DEBUG(0,("ERROR: Failed to initialise messages database\n"));
123 /* Activate the per-hashchain freelist */
124 tdb_set_max_dead(msg_ctx->tdb, 5);
126 CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
128 messaging_register(msg_ctx, NULL, MSG_PING, ping_message);
130 /* Register some debugging related messages */
132 register_msg_pool_usage(msg_ctx);
133 register_dmalloc_msgs(msg_ctx);
134 debug_register_msgs(msg_ctx);
139 /*******************************************************************
140 Form a static tdb key from a pid.
141 ******************************************************************/
143 static TDB_DATA message_key_pid(struct server_id pid)
148 slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid));
150 kbuf.dptr = (uint8 *)key;
151 kbuf.dsize = strlen(key)+1;
156 Fetch the messaging array for a process
159 static NTSTATUS messaging_tdb_fetch(TDB_CONTEXT *msg_tdb,
162 struct messaging_array **presult)
164 struct messaging_array *result;
169 if (!(result = TALLOC_ZERO_P(mem_ctx, struct messaging_array))) {
170 return NT_STATUS_NO_MEMORY;
173 data = tdb_fetch(msg_tdb, key);
175 if (data.dptr == NULL) {
180 blob = data_blob_const(data.dptr, data.dsize);
182 status = ndr_pull_struct_blob(
183 &blob, result, result,
184 (ndr_pull_flags_fn_t)ndr_pull_messaging_array);
186 SAFE_FREE(data.dptr);
188 if (!NT_STATUS_IS_OK(status)) {
193 if (DEBUGLEVEL >= 10) {
194 DEBUG(10, ("messaging_tdb_fetch:\n"));
195 NDR_PRINT_DEBUG(messaging_array, result);
203 Store a messaging array for a pid
206 static NTSTATUS messaging_tdb_store(TDB_CONTEXT *msg_tdb,
208 struct messaging_array *array)
216 if (array->num_messages == 0) {
217 tdb_delete(msg_tdb, key);
221 if (!(mem_ctx = talloc_new(array))) {
222 return NT_STATUS_NO_MEMORY;
225 status = ndr_push_struct_blob(
226 &blob, mem_ctx, array,
227 (ndr_push_flags_fn_t)ndr_push_messaging_array);
229 if (!NT_STATUS_IS_OK(status)) {
230 talloc_free(mem_ctx);
234 if (DEBUGLEVEL >= 10) {
235 DEBUG(10, ("messaging_tdb_store:\n"));
236 NDR_PRINT_DEBUG(messaging_array, array);
239 data.dptr = blob.data;
240 data.dsize = blob.length;
242 ret = tdb_store(msg_tdb, key, data, TDB_REPLACE);
243 TALLOC_FREE(mem_ctx);
245 return (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION;
248 /****************************************************************************
249 Notify a process that it has a message. If the process doesn't exist
250 then delete its record in the database.
251 ****************************************************************************/
253 static NTSTATUS message_notify(struct server_id procid)
255 pid_t pid = procid.pid;
257 uid_t euid = geteuid();
260 * Doing kill with a non-positive pid causes messages to be
261 * sent to places we don't want.
267 /* If we're not root become so to send the message. */
269 set_effective_uid(0);
272 ret = kill(pid, SIGUSR1);
275 /* Go back to who we were. */
276 int saved_errno = errno;
277 restore_re_uid_fromroot();
286 * Something has gone wrong
289 DEBUG(2,("message to process %d failed - %s\n", (int)pid,
293 * No call to map_nt_error_from_unix -- don't want to link in
294 * errormap.o into lots of utils.
297 if (errno == ESRCH) return NT_STATUS_INVALID_HANDLE;
298 if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER;
299 if (errno == EPERM) return NT_STATUS_ACCESS_DENIED;
300 return NT_STATUS_UNSUCCESSFUL;
303 /****************************************************************************
304 Send a message to a particular pid.
305 ****************************************************************************/
307 static NTSTATUS messaging_tdb_send(TDB_CONTEXT *msg_tdb,
308 struct server_id pid, int msg_type,
309 const void *buf, size_t len)
311 struct messaging_array *msg_array;
312 struct messaging_rec *rec;
315 TDB_DATA key = message_key_pid(pid);
317 /* NULL pointer means implicit length zero. */
319 SMB_ASSERT(len == 0);
323 * Doing kill with a non-positive pid causes messages to be
324 * sent to places we don't want.
327 SMB_ASSERT(procid_to_pid(&pid) > 0);
329 if (!(mem_ctx = talloc_init("message_send_pid"))) {
330 return NT_STATUS_NO_MEMORY;
333 if (tdb_chainlock(msg_tdb, key) == -1) {
334 return NT_STATUS_LOCK_NOT_GRANTED;
337 status = messaging_tdb_fetch(msg_tdb, key, mem_ctx, &msg_array);
339 if (!NT_STATUS_IS_OK(status)) {
340 tdb_chainunlock(msg_tdb, key);
341 TALLOC_FREE(mem_ctx);
345 if (!(rec = TALLOC_REALLOC_ARRAY(mem_ctx, msg_array->messages,
346 struct messaging_rec,
347 msg_array->num_messages+1))) {
348 tdb_chainunlock(msg_tdb, key);
349 TALLOC_FREE(mem_ctx);
350 return NT_STATUS_NO_MEMORY;
353 rec[msg_array->num_messages].msg_version = MESSAGE_VERSION;
354 rec[msg_array->num_messages].msg_type = msg_type;
355 rec[msg_array->num_messages].dest = pid;
356 rec[msg_array->num_messages].src = procid_self();
357 rec[msg_array->num_messages].buf = data_blob_const(buf, len);
359 msg_array->messages = rec;
360 msg_array->num_messages += 1;
362 status = messaging_tdb_store(msg_tdb, key, msg_array);
364 tdb_chainunlock(msg_tdb, key);
365 TALLOC_FREE(mem_ctx);
367 if (!NT_STATUS_IS_OK(status)) {
371 status = message_notify(pid);
373 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
374 DEBUG(2, ("pid %s doesn't exist - deleting messages record\n",
375 procid_str_static(&pid)));
376 tdb_delete(msg_tdb, message_key_pid(pid));
382 /****************************************************************************
383 Count the messages pending for a particular pid. Expensive....
384 ****************************************************************************/
386 unsigned int messages_pending_for_pid(struct messaging_context *msg_ctx,
387 struct server_id pid)
389 struct messaging_array *msg_array;
392 if (!NT_STATUS_IS_OK(messaging_tdb_fetch(msg_ctx->tdb,
393 message_key_pid(pid), NULL,
395 DEBUG(10, ("messaging_tdb_fetch failed\n"));
399 result = msg_array->num_messages;
400 TALLOC_FREE(msg_array);
404 /****************************************************************************
405 Retrieve all messages for the current process.
406 ****************************************************************************/
408 static NTSTATUS retrieve_all_messages(TDB_CONTEXT *msg_tdb,
410 struct messaging_array **presult)
412 struct messaging_array *result;
413 TDB_DATA key = message_key_pid(procid_self());
416 if (tdb_chainlock(msg_tdb, key) == -1) {
417 return NT_STATUS_LOCK_NOT_GRANTED;
420 status = messaging_tdb_fetch(msg_tdb, key, mem_ctx, &result);
423 * We delete the record here, tdb_set_max_dead keeps it around
425 tdb_delete(msg_tdb, key);
426 tdb_chainunlock(msg_tdb, key);
428 if (NT_STATUS_IS_OK(status)) {
436 Dispatch one messsaging_rec
438 static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
439 struct messaging_rec *rec)
441 struct messaging_callback *cb, *next;
443 for (cb = msg_ctx->callbacks; cb != NULL; cb = next) {
445 if (cb->msg_type == rec->msg_type) {
446 cb->fn(msg_ctx, cb->private_data, rec->msg_type,
447 rec->src, &rec->buf);
454 /****************************************************************************
455 Receive and dispatch any messages pending for this process.
456 JRA changed Dec 13 2006. Only one message handler now permitted per type.
457 *NOTE*: Dispatch functions must be able to cope with incoming
458 messages on an *odd* byte boundary.
459 ****************************************************************************/
461 void message_dispatch(struct messaging_context *msg_ctx)
463 struct messaging_array *msg_array = NULL;
466 if (!received_signal)
469 DEBUG(10, ("message_dispatch: received_signal = %d\n",
474 if (!NT_STATUS_IS_OK(retrieve_all_messages(msg_ctx->tdb, NULL,
479 for (i=0; i<msg_array->num_messages; i++) {
480 messaging_dispatch_rec(msg_ctx, &msg_array->messages[i]);
483 TALLOC_FREE(msg_array);
486 /****************************************************************************
487 Register/replace a dispatch function for a particular message type.
488 JRA changed Dec 13 2006. Only one message handler now permitted per type.
489 *NOTE*: Dispatch functions must be able to cope with incoming
490 messages on an *odd* byte boundary.
491 ****************************************************************************/
494 struct messaging_context *msg_ctx;
502 /****************************************************************************
503 Send one of the messages for the broadcast.
504 ****************************************************************************/
506 static int traverse_fn(TDB_CONTEXT *the_tdb,
507 const struct connections_key *ckey,
508 const struct connections_data *crec,
511 struct msg_all *msg_all = (struct msg_all *)private_data;
514 if (crec->cnum != -1)
517 /* Don't send if the receiver hasn't registered an interest. */
519 if(!(crec->bcast_msg_flags & msg_all->msg_flag))
522 /* If the msg send fails because the pid was not found (i.e. smbd died),
523 * the msg has already been deleted from the messages.tdb.*/
525 status = messaging_send_buf(msg_all->msg_ctx,
526 crec->pid, msg_all->msg_type,
527 (uint8 *)msg_all->buf, msg_all->len);
529 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
533 /* If the pid was not found delete the entry from
536 DEBUG(2,("pid %s doesn't exist - deleting connections "
537 "%d [%s]\n", procid_str_static(&crec->pid),
538 crec->cnum, crec->servicename));
540 key.dptr = (uint8 *)ckey;
541 key.dsize = sizeof(*ckey);
543 tdb_delete(the_tdb, key);
550 * Send a message to all smbd processes.
552 * It isn't very efficient, but should be OK for the sorts of
553 * applications that use it. When we need efficient broadcast we can add
556 * @param n_sent Set to the number of messages sent. This should be
557 * equal to the number of processes, but be careful for races.
559 * @retval True for success.
561 BOOL message_send_all(struct messaging_context *msg_ctx,
563 const void *buf, size_t len,
566 struct msg_all msg_all;
568 msg_all.msg_type = msg_type;
570 msg_all.msg_flag = FLAG_MSG_GENERAL;
571 else if (msg_type > 1000 && msg_type < 2000)
572 msg_all.msg_flag = FLAG_MSG_NMBD;
573 else if (msg_type > 2000 && msg_type < 2100)
574 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
575 else if (msg_type > 2100 && msg_type < 3000)
576 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
577 else if (msg_type > 3000 && msg_type < 4000)
578 msg_all.msg_flag = FLAG_MSG_SMBD;
585 msg_all.msg_ctx = msg_ctx;
587 connections_forall(traverse_fn, &msg_all);
589 *n_sent = msg_all.n_sent;
594 * Block and unblock receiving of messages. Allows removal of race conditions
595 * when doing a fork and changing message disposition.
598 void message_block(void)
600 BlockSignals(True, SIGUSR1);
603 void message_unblock(void)
605 BlockSignals(False, SIGUSR1);
608 struct event_context *messaging_event_context(struct messaging_context *msg_ctx)
610 return msg_ctx->event_ctx;
613 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
614 struct server_id server_id,
615 struct event_context *ev)
617 struct messaging_context *ctx;
619 if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
626 if (!message_init(ctx)) {
627 DEBUG(0, ("message_init failed: %s\n", strerror(errno)));
635 * Register a dispatch function for a particular message type. Allow multiple
638 NTSTATUS messaging_register(struct messaging_context *msg_ctx,
641 void (*fn)(struct messaging_context *msg,
644 struct server_id server_id,
647 struct messaging_callback *cb;
650 * Only one callback per type
653 for (cb = msg_ctx->callbacks; cb != NULL; cb = cb->next) {
654 if (cb->msg_type == msg_type) {
656 cb->private_data = private_data;
661 if (!(cb = talloc(msg_ctx, struct messaging_callback))) {
662 return NT_STATUS_NO_MEMORY;
665 cb->msg_type = msg_type;
667 cb->private_data = private_data;
669 DLIST_ADD(msg_ctx->callbacks, cb);
674 De-register the function for a particular message type.
676 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
679 struct messaging_callback *cb, *next;
681 for (cb = ctx->callbacks; cb; cb = next) {
683 if ((cb->msg_type == msg_type)
684 && (cb->private_data == private_data)) {
685 DLIST_REMOVE(ctx->callbacks, cb);
692 Send a message to a particular server
694 NTSTATUS messaging_send(struct messaging_context *msg_ctx,
695 struct server_id server,
696 uint32_t msg_type, const DATA_BLOB *data)
698 return messaging_tdb_send(msg_ctx->tdb, server, msg_type,
699 data->data, data->length);
702 NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
703 struct server_id server, uint32_t msg_type,
704 const uint8 *buf, size_t len)
706 DATA_BLOB blob = data_blob_const(buf, len);
707 return messaging_send(msg_ctx, server, msg_type, &blob);