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 3 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, see <http://www.gnu.org/licenses/>.
24 @defgroup messages Internal messaging framework
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
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
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
49 #include "librpc/gen_ndr/messaging.h"
50 #include "librpc/gen_ndr/ndr_messaging.h"
52 struct messaging_callback
{
53 struct messaging_callback
*prev
, *next
;
55 void (*fn
)(struct messaging_context
*msg
, void *private_data
,
57 struct server_id server_id
, DATA_BLOB
*data
);
61 /****************************************************************************
62 A useful function for testing the message system.
63 ****************************************************************************/
65 static void ping_message(struct messaging_context
*msg_ctx
,
71 const char *msg
= data
->data
? (const char *)data
->data
: "none";
73 DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
74 procid_str_static(&src
), msg
));
75 messaging_send(msg_ctx
, src
, MSG_PONG
, data
);
78 /****************************************************************************
79 Register/replace a dispatch function for a particular message type.
80 JRA changed Dec 13 2006. Only one message handler now permitted per type.
81 *NOTE*: Dispatch functions must be able to cope with incoming
82 messages on an *odd* byte boundary.
83 ****************************************************************************/
86 struct messaging_context
*msg_ctx
;
94 /****************************************************************************
95 Send one of the messages for the broadcast.
96 ****************************************************************************/
98 static int traverse_fn(struct db_record
*rec
,
99 const struct connections_key
*ckey
,
100 const struct connections_data
*crec
,
103 struct msg_all
*msg_all
= (struct msg_all
*)state
;
106 if (crec
->cnum
!= -1)
109 /* Don't send if the receiver hasn't registered an interest. */
111 if(!(crec
->bcast_msg_flags
& msg_all
->msg_flag
))
114 /* If the msg send fails because the pid was not found (i.e. smbd died),
115 * the msg has already been deleted from the messages.tdb.*/
117 status
= messaging_send_buf(msg_all
->msg_ctx
,
118 crec
->pid
, msg_all
->msg_type
,
119 (uint8
*)msg_all
->buf
, msg_all
->len
);
121 if (NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_HANDLE
)) {
123 /* If the pid was not found delete the entry from connections.tdb */
125 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
126 procid_str_static(&crec
->pid
), crec
->cnum
,
129 rec
->delete_rec(rec
);
136 * Send a message to all smbd processes.
138 * It isn't very efficient, but should be OK for the sorts of
139 * applications that use it. When we need efficient broadcast we can add
142 * @param n_sent Set to the number of messages sent. This should be
143 * equal to the number of processes, but be careful for races.
145 * @retval True for success.
147 bool message_send_all(struct messaging_context
*msg_ctx
,
149 const void *buf
, size_t len
,
152 struct msg_all msg_all
;
154 msg_all
.msg_type
= msg_type
;
156 msg_all
.msg_flag
= FLAG_MSG_GENERAL
;
157 else if (msg_type
> 1000 && msg_type
< 2000)
158 msg_all
.msg_flag
= FLAG_MSG_NMBD
;
159 else if (msg_type
> 2000 && msg_type
< 2100)
160 msg_all
.msg_flag
= FLAG_MSG_PRINT_NOTIFY
;
161 else if (msg_type
> 2100 && msg_type
< 3000)
162 msg_all
.msg_flag
= FLAG_MSG_PRINT_GENERAL
;
163 else if (msg_type
> 3000 && msg_type
< 4000)
164 msg_all
.msg_flag
= FLAG_MSG_SMBD
;
165 else if (msg_type
> 4000 && msg_type
< 5000)
166 msg_all
.msg_flag
= FLAG_MSG_DBWRAP
;
173 msg_all
.msg_ctx
= msg_ctx
;
175 connections_forall(traverse_fn
, &msg_all
);
177 *n_sent
= msg_all
.n_sent
;
181 struct event_context
*messaging_event_context(struct messaging_context
*msg_ctx
)
183 return msg_ctx
->event_ctx
;
186 struct messaging_context
*messaging_init(TALLOC_CTX
*mem_ctx
,
187 struct server_id server_id
,
188 struct event_context
*ev
)
190 struct messaging_context
*ctx
;
193 if (!(ctx
= TALLOC_ZERO_P(mem_ctx
, struct messaging_context
))) {
200 status
= messaging_tdb_init(ctx
, ctx
, &ctx
->local
);
202 if (!NT_STATUS_IS_OK(status
)) {
203 DEBUG(0, ("messaging_tdb_init failed: %s\n",
209 #ifdef CLUSTER_SUPPORT
210 if (lp_clustering()) {
211 status
= messaging_ctdbd_init(ctx
, ctx
, &ctx
->remote
);
213 if (!NT_STATUS_IS_OK(status
)) {
214 DEBUG(0, ("messaging_ctdb_init failed: %s\n",
222 messaging_register(ctx
, NULL
, MSG_PING
, ping_message
);
224 /* Register some debugging related messages */
226 register_msg_pool_usage(ctx
);
227 register_dmalloc_msgs(ctx
);
228 debug_register_msgs(ctx
);
234 * re-init after a fork
236 NTSTATUS
messaging_reinit(struct messaging_context
*msg_ctx
)
238 #ifdef CLUSTER_SUPPORT
240 TALLOC_FREE(msg_ctx
->remote
);
242 if (lp_clustering()) {
245 status
= messaging_ctdbd_init(msg_ctx
, msg_ctx
,
248 if (!NT_STATUS_IS_OK(status
)) {
249 DEBUG(0, ("messaging_ctdb_init failed: %s\n",
262 * Register a dispatch function for a particular message type. Allow multiple
265 NTSTATUS
messaging_register(struct messaging_context
*msg_ctx
,
268 void (*fn
)(struct messaging_context
*msg
,
271 struct server_id server_id
,
274 struct messaging_callback
*cb
;
277 * Only one callback per type
280 for (cb
= msg_ctx
->callbacks
; cb
!= NULL
; cb
= cb
->next
) {
281 if (cb
->msg_type
== msg_type
) {
283 cb
->private_data
= private_data
;
288 if (!(cb
= talloc(msg_ctx
, struct messaging_callback
))) {
289 return NT_STATUS_NO_MEMORY
;
292 cb
->msg_type
= msg_type
;
294 cb
->private_data
= private_data
;
296 DLIST_ADD(msg_ctx
->callbacks
, cb
);
301 De-register the function for a particular message type.
303 void messaging_deregister(struct messaging_context
*ctx
, uint32_t msg_type
,
306 struct messaging_callback
*cb
, *next
;
308 for (cb
= ctx
->callbacks
; cb
; cb
= next
) {
310 if ((cb
->msg_type
== msg_type
)
311 && (cb
->private_data
== private_data
)) {
312 DLIST_REMOVE(ctx
->callbacks
, cb
);
319 Send a message to a particular server
321 NTSTATUS
messaging_send(struct messaging_context
*msg_ctx
,
322 struct server_id server
, uint32_t msg_type
,
323 const DATA_BLOB
*data
)
325 #ifdef CLUSTER_SUPPORT
326 if (!procid_is_local(&server
)) {
327 return msg_ctx
->remote
->send_fn(msg_ctx
, server
,
332 return msg_ctx
->local
->send_fn(msg_ctx
, server
, msg_type
, data
,
336 NTSTATUS
messaging_send_buf(struct messaging_context
*msg_ctx
,
337 struct server_id server
, uint32_t msg_type
,
338 const uint8
*buf
, size_t len
)
340 DATA_BLOB blob
= data_blob_const(buf
, len
);
341 return messaging_send(msg_ctx
, server
, msg_type
, &blob
);
345 Dispatch one messsaging_rec
347 void messaging_dispatch_rec(struct messaging_context
*msg_ctx
,
348 struct messaging_rec
*rec
)
350 struct messaging_callback
*cb
, *next
;
352 for (cb
= msg_ctx
->callbacks
; cb
!= NULL
; cb
= next
) {
354 if (cb
->msg_type
== rec
->msg_type
) {
355 cb
->fn(msg_ctx
, cb
->private_data
, rec
->msg_type
,
356 rec
->src
, &rec
->buf
);