s3: Fix a long-standing problem with recycled PIDs
[ira/wip.git] / source3 / lib / messages.c
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    Copyright (C) 2007 by Volker Lendecke
8    
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.
13    
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.
18    
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/>.
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 #include "librpc/gen_ndr/messaging.h"
50 #include "librpc/gen_ndr/ndr_messaging.h"
51
52 struct messaging_callback {
53         struct messaging_callback *prev, *next;
54         uint32 msg_type;
55         void (*fn)(struct messaging_context *msg, void *private_data, 
56                    uint32_t msg_type, 
57                    struct server_id server_id, DATA_BLOB *data);
58         void *private_data;
59 };
60
61 /****************************************************************************
62  A useful function for testing the message system.
63 ****************************************************************************/
64
65 static void ping_message(struct messaging_context *msg_ctx,
66                          void *private_data,
67                          uint32_t msg_type,
68                          struct server_id src,
69                          DATA_BLOB *data)
70 {
71         const char *msg = data->data ? (const char *)data->data : "none";
72
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);
76 }
77
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 ****************************************************************************/
84
85 struct msg_all {
86         struct messaging_context *msg_ctx;
87         int msg_type;
88         uint32 msg_flag;
89         const void *buf;
90         size_t len;
91         int n_sent;
92 };
93
94 /****************************************************************************
95  Send one of the messages for the broadcast.
96 ****************************************************************************/
97
98 static int traverse_fn(struct db_record *rec, const struct server_id *id,
99                        uint32_t msg_flags, void *state)
100 {
101         struct msg_all *msg_all = (struct msg_all *)state;
102         NTSTATUS status;
103
104         /* Don't send if the receiver hasn't registered an interest. */
105
106         if((msg_flags & msg_all->msg_flag) == 0) {
107                 return 0;
108         }
109
110         /* If the msg send fails because the pid was not found (i.e. smbd died), 
111          * the msg has already been deleted from the messages.tdb.*/
112
113         status = messaging_send_buf(msg_all->msg_ctx, *id, msg_all->msg_type,
114                                     (uint8 *)msg_all->buf, msg_all->len);
115
116         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
117                 
118                 /* If the pid was not found delete the entry from connections.tdb */
119
120                 DEBUG(2, ("pid %s doesn't exist\n", procid_str_static(id)));
121
122                 rec->delete_rec(rec);
123         }
124         msg_all->n_sent++;
125         return 0;
126 }
127
128 /**
129  * Send a message to all smbd processes.
130  *
131  * It isn't very efficient, but should be OK for the sorts of
132  * applications that use it. When we need efficient broadcast we can add
133  * it.
134  *
135  * @param n_sent Set to the number of messages sent.  This should be
136  * equal to the number of processes, but be careful for races.
137  *
138  * @retval True for success.
139  **/
140 bool message_send_all(struct messaging_context *msg_ctx,
141                       int msg_type,
142                       const void *buf, size_t len,
143                       int *n_sent)
144 {
145         struct msg_all msg_all;
146
147         msg_all.msg_type = msg_type;
148         if (msg_type < 1000)
149                 msg_all.msg_flag = FLAG_MSG_GENERAL;
150         else if (msg_type > 1000 && msg_type < 2000)
151                 msg_all.msg_flag = FLAG_MSG_NMBD;
152         else if (msg_type > 2000 && msg_type < 2100)
153                 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
154         else if (msg_type > 2100 && msg_type < 3000)
155                 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
156         else if (msg_type > 3000 && msg_type < 4000)
157                 msg_all.msg_flag = FLAG_MSG_SMBD;
158         else if (msg_type > 4000 && msg_type < 5000)
159                 msg_all.msg_flag = FLAG_MSG_DBWRAP;
160         else
161                 return False;
162
163         msg_all.buf = buf;
164         msg_all.len = len;
165         msg_all.n_sent = 0;
166         msg_all.msg_ctx = msg_ctx;
167
168         serverid_traverse(traverse_fn, &msg_all);
169         if (n_sent)
170                 *n_sent = msg_all.n_sent;
171         return True;
172 }
173
174 struct event_context *messaging_event_context(struct messaging_context *msg_ctx)
175 {
176         return msg_ctx->event_ctx;
177 }
178
179 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, 
180                                          struct server_id server_id, 
181                                          struct event_context *ev)
182 {
183         struct messaging_context *ctx;
184         NTSTATUS status;
185
186         if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
187                 return NULL;
188         }
189
190         ctx->id = server_id;
191         ctx->event_ctx = ev;
192
193         status = messaging_tdb_init(ctx, ctx, &ctx->local);
194
195         if (!NT_STATUS_IS_OK(status)) {
196                 DEBUG(0, ("messaging_tdb_init failed: %s\n",
197                           nt_errstr(status)));
198                 TALLOC_FREE(ctx);
199                 return NULL;
200         }
201
202 #ifdef CLUSTER_SUPPORT
203         if (lp_clustering()) {
204                 status = messaging_ctdbd_init(ctx, ctx, &ctx->remote);
205
206                 if (!NT_STATUS_IS_OK(status)) {
207                         DEBUG(1, ("messaging_ctdb_init failed: %s\n",
208                                   nt_errstr(status)));
209                         TALLOC_FREE(ctx);
210                         return NULL;
211                 }
212         }
213 #endif
214
215         messaging_register(ctx, NULL, MSG_PING, ping_message);
216
217         /* Register some debugging related messages */
218
219         register_msg_pool_usage(ctx);
220         register_dmalloc_msgs(ctx);
221         debug_register_msgs(ctx);
222
223         return ctx;
224 }
225
226 /*
227  * re-init after a fork
228  */
229 NTSTATUS messaging_reinit(struct messaging_context *msg_ctx)
230 {
231         NTSTATUS status;
232
233         TALLOC_FREE(msg_ctx->local);
234
235         status = messaging_tdb_init(msg_ctx, msg_ctx, &msg_ctx->local);
236         if (!NT_STATUS_IS_OK(status)) {
237                 DEBUG(0, ("messaging_tdb_init failed: %s\n",
238                           nt_errstr(status)));
239                 return status;
240         }
241
242 #ifdef CLUSTER_SUPPORT
243         TALLOC_FREE(msg_ctx->remote);
244
245         if (lp_clustering()) {
246                 status = messaging_ctdbd_init(msg_ctx, msg_ctx,
247                                               &msg_ctx->remote);
248
249                 if (!NT_STATUS_IS_OK(status)) {
250                         DEBUG(1, ("messaging_ctdb_init failed: %s\n",
251                                   nt_errstr(status)));
252                         return status;
253                 }
254         }
255
256 #endif
257
258         return NT_STATUS_OK;
259 }
260
261
262 /*
263  * Register a dispatch function for a particular message type. Allow multiple
264  * registrants
265 */
266 NTSTATUS messaging_register(struct messaging_context *msg_ctx,
267                             void *private_data,
268                             uint32_t msg_type,
269                             void (*fn)(struct messaging_context *msg,
270                                        void *private_data, 
271                                        uint32_t msg_type, 
272                                        struct server_id server_id,
273                                        DATA_BLOB *data))
274 {
275         struct messaging_callback *cb;
276
277         /*
278          * Only one callback per type
279          */
280
281         for (cb = msg_ctx->callbacks; cb != NULL; cb = cb->next) {
282                 /* we allow a second registration of the same message
283                    type if it has a different private pointer. This is
284                    needed in, for example, the internal notify code,
285                    which creates a new notify context for each tree
286                    connect, and expects to receive messages to each of
287                    them. */
288                 if (cb->msg_type == msg_type && private_data == cb->private_data) {
289                         DEBUG(5,("Overriding messaging pointer for type %u - private_data=%p\n",
290                                   (unsigned)msg_type, private_data));
291                         cb->fn = fn;
292                         cb->private_data = private_data;
293                         return NT_STATUS_OK;
294                 }
295         }
296
297         if (!(cb = talloc(msg_ctx, struct messaging_callback))) {
298                 return NT_STATUS_NO_MEMORY;
299         }
300
301         cb->msg_type = msg_type;
302         cb->fn = fn;
303         cb->private_data = private_data;
304
305         DLIST_ADD(msg_ctx->callbacks, cb);
306         return NT_STATUS_OK;
307 }
308
309 /*
310   De-register the function for a particular message type.
311 */
312 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
313                           void *private_data)
314 {
315         struct messaging_callback *cb, *next;
316
317         for (cb = ctx->callbacks; cb; cb = next) {
318                 next = cb->next;
319                 if ((cb->msg_type == msg_type)
320                     && (cb->private_data == private_data)) {
321                         DEBUG(5,("Deregistering messaging pointer for type %u - private_data=%p\n",
322                                   (unsigned)msg_type, private_data));
323                         DLIST_REMOVE(ctx->callbacks, cb);
324                         TALLOC_FREE(cb);
325                 }
326         }
327 }
328
329 /*
330   Send a message to a particular server
331 */
332 NTSTATUS messaging_send(struct messaging_context *msg_ctx,
333                         struct server_id server, uint32_t msg_type,
334                         const DATA_BLOB *data)
335 {
336 #ifdef CLUSTER_SUPPORT
337         if (!procid_is_local(&server)) {
338                 return msg_ctx->remote->send_fn(msg_ctx, server,
339                                                 msg_type, data,
340                                                 msg_ctx->remote);
341         }
342 #endif
343         return msg_ctx->local->send_fn(msg_ctx, server, msg_type, data,
344                                        msg_ctx->local);
345 }
346
347 NTSTATUS messaging_send_buf(struct messaging_context *msg_ctx,
348                             struct server_id server, uint32_t msg_type,
349                             const uint8 *buf, size_t len)
350 {
351         DATA_BLOB blob = data_blob_const(buf, len);
352         return messaging_send(msg_ctx, server, msg_type, &blob);
353 }
354
355 /*
356   Dispatch one messsaging_rec
357 */
358 void messaging_dispatch_rec(struct messaging_context *msg_ctx,
359                             struct messaging_rec *rec)
360 {
361         struct messaging_callback *cb, *next;
362
363         for (cb = msg_ctx->callbacks; cb != NULL; cb = next) {
364                 next = cb->next;
365                 if (cb->msg_type == rec->msg_type) {
366                         cb->fn(msg_ctx, cb->private_data, rec->msg_type,
367                                rec->src, &rec->buf);
368                         /* we continue looking for matching messages
369                            after finding one. This matters for
370                            subsystems like the internal notify code
371                            which register more than one handler for
372                            the same message type */
373                 }
374         }
375         return;
376 }
377
378 /** @} **/