source: trunk/samba-3.0.25pre1/source/lib/messages.c@ 1

Last change on this file since 1 was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 21.3 KB
Line 
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
7
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.
12
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.
17
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.
21*/
22
23/**
24 @defgroup messages Internal messaging framework
25 @{
26 @file messages.c
27
28 @brief Module for internal messaging between Samba daemons.
29
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.
34
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.
38
39 @caution Dispatch functions must be able to cope with incoming
40 messages on an *odd* byte boundary.
41
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.
45
46*/
47
48#include "includes.h"
49
50/* the locking database handle */
51static TDB_CONTEXT *tdb;
52static int received_signal;
53
54/* change the message version with any incompatible changes in the protocol */
55#define MESSAGE_VERSION 1
56
57struct message_rec {
58 int msg_version;
59 int msg_type;
60 struct process_id dest;
61 struct process_id src;
62 size_t len;
63};
64
65/* we have a linked list of dispatch handlers */
66static 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;
73
74/****************************************************************************
75 Free global objects.
76****************************************************************************/
77
78void gfree_messages(void)
79{
80 struct dispatch_fns *dfn, *next;
81
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;
89 }
90}
91
92/****************************************************************************
93 Notifications come in as signals.
94****************************************************************************/
95
96static void sig_usr1(void)
97{
98 received_signal = 1;
99 sys_select_signal(SIGUSR1);
100}
101
102/****************************************************************************
103 A useful function for testing the message system.
104****************************************************************************/
105
106static void ping_message(int msg_type, struct process_id src,
107 void *buf, size_t len, void *private_data)
108{
109 const char *msg = buf ? (const char *)buf : "none";
110
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);
114}
115
116/****************************************************************************
117 Initialise the messaging functions.
118****************************************************************************/
119
120BOOL message_init(void)
121{
122 sec_init();
123
124 if (tdb)
125 return True;
126
127 tdb = tdb_open_log(lock_path("messages.tdb"),
128 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
129 O_RDWR|O_CREAT,0600);
130 if (!tdb) {
131 DEBUG(0,("ERROR: Failed to initialise messages database\n"));
132 return False;
133 }
134
135 CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
136
137 message_register(MSG_PING, ping_message, NULL);
138
139 /* Register some debugging related messages */
140
141 register_msg_pool_usage();
142 register_dmalloc_msgs();
143
144 return True;
145}
146
147/*******************************************************************
148 Form a static tdb key from a pid.
149******************************************************************/
150
151static TDB_DATA message_key_pid(struct process_id pid)
152{
153 static char key[20];
154 TDB_DATA kbuf;
155
156 slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid));
157
158 kbuf.dptr = (char *)key;
159 kbuf.dsize = strlen(key)+1;
160 return kbuf;
161}
162
163/****************************************************************************
164 Notify a process that it has a message. If the process doesn't exist
165 then delete its record in the database.
166****************************************************************************/
167
168static NTSTATUS message_notify(struct process_id procid)
169{
170 pid_t pid = procid.pid;
171 int ret;
172 uid_t euid = geteuid();
173
174 /*
175 * Doing kill with a non-positive pid causes messages to be
176 * sent to places we don't want.
177 */
178
179 SMB_ASSERT(pid > 0);
180
181 if (euid != 0) {
182 become_root_uid_only();
183 }
184
185 ret = kill(pid, SIGUSR1);
186
187 if (euid != 0) {
188 unbecome_root_uid_only();
189 }
190
191 if (ret == -1) {
192 if (errno == ESRCH) {
193 DEBUG(2,("pid %d doesn't exist - deleting messages record\n",
194 (int)pid));
195 tdb_delete(tdb, message_key_pid(procid));
196
197 /*
198 * INVALID_HANDLE is the closest I can think of -- vl
199 */
200 return NT_STATUS_INVALID_HANDLE;
201 }
202
203 DEBUG(2,("message to process %d failed - %s\n", (int)pid,
204 strerror(errno)));
205
206 /*
207 * No call to map_nt_error_from_unix -- don't want to link in
208 * errormap.o into lots of utils.
209 */
210
211 if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER;
212 if (errno == EPERM) return NT_STATUS_ACCESS_DENIED;
213 return NT_STATUS_UNSUCCESSFUL;
214 }
215
216 return NT_STATUS_OK;
217}
218
219/****************************************************************************
220 Send a message to a particular pid.
221****************************************************************************/
222
223static NTSTATUS message_send_pid_internal(struct process_id pid, int msg_type,
224 const void *buf, size_t len,
225 BOOL duplicates_allowed,
226 unsigned int timeout)
227{
228 TDB_DATA kbuf;
229 TDB_DATA dbuf;
230 TDB_DATA old_dbuf;
231 struct message_rec rec;
232 char *ptr;
233 struct message_rec prec;
234
235 /* NULL pointer means implicit length zero. */
236 if (!buf) {
237 SMB_ASSERT(len == 0);
238 }
239
240 /*
241 * Doing kill with a non-positive pid causes messages to be
242 * sent to places we don't want.
243 */
244
245 SMB_ASSERT(procid_to_pid(&pid) > 0);
246
247 rec.msg_version = MESSAGE_VERSION;
248 rec.msg_type = msg_type;
249 rec.dest = pid;
250 rec.src = procid_self();
251 rec.len = buf ? len : 0;
252
253 kbuf = message_key_pid(pid);
254
255 dbuf.dptr = (char *)SMB_MALLOC(len + sizeof(rec));
256 if (!dbuf.dptr) {
257 return NT_STATUS_NO_MEMORY;
258 }
259
260 memcpy(dbuf.dptr, &rec, sizeof(rec));
261 if (len > 0 && buf)
262 memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);
263
264 dbuf.dsize = len + sizeof(rec);
265
266 if (duplicates_allowed) {
267
268 /* If duplicates are allowed we can just append the message and return. */
269
270 /* lock the record for the destination */
271 if (timeout) {
272 if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
273 DEBUG(0,("message_send_pid_internal: failed to get "
274 "chainlock with timeout %ul.\n", timeout));
275 return NT_STATUS_IO_TIMEOUT;
276 }
277 } else {
278 if (tdb_chainlock(tdb, kbuf) == -1) {
279 DEBUG(0,("message_send_pid_internal: failed to get "
280 "chainlock.\n"));
281 return NT_STATUS_LOCK_NOT_GRANTED;
282 }
283 }
284 tdb_append(tdb, kbuf, dbuf);
285 tdb_chainunlock(tdb, kbuf);
286
287 SAFE_FREE(dbuf.dptr);
288 errno = 0; /* paranoia */
289 return message_notify(pid);
290 }
291
292 /* lock the record for the destination */
293 if (timeout) {
294 if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
295 DEBUG(0,("message_send_pid_internal: failed to get chainlock "
296 "with timeout %ul.\n", timeout));
297 return NT_STATUS_IO_TIMEOUT;
298 }
299 } else {
300 if (tdb_chainlock(tdb, kbuf) == -1) {
301 DEBUG(0,("message_send_pid_internal: failed to get "
302 "chainlock.\n"));
303 return NT_STATUS_LOCK_NOT_GRANTED;
304 }
305 }
306
307 old_dbuf = tdb_fetch(tdb, kbuf);
308
309 if (!old_dbuf.dptr) {
310 /* its a new record */
311
312 tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
313 tdb_chainunlock(tdb, kbuf);
314
315 SAFE_FREE(dbuf.dptr);
316 errno = 0; /* paranoia */
317 return message_notify(pid);
318 }
319
320 /* Not a new record. Check for duplicates. */
321
322 for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) {
323 /*
324 * First check if the message header matches, then, if it's a non-zero
325 * sized message, check if the data matches. If so it's a duplicate and
326 * we can discard it. JRA.
327 */
328
329 if (!memcmp(ptr, &rec, sizeof(rec))) {
330 if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
331 tdb_chainunlock(tdb, kbuf);
332 DEBUG(10,("message_send_pid_internal: discarding "
333 "duplicate message.\n"));
334 SAFE_FREE(dbuf.dptr);
335 SAFE_FREE(old_dbuf.dptr);
336 return NT_STATUS_OK;
337 }
338 }
339 memcpy(&prec, ptr, sizeof(prec));
340 ptr += sizeof(rec) + prec.len;
341 }
342
343 /* we're adding to an existing entry */
344
345 tdb_append(tdb, kbuf, dbuf);
346 tdb_chainunlock(tdb, kbuf);
347
348 SAFE_FREE(old_dbuf.dptr);
349 SAFE_FREE(dbuf.dptr);
350
351 errno = 0; /* paranoia */
352 return message_notify(pid);
353}
354
355/****************************************************************************
356 Send a message to a particular pid - no timeout.
357****************************************************************************/
358
359NTSTATUS message_send_pid(struct process_id pid, int msg_type, const void *buf,
360 size_t len, BOOL duplicates_allowed)
361{
362 return message_send_pid_internal(pid, msg_type, buf, len,
363 duplicates_allowed, 0);
364}
365
366/****************************************************************************
367 Send a message to a particular pid, with timeout in seconds.
368****************************************************************************/
369
370NTSTATUS message_send_pid_with_timeout(struct process_id pid, int msg_type,
371 const void *buf, size_t len,
372 BOOL duplicates_allowed, unsigned int timeout)
373{
374 return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed,
375 timeout);
376}
377
378/****************************************************************************
379 Count the messages pending for a particular pid. Expensive....
380****************************************************************************/
381
382unsigned int messages_pending_for_pid(struct process_id pid)
383{
384 TDB_DATA kbuf;
385 TDB_DATA dbuf;
386 char *buf;
387 unsigned int message_count = 0;
388
389 kbuf = message_key_pid(pid);
390
391 dbuf = tdb_fetch(tdb, kbuf);
392 if (dbuf.dptr == NULL || dbuf.dsize == 0) {
393 SAFE_FREE(dbuf.dptr);
394 return 0;
395 }
396
397 for (buf = dbuf.dptr; dbuf.dsize > sizeof(struct message_rec);) {
398 struct message_rec rec;
399 memcpy(&rec, buf, sizeof(rec));
400 buf += (sizeof(rec) + rec.len);
401 dbuf.dsize -= (sizeof(rec) + rec.len);
402 message_count++;
403 }
404
405 SAFE_FREE(dbuf.dptr);
406 return message_count;
407}
408
409/****************************************************************************
410 Retrieve all messages for the current process.
411****************************************************************************/
412
413static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
414{
415 TDB_DATA kbuf;
416 TDB_DATA dbuf;
417 TDB_DATA null_dbuf;
418
419 ZERO_STRUCT(null_dbuf);
420
421 *msgs_buf = NULL;
422 *total_len = 0;
423
424 kbuf = message_key_pid(pid_to_procid(sys_getpid()));
425
426 if (tdb_chainlock(tdb, kbuf) == -1)
427 return False;
428
429 dbuf = tdb_fetch(tdb, kbuf);
430 /*
431 * Replace with an empty record to keep the allocated
432 * space in the tdb.
433 */
434 tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE);
435 tdb_chainunlock(tdb, kbuf);
436
437 if (dbuf.dptr == NULL || dbuf.dsize == 0) {
438 SAFE_FREE(dbuf.dptr);
439 return False;
440 }
441
442 *msgs_buf = dbuf.dptr;
443 *total_len = dbuf.dsize;
444
445 return True;
446}
447
448/****************************************************************************
449 Parse out the next message for the current process.
450****************************************************************************/
451
452static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type,
453 struct process_id *src, char **buf, size_t *len)
454{
455 struct message_rec rec;
456 char *ret_buf = *buf;
457
458 *buf = NULL;
459 *len = 0;
460
461 if (total_len - (ret_buf - msgs_buf) < sizeof(rec))
462 return False;
463
464 memcpy(&rec, ret_buf, sizeof(rec));
465 ret_buf += sizeof(rec);
466
467 if (rec.msg_version != MESSAGE_VERSION) {
468 DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION));
469 return False;
470 }
471
472 if (rec.len > 0) {
473 if (total_len - (ret_buf - msgs_buf) < rec.len)
474 return False;
475 }
476
477 *len = rec.len;
478 *msg_type = rec.msg_type;
479 *src = rec.src;
480 *buf = ret_buf;
481
482 return True;
483}
484
485/****************************************************************************
486 Receive and dispatch any messages pending for this process.
487 JRA changed Dec 13 2006. Only one message handler now permitted per type.
488 *NOTE*: Dispatch functions must be able to cope with incoming
489 messages on an *odd* byte boundary.
490****************************************************************************/
491
492void message_dispatch(void)
493{
494 int msg_type;
495 struct process_id src;
496 char *buf;
497 char *msgs_buf;
498 size_t len, total_len;
499 int n_handled;
500
501 if (!received_signal)
502 return;
503
504 DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal));
505
506 received_signal = 0;
507
508 if (!retrieve_all_messages(&msgs_buf, &total_len))
509 return;
510
511 for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) {
512 struct dispatch_fns *dfn;
513
514 DEBUG(10,("message_dispatch: received msg_type=%d "
515 "src_pid=%u\n", msg_type,
516 (unsigned int) procid_to_pid(&src)));
517
518 n_handled = 0;
519 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
520 if (dfn->msg_type == msg_type) {
521 DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type));
522 dfn->fn(msg_type, src,
523 len ? (void *)buf : NULL, len,
524 dfn->private_data);
525 n_handled++;
526 break;
527 }
528 }
529 if (!n_handled) {
530 DEBUG(5,("message_dispatch: warning: no handler registed for "
531 "msg_type %d in pid %u\n",
532 msg_type, (unsigned int)sys_getpid()));
533 }
534 }
535 SAFE_FREE(msgs_buf);
536}
537
538/****************************************************************************
539 Register/replace a dispatch function for a particular message type.
540 JRA changed Dec 13 2006. Only one message handler now permitted per type.
541 *NOTE*: Dispatch functions must be able to cope with incoming
542 messages on an *odd* byte boundary.
543****************************************************************************/
544
545void message_register(int msg_type,
546 void (*fn)(int msg_type, struct process_id pid,
547 void *buf, size_t len,
548 void *private_data),
549 void *private_data)
550{
551 struct dispatch_fns *dfn;
552
553 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
554 if (dfn->msg_type == msg_type) {
555 dfn->fn = fn;
556 return;
557 }
558 }
559
560 dfn = SMB_MALLOC_P(struct dispatch_fns);
561
562 if (dfn != NULL) {
563
564 ZERO_STRUCTPN(dfn);
565
566 dfn->msg_type = msg_type;
567 dfn->fn = fn;
568 dfn->private_data = private_data;
569
570 DLIST_ADD(dispatch_fns, dfn);
571 }
572 else {
573
574 DEBUG(0,("message_register: Not enough memory. malloc failed!\n"));
575 }
576}
577
578/****************************************************************************
579 De-register the function for a particular message type.
580****************************************************************************/
581
582void message_deregister(int msg_type)
583{
584 struct dispatch_fns *dfn, *next;
585
586 for (dfn = dispatch_fns; dfn; dfn = next) {
587 next = dfn->next;
588 if (dfn->msg_type == msg_type) {
589 DLIST_REMOVE(dispatch_fns, dfn);
590 SAFE_FREE(dfn);
591 return;
592 }
593 }
594}
595
596struct msg_all {
597 int msg_type;
598 uint32 msg_flag;
599 const void *buf;
600 size_t len;
601 BOOL duplicates;
602 int n_sent;
603};
604
605/****************************************************************************
606 Send one of the messages for the broadcast.
607****************************************************************************/
608
609static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
610{
611 struct connections_data crec;
612 struct msg_all *msg_all = (struct msg_all *)state;
613 NTSTATUS status;
614
615 if (dbuf.dsize != sizeof(crec))
616 return 0;
617
618 memcpy(&crec, dbuf.dptr, sizeof(crec));
619
620 if (crec.cnum != -1)
621 return 0;
622
623 /* Don't send if the receiver hasn't registered an interest. */
624
625 if(!(crec.bcast_msg_flags & msg_all->msg_flag))
626 return 0;
627
628 /* If the msg send fails because the pid was not found (i.e. smbd died),
629 * the msg has already been deleted from the messages.tdb.*/
630
631 status = message_send_pid(crec.pid, msg_all->msg_type,
632 msg_all->buf, msg_all->len,
633 msg_all->duplicates);
634
635 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
636
637 /* If the pid was not found delete the entry from connections.tdb */
638
639 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
640 procid_str_static(&crec.pid), crec.cnum, crec.name));
641 tdb_delete(the_tdb, kbuf);
642 }
643 msg_all->n_sent++;
644 return 0;
645}
646
647/**
648 * Send a message to all smbd processes.
649 *
650 * It isn't very efficient, but should be OK for the sorts of
651 * applications that use it. When we need efficient broadcast we can add
652 * it.
653 *
654 * @param n_sent Set to the number of messages sent. This should be
655 * equal to the number of processes, but be careful for races.
656 *
657 * @retval True for success.
658 **/
659BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
660 const void *buf, size_t len,
661 BOOL duplicates_allowed,
662 int *n_sent)
663{
664 struct msg_all msg_all;
665
666 msg_all.msg_type = msg_type;
667 if (msg_type < 1000)
668 msg_all.msg_flag = FLAG_MSG_GENERAL;
669 else if (msg_type > 1000 && msg_type < 2000)
670 msg_all.msg_flag = FLAG_MSG_NMBD;
671 else if (msg_type > 2000 && msg_type < 2100)
672 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
673 else if (msg_type > 2100 && msg_type < 3000)
674 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
675 else if (msg_type > 3000 && msg_type < 4000)
676 msg_all.msg_flag = FLAG_MSG_SMBD;
677 else
678 return False;
679
680 msg_all.buf = buf;
681 msg_all.len = len;
682 msg_all.duplicates = duplicates_allowed;
683 msg_all.n_sent = 0;
684
685 tdb_traverse(conn_tdb, traverse_fn, &msg_all);
686 if (n_sent)
687 *n_sent = msg_all.n_sent;
688 return True;
689}
690
691/*
692 * Block and unblock receiving of messages. Allows removal of race conditions
693 * when doing a fork and changing message disposition.
694 */
695
696void message_block(void)
697{
698 BlockSignals(True, SIGUSR1);
699}
700
701void message_unblock(void)
702{
703 BlockSignals(False, SIGUSR1);
704}
705
706/*
707 * Samba4 API wrapper around the Samba3 implementation. Yes, I know, we could
708 * import the whole Samba4 thing, but I want notify.c from Samba4 in first.
709 */
710
711struct messaging_callback {
712 struct messaging_callback *prev, *next;
713 uint32 msg_type;
714 void (*fn)(struct messaging_context *msg, void *private_data,
715 uint32_t msg_type,
716 struct server_id server_id, DATA_BLOB *data);
717 void *private_data;
718};
719
720struct messaging_context {
721 struct server_id id;
722 struct messaging_callback *callbacks;
723};
724
725static int messaging_context_destructor(struct messaging_context *ctx)
726{
727 struct messaging_callback *cb;
728
729 for (cb = ctx->callbacks; cb; cb = cb->next) {
730 /*
731 * We unconditionally remove all instances of our callback
732 * from the tdb basis.
733 */
734 message_deregister(cb->msg_type);
735 }
736 return 0;
737}
738
739struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
740 struct server_id server_id,
741 struct event_context *ev)
742{
743 struct messaging_context *ctx;
744
745 if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
746 return NULL;
747 }
748
749 ctx->id = server_id;
750 talloc_set_destructor(ctx, messaging_context_destructor);
751 return ctx;
752}
753
754static void messaging_callback(int msg_type, struct process_id pid,
755 void *buf, size_t len, void *private_data)
756{
757 struct messaging_context *ctx = talloc_get_type_abort(
758 private_data, struct messaging_context);
759 struct messaging_callback *cb, *next;
760
761 for (cb = ctx->callbacks; cb; cb = next) {
762 /*
763 * Allow a callback to remove itself
764 */
765 next = cb->next;
766
767 if (msg_type == cb->msg_type) {
768 DATA_BLOB blob;
769 struct server_id id;
770
771 blob.data = (uint8 *)buf;
772 blob.length = len;
773 id.id = pid;
774
775 cb->fn(ctx, cb->private_data, msg_type, id, &blob);
776 }
777 }
778}
779
780/*
781 * Register a dispatch function for a particular message type. Allow multiple
782 * registrants
783*/
784NTSTATUS messaging_register(struct messaging_context *ctx, void *private_data,
785 uint32_t msg_type,
786 void (*fn)(struct messaging_context *msg,
787 void *private_data,
788 uint32_t msg_type,
789 struct server_id server_id,
790 DATA_BLOB *data))
791{
792 struct messaging_callback *cb;
793
794 if (!(cb = talloc(ctx, struct messaging_callback))) {
795 return NT_STATUS_NO_MEMORY;
796 }
797
798 cb->msg_type = msg_type;
799 cb->fn = fn;
800 cb->private_data = private_data;
801
802 DLIST_ADD(ctx->callbacks, cb);
803 message_register(msg_type, messaging_callback, ctx);
804 return NT_STATUS_OK;
805}
806
807/*
808 De-register the function for a particular message type.
809*/
810void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
811 void *private_data)
812{
813 struct messaging_callback *cb, *next;
814
815 for (cb = ctx->callbacks; cb; cb = next) {
816 next = cb->next;
817 if ((cb->msg_type == msg_type)
818 && (cb->private_data == private_data)) {
819 DLIST_REMOVE(ctx->callbacks, cb);
820 TALLOC_FREE(cb);
821 }
822 }
823}
824
825/*
826 Send a message to a particular server
827*/
828NTSTATUS messaging_send(struct messaging_context *msg,
829 struct server_id server,
830 uint32_t msg_type, DATA_BLOB *data)
831{
832 return message_send_pid_internal(server.id, msg_type, data->data,
833 data->length, True, 0);
834}
835
836/** @} **/
Note: See TracBrowser for help on using the repository browser.