source: branches/samba-3.0/source/lib/messages.c@ 160

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

Update source to 3.0.25c level

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