[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / lib / messages.c
blob88b5f3ab93695638d08a33d8188fca5860a0591f
1 /*
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
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /**
24 @defgroup messages Internal messaging framework
26 @file messages.c
28 @brief Module for internal messaging between Samba daemons.
30 The idea is that if a part of Samba wants to do communication with
31 another Samba process then it will do a message_register() of a
32 dispatch function, and use message_send_pid() to send messages to
33 that process.
35 The dispatch function is given the pid of the sender, and it can
36 use that to reply by message_send_pid(). See ping_message() for a
37 simple example.
39 @caution Dispatch functions must be able to cope with incoming
40 messages on an *odd* byte boundary.
42 This system doesn't have any inherent size limitations but is not
43 very efficient for large messages or when messages are sent in very
44 quick succession.
48 #include "includes.h"
50 /* the locking database handle */
51 static TDB_CONTEXT *tdb;
52 static int received_signal;
54 /* change the message version with any incompatible changes in the protocol */
55 #define MESSAGE_VERSION 1
57 struct message_rec {
58 int msg_version;
59 int msg_type;
60 struct process_id dest;
61 struct process_id src;
62 size_t len;
65 /* we have a linked list of dispatch handlers */
66 static struct dispatch_fns {
67 struct dispatch_fns *next, *prev;
68 int msg_type;
69 void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len,
70 void *private_data);
71 void *private_data;
72 } *dispatch_fns;
74 /****************************************************************************
75 Free global objects.
76 ****************************************************************************/
78 void gfree_messages(void)
80 struct dispatch_fns *dfn, *next;
82 /* delete the dispatch_fns list */
83 dfn = dispatch_fns;
84 while( dfn ) {
85 next = dfn->next;
86 DLIST_REMOVE(dispatch_fns, dfn);
87 SAFE_FREE(dfn);
88 dfn = next;
92 /****************************************************************************
93 Notifications come in as signals.
94 ****************************************************************************/
96 static void sig_usr1(void)
98 received_signal = 1;
99 sys_select_signal(SIGUSR1);
102 /****************************************************************************
103 A useful function for testing the message system.
104 ****************************************************************************/
106 static void ping_message(int msg_type, struct process_id src,
107 void *buf, size_t len, void *private_data)
109 const char *msg = buf ? (const char *)buf : "none";
111 DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
112 procid_str_static(&src), msg));
113 message_send_pid(src, MSG_PONG, buf, len, True);
116 /****************************************************************************
117 Initialise the messaging functions.
118 ****************************************************************************/
120 BOOL message_init(void)
122 sec_init();
124 if (tdb)
125 return True;
127 tdb = tdb_open_log(lock_path("messages.tdb"),
128 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
129 O_RDWR|O_CREAT,0600);
131 if (!tdb) {
132 DEBUG(0,("ERROR: Failed to initialise messages database\n"));
133 return False;
136 /* Activate the per-hashchain freelist */
137 tdb_set_max_dead(tdb, 5);
139 CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
141 message_register(MSG_PING, ping_message, NULL);
143 /* Register some debugging related messages */
145 register_msg_pool_usage();
146 register_dmalloc_msgs();
148 return True;
151 /*******************************************************************
152 Form a static tdb key from a pid.
153 ******************************************************************/
155 static TDB_DATA message_key_pid(struct process_id pid)
157 static char key[20];
158 TDB_DATA kbuf;
160 slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid));
162 kbuf.dptr = (char *)key;
163 kbuf.dsize = strlen(key)+1;
164 return kbuf;
167 /****************************************************************************
168 Notify a process that it has a message. If the process doesn't exist
169 then delete its record in the database.
170 ****************************************************************************/
172 static NTSTATUS message_notify(struct process_id procid)
174 pid_t pid = procid.pid;
175 int ret;
176 uid_t euid = geteuid();
179 * Doing kill with a non-positive pid causes messages to be
180 * sent to places we don't want.
183 SMB_ASSERT(pid > 0);
185 if (euid != 0) {
186 /* If we're not root become so to send the message. */
187 save_re_uid();
188 set_effective_uid(0);
191 ret = kill(pid, SIGUSR1);
193 if (euid != 0) {
194 /* Go back to who we were. */
195 int saved_errno = errno;
196 restore_re_uid_fromroot();
197 errno = saved_errno;
200 if (ret == -1) {
201 if (errno == ESRCH) {
202 DEBUG(2,("pid %d doesn't exist - deleting messages record\n",
203 (int)pid));
204 tdb_delete(tdb, message_key_pid(procid));
207 * INVALID_HANDLE is the closest I can think of -- vl
209 return NT_STATUS_INVALID_HANDLE;
212 DEBUG(2,("message to process %d failed - %s\n", (int)pid,
213 strerror(errno)));
216 * No call to map_nt_error_from_unix -- don't want to link in
217 * errormap.o into lots of utils.
220 if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER;
221 if (errno == EPERM) return NT_STATUS_ACCESS_DENIED;
222 return NT_STATUS_UNSUCCESSFUL;
225 return NT_STATUS_OK;
228 /****************************************************************************
229 Send a message to a particular pid.
230 ****************************************************************************/
232 static NTSTATUS message_send_pid_internal(struct process_id pid, int msg_type,
233 const void *buf, size_t len,
234 BOOL duplicates_allowed,
235 unsigned int timeout)
237 TDB_DATA kbuf;
238 TDB_DATA dbuf;
239 TDB_DATA old_dbuf;
240 struct message_rec rec;
241 char *ptr;
242 struct message_rec prec;
244 /* NULL pointer means implicit length zero. */
245 if (!buf) {
246 SMB_ASSERT(len == 0);
250 * Doing kill with a non-positive pid causes messages to be
251 * sent to places we don't want.
254 SMB_ASSERT(procid_to_pid(&pid) > 0);
256 rec.msg_version = MESSAGE_VERSION;
257 rec.msg_type = msg_type;
258 rec.dest = pid;
259 rec.src = procid_self();
260 rec.len = buf ? len : 0;
262 kbuf = message_key_pid(pid);
264 dbuf.dptr = (char *)SMB_MALLOC(len + sizeof(rec));
265 if (!dbuf.dptr) {
266 return NT_STATUS_NO_MEMORY;
269 memcpy(dbuf.dptr, &rec, sizeof(rec));
270 if (len > 0 && buf)
271 memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);
273 dbuf.dsize = len + sizeof(rec);
275 if (duplicates_allowed) {
277 /* If duplicates are allowed we can just append the message and return. */
279 /* lock the record for the destination */
280 if (timeout) {
281 if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
282 DEBUG(0,("message_send_pid_internal: failed to get "
283 "chainlock with timeout %ul.\n", timeout));
284 SAFE_FREE(dbuf.dptr);
285 return NT_STATUS_IO_TIMEOUT;
287 } else {
288 if (tdb_chainlock(tdb, kbuf) == -1) {
289 DEBUG(0,("message_send_pid_internal: failed to get "
290 "chainlock.\n"));
291 SAFE_FREE(dbuf.dptr);
292 return NT_STATUS_LOCK_NOT_GRANTED;
295 tdb_append(tdb, kbuf, dbuf);
296 tdb_chainunlock(tdb, kbuf);
298 SAFE_FREE(dbuf.dptr);
299 errno = 0; /* paranoia */
300 return message_notify(pid);
303 /* lock the record for the destination */
304 if (timeout) {
305 if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
306 DEBUG(0,("message_send_pid_internal: failed to get chainlock "
307 "with timeout %ul.\n", timeout));
308 SAFE_FREE(dbuf.dptr);
309 return NT_STATUS_IO_TIMEOUT;
311 } else {
312 if (tdb_chainlock(tdb, kbuf) == -1) {
313 DEBUG(0,("message_send_pid_internal: failed to get "
314 "chainlock.\n"));
315 SAFE_FREE(dbuf.dptr);
316 return NT_STATUS_LOCK_NOT_GRANTED;
320 old_dbuf = tdb_fetch(tdb, kbuf);
322 if (!old_dbuf.dptr) {
323 /* its a new record */
325 tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
326 tdb_chainunlock(tdb, kbuf);
328 SAFE_FREE(dbuf.dptr);
329 errno = 0; /* paranoia */
330 return message_notify(pid);
333 /* Not a new record. Check for duplicates. */
335 for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) {
337 * First check if the message header matches, then, if it's a non-zero
338 * sized message, check if the data matches. If so it's a duplicate and
339 * we can discard it. JRA.
342 if (!memcmp(ptr, &rec, sizeof(rec))) {
343 if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
344 tdb_chainunlock(tdb, kbuf);
345 DEBUG(10,("message_send_pid_internal: discarding "
346 "duplicate message.\n"));
347 SAFE_FREE(dbuf.dptr);
348 SAFE_FREE(old_dbuf.dptr);
349 return NT_STATUS_OK;
352 memcpy(&prec, ptr, sizeof(prec));
353 ptr += sizeof(rec) + prec.len;
356 /* we're adding to an existing entry */
358 tdb_append(tdb, kbuf, dbuf);
359 tdb_chainunlock(tdb, kbuf);
361 SAFE_FREE(old_dbuf.dptr);
362 SAFE_FREE(dbuf.dptr);
364 errno = 0; /* paranoia */
365 return message_notify(pid);
368 /****************************************************************************
369 Send a message to a particular pid - no timeout.
370 ****************************************************************************/
372 NTSTATUS message_send_pid(struct process_id pid, int msg_type, const void *buf,
373 size_t len, BOOL duplicates_allowed)
375 return message_send_pid_internal(pid, msg_type, buf, len,
376 duplicates_allowed, 0);
379 /****************************************************************************
380 Send a message to a particular pid, with timeout in seconds.
381 ****************************************************************************/
383 NTSTATUS message_send_pid_with_timeout(struct process_id pid, int msg_type,
384 const void *buf, size_t len,
385 BOOL duplicates_allowed, unsigned int timeout)
387 return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed,
388 timeout);
391 /****************************************************************************
392 Count the messages pending for a particular pid. Expensive....
393 ****************************************************************************/
395 unsigned int messages_pending_for_pid(struct process_id pid)
397 TDB_DATA kbuf;
398 TDB_DATA dbuf;
399 char *buf;
400 unsigned int message_count = 0;
402 kbuf = message_key_pid(pid);
404 dbuf = tdb_fetch(tdb, kbuf);
405 if (dbuf.dptr == NULL || dbuf.dsize == 0) {
406 SAFE_FREE(dbuf.dptr);
407 return 0;
410 for (buf = dbuf.dptr; dbuf.dsize > sizeof(struct message_rec);) {
411 struct message_rec rec;
412 memcpy(&rec, buf, sizeof(rec));
413 buf += (sizeof(rec) + rec.len);
414 dbuf.dsize -= (sizeof(rec) + rec.len);
415 message_count++;
418 SAFE_FREE(dbuf.dptr);
419 return message_count;
422 /****************************************************************************
423 Retrieve all messages for the current process.
424 ****************************************************************************/
426 static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
428 TDB_DATA kbuf;
429 TDB_DATA dbuf;
430 TDB_DATA null_dbuf;
432 ZERO_STRUCT(null_dbuf);
434 *msgs_buf = NULL;
435 *total_len = 0;
437 kbuf = message_key_pid(pid_to_procid(sys_getpid()));
439 if (tdb_chainlock(tdb, kbuf) == -1)
440 return False;
442 dbuf = tdb_fetch(tdb, kbuf);
444 * Replace with an empty record to keep the allocated
445 * space in the tdb.
447 tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE);
448 tdb_chainunlock(tdb, kbuf);
450 if (dbuf.dptr == NULL || dbuf.dsize == 0) {
451 SAFE_FREE(dbuf.dptr);
452 return False;
455 *msgs_buf = dbuf.dptr;
456 *total_len = dbuf.dsize;
458 return True;
461 /****************************************************************************
462 Parse out the next message for the current process.
463 ****************************************************************************/
465 static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type,
466 struct process_id *src, char **buf, size_t *len)
468 struct message_rec rec;
469 char *ret_buf = *buf;
471 *buf = NULL;
472 *len = 0;
474 if (total_len - (ret_buf - msgs_buf) < sizeof(rec))
475 return False;
477 memcpy(&rec, ret_buf, sizeof(rec));
478 ret_buf += sizeof(rec);
480 if (rec.msg_version != MESSAGE_VERSION) {
481 DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION));
482 return False;
485 if (rec.len > 0) {
486 if (total_len - (ret_buf - msgs_buf) < rec.len)
487 return False;
490 *len = rec.len;
491 *msg_type = rec.msg_type;
492 *src = rec.src;
493 *buf = ret_buf;
495 return True;
498 /****************************************************************************
499 Receive and dispatch any messages pending for this process.
500 JRA changed Dec 13 2006. Only one message handler now permitted per type.
501 *NOTE*: Dispatch functions must be able to cope with incoming
502 messages on an *odd* byte boundary.
503 ****************************************************************************/
505 void message_dispatch(void)
507 int msg_type;
508 struct process_id src;
509 char *buf;
510 char *msgs_buf;
511 size_t len, total_len;
512 int n_handled;
514 if (!received_signal)
515 return;
517 DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal));
519 received_signal = 0;
521 if (!retrieve_all_messages(&msgs_buf, &total_len))
522 return;
524 for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) {
525 struct dispatch_fns *dfn;
527 DEBUG(10,("message_dispatch: received msg_type=%d "
528 "src_pid=%u\n", msg_type,
529 (unsigned int) procid_to_pid(&src)));
531 n_handled = 0;
532 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
533 if (dfn->msg_type == msg_type) {
534 DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type));
535 dfn->fn(msg_type, src,
536 len ? (void *)buf : NULL, len,
537 dfn->private_data);
538 n_handled++;
539 break;
542 if (!n_handled) {
543 DEBUG(5,("message_dispatch: warning: no handler registed for "
544 "msg_type %d in pid %u\n",
545 msg_type, (unsigned int)sys_getpid()));
548 SAFE_FREE(msgs_buf);
551 /****************************************************************************
552 Register/replace a dispatch function for a particular message type.
553 JRA changed Dec 13 2006. Only one message handler now permitted per type.
554 *NOTE*: Dispatch functions must be able to cope with incoming
555 messages on an *odd* byte boundary.
556 ****************************************************************************/
558 void message_register(int msg_type,
559 void (*fn)(int msg_type, struct process_id pid,
560 void *buf, size_t len,
561 void *private_data),
562 void *private_data)
564 struct dispatch_fns *dfn;
566 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
567 if (dfn->msg_type == msg_type) {
568 dfn->fn = fn;
569 return;
573 dfn = SMB_MALLOC_P(struct dispatch_fns);
575 if (dfn != NULL) {
577 ZERO_STRUCTPN(dfn);
579 dfn->msg_type = msg_type;
580 dfn->fn = fn;
581 dfn->private_data = private_data;
583 DLIST_ADD(dispatch_fns, dfn);
585 else {
587 DEBUG(0,("message_register: Not enough memory. malloc failed!\n"));
591 /****************************************************************************
592 De-register the function for a particular message type.
593 ****************************************************************************/
595 void message_deregister(int msg_type)
597 struct dispatch_fns *dfn, *next;
599 for (dfn = dispatch_fns; dfn; dfn = next) {
600 next = dfn->next;
601 if (dfn->msg_type == msg_type) {
602 DLIST_REMOVE(dispatch_fns, dfn);
603 SAFE_FREE(dfn);
604 return;
609 struct msg_all {
610 int msg_type;
611 uint32 msg_flag;
612 const void *buf;
613 size_t len;
614 BOOL duplicates;
615 int n_sent;
618 /****************************************************************************
619 Send one of the messages for the broadcast.
620 ****************************************************************************/
622 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
624 struct connections_data crec;
625 struct msg_all *msg_all = (struct msg_all *)state;
626 NTSTATUS status;
628 if (dbuf.dsize != sizeof(crec))
629 return 0;
631 memcpy(&crec, dbuf.dptr, sizeof(crec));
633 if (crec.cnum != -1)
634 return 0;
636 /* Don't send if the receiver hasn't registered an interest. */
638 if(!(crec.bcast_msg_flags & msg_all->msg_flag))
639 return 0;
641 /* If the msg send fails because the pid was not found (i.e. smbd died),
642 * the msg has already been deleted from the messages.tdb.*/
644 status = message_send_pid(crec.pid, msg_all->msg_type,
645 msg_all->buf, msg_all->len,
646 msg_all->duplicates);
648 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
650 /* If the pid was not found delete the entry from connections.tdb */
652 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
653 procid_str_static(&crec.pid), crec.cnum, crec.servicename));
654 tdb_delete(the_tdb, kbuf);
656 msg_all->n_sent++;
657 return 0;
661 * Send a message to all smbd processes.
663 * It isn't very efficient, but should be OK for the sorts of
664 * applications that use it. When we need efficient broadcast we can add
665 * it.
667 * @param n_sent Set to the number of messages sent. This should be
668 * equal to the number of processes, but be careful for races.
670 * @retval True for success.
672 BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
673 const void *buf, size_t len,
674 BOOL duplicates_allowed,
675 int *n_sent)
677 struct msg_all msg_all;
679 msg_all.msg_type = msg_type;
680 if (msg_type < 1000)
681 msg_all.msg_flag = FLAG_MSG_GENERAL;
682 else if (msg_type > 1000 && msg_type < 2000)
683 msg_all.msg_flag = FLAG_MSG_NMBD;
684 else if (msg_type > 2000 && msg_type < 2100)
685 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
686 else if (msg_type > 2100 && msg_type < 3000)
687 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
688 else if (msg_type > 3000 && msg_type < 4000)
689 msg_all.msg_flag = FLAG_MSG_SMBD;
690 else
691 return False;
693 msg_all.buf = buf;
694 msg_all.len = len;
695 msg_all.duplicates = duplicates_allowed;
696 msg_all.n_sent = 0;
698 tdb_traverse(conn_tdb, traverse_fn, &msg_all);
699 if (n_sent)
700 *n_sent = msg_all.n_sent;
701 return True;
705 * Block and unblock receiving of messages. Allows removal of race conditions
706 * when doing a fork and changing message disposition.
709 void message_block(void)
711 BlockSignals(True, SIGUSR1);
714 void message_unblock(void)
716 BlockSignals(False, SIGUSR1);
720 * Samba4 API wrapper around the Samba3 implementation. Yes, I know, we could
721 * import the whole Samba4 thing, but I want notify.c from Samba4 in first.
724 struct messaging_callback {
725 struct messaging_callback *prev, *next;
726 uint32 msg_type;
727 void (*fn)(struct messaging_context *msg, void *private_data,
728 uint32_t msg_type,
729 struct server_id server_id, DATA_BLOB *data);
730 void *private_data;
733 struct messaging_context {
734 struct server_id id;
735 struct messaging_callback *callbacks;
738 static int messaging_context_destructor(struct messaging_context *ctx)
740 struct messaging_callback *cb;
742 for (cb = ctx->callbacks; cb; cb = cb->next) {
744 * We unconditionally remove all instances of our callback
745 * from the tdb basis.
747 message_deregister(cb->msg_type);
749 return 0;
752 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
753 struct server_id server_id,
754 struct event_context *ev)
756 struct messaging_context *ctx;
758 if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
759 return NULL;
762 ctx->id = server_id;
763 talloc_set_destructor(ctx, messaging_context_destructor);
764 return ctx;
767 static void messaging_callback(int msg_type, struct process_id pid,
768 void *buf, size_t len, void *private_data)
770 struct messaging_context *ctx = talloc_get_type_abort(
771 private_data, struct messaging_context);
772 struct messaging_callback *cb, *next;
774 for (cb = ctx->callbacks; cb; cb = next) {
776 * Allow a callback to remove itself
778 next = cb->next;
780 if (msg_type == cb->msg_type) {
781 DATA_BLOB blob;
782 struct server_id id;
784 blob.data = (uint8 *)buf;
785 blob.length = len;
786 id.id = pid;
788 cb->fn(ctx, cb->private_data, msg_type, id, &blob);
794 * Register a dispatch function for a particular message type. Allow multiple
795 * registrants
797 NTSTATUS messaging_register(struct messaging_context *ctx, void *private_data,
798 uint32_t msg_type,
799 void (*fn)(struct messaging_context *msg,
800 void *private_data,
801 uint32_t msg_type,
802 struct server_id server_id,
803 DATA_BLOB *data))
805 struct messaging_callback *cb;
807 if (!(cb = talloc(ctx, struct messaging_callback))) {
808 return NT_STATUS_NO_MEMORY;
811 cb->msg_type = msg_type;
812 cb->fn = fn;
813 cb->private_data = private_data;
815 DLIST_ADD(ctx->callbacks, cb);
816 message_register(msg_type, messaging_callback, ctx);
817 return NT_STATUS_OK;
821 De-register the function for a particular message type.
823 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
824 void *private_data)
826 struct messaging_callback *cb, *next;
828 for (cb = ctx->callbacks; cb; cb = next) {
829 next = cb->next;
830 if ((cb->msg_type == msg_type)
831 && (cb->private_data == private_data)) {
832 DLIST_REMOVE(ctx->callbacks, cb);
833 TALLOC_FREE(cb);
839 Send a message to a particular server
841 NTSTATUS messaging_send(struct messaging_context *msg,
842 struct server_id server,
843 uint32_t msg_type, DATA_BLOB *data)
845 return message_send_pid_internal(server.id, msg_type, data->data,
846 data->length, True, 0);
849 /** @} **/