2 Unix SMB/Netbios implementation.
4 Samba internal messaging functions
5 Copyright (C) Andrew Tridgell 2000
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This module is used for internal messaging between Samba daemons.
27 The idea is that if a part of Samba wants to do communication with
28 another Samba process then it will do a message_register() of a
29 dispatch function, and use message_send_pid() to send messages to
32 The dispatch function is given the pid of the sender, and it can
33 use that to reply by message_send_pid(). See ping_message() for a
36 This system doesn't have any inherent size limitations but is not
37 very efficient for large messages or when messages are sent in very
44 /* the locking database handle */
45 static TDB_CONTEXT *tdb;
46 static int received_signal;
48 /* change the message version with any incompatible changes in the protocol */
49 #define MESSAGE_VERSION 1
59 /* we have a linked list of dispatch handlers */
60 static struct dispatch_fns {
61 struct dispatch_fns *next, *prev;
63 void (*fn)(int msg_type, pid_t pid, void *buf, size_t len);
66 /****************************************************************************
67 Notifications come in as signals.
68 ****************************************************************************/
70 static void sig_usr1(void)
76 /****************************************************************************
77 A useful function for testing the message system.
78 ****************************************************************************/
80 void ping_message(int msg_type, pid_t src, void *buf, size_t len)
82 char *msg = buf ? buf : "none";
83 DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(unsigned int)src, msg));
84 message_send_pid(src, MSG_PONG, buf, len, True);
87 /****************************************************************************
88 Return current debug level.
89 ****************************************************************************/
91 void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len)
93 DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n",(unsigned int)src));
94 message_send_pid(src, MSG_DEBUGLEVEL, DEBUGLEVEL_CLASS, sizeof(DEBUGLEVEL_CLASS), True);
97 /****************************************************************************
98 Initialise the messaging functions.
99 ****************************************************************************/
101 BOOL message_init(void)
103 if (tdb) return True;
105 tdb = tdb_open_log(lock_path("messages.tdb"),
106 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
107 O_RDWR|O_CREAT,0600);
110 DEBUG(0,("ERROR: Failed to initialise messages database\n"));
114 CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
116 message_register(MSG_PING, ping_message);
117 message_register(MSG_REQ_DEBUGLEVEL, debuglevel_message);
122 /*******************************************************************
123 Form a static tdb key from a pid.
124 ******************************************************************/
126 static TDB_DATA message_key_pid(pid_t pid)
131 slprintf(key, sizeof(key)-1, "PID/%d", (int)pid);
133 kbuf.dptr = (char *)key;
134 kbuf.dsize = strlen(key)+1;
138 /****************************************************************************
139 Notify a process that it has a message. If the process doesn't exist
140 then delete its record in the database.
141 ****************************************************************************/
143 static BOOL message_notify(pid_t pid)
145 if (kill(pid, SIGUSR1) == -1) {
146 if (errno == ESRCH) {
147 DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid));
148 tdb_delete(tdb, message_key_pid(pid));
150 DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno)));
157 /****************************************************************************
158 Send a message to a particular pid.
159 ****************************************************************************/
161 BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len, BOOL duplicates_allowed)
165 struct message_rec rec;
168 rec.msg_version = MESSAGE_VERSION;
169 rec.msg_type = msg_type;
171 rec.src = sys_getpid();
174 kbuf = message_key_pid(pid);
176 /* lock the record for the destination */
177 tdb_chainlock(tdb, kbuf);
179 dbuf = tdb_fetch(tdb, kbuf);
182 /* its a new record */
183 p = (void *)malloc(len + sizeof(rec));
186 memcpy(p, &rec, sizeof(rec));
187 if (len > 0) memcpy((void *)((char*)p+sizeof(rec)), buf, len);
190 dbuf.dsize = len + sizeof(rec);
191 tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
196 if (!duplicates_allowed) {
198 struct message_rec prec;
200 for(ptr = (char *)dbuf.dptr; ptr < dbuf.dptr + dbuf.dsize; ) {
202 * First check if the message header matches, then, if it's a non-zero
203 * sized message, check if the data matches. If so it's a duplicate and
204 * we can discard it. JRA.
207 if (!memcmp(ptr, &rec, sizeof(rec))) {
208 if (!len || (len && !memcmp( ptr + sizeof(rec), (char *)buf, len))) {
209 DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
210 SAFE_FREE(dbuf.dptr);
211 tdb_chainunlock(tdb, kbuf);
215 memcpy(&prec, ptr, sizeof(prec));
216 ptr += sizeof(rec) + prec.len;
220 /* we're adding to an existing entry */
221 p = (void *)malloc(dbuf.dsize + len + sizeof(rec));
224 memcpy(p, dbuf.dptr, dbuf.dsize);
225 memcpy((void *)((char*)p+dbuf.dsize), &rec, sizeof(rec));
226 if (len > 0) memcpy((void *)((char*)p+dbuf.dsize+sizeof(rec)), buf, len);
228 SAFE_FREE(dbuf.dptr);
230 dbuf.dsize += len + sizeof(rec);
231 tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
232 SAFE_FREE(dbuf.dptr);
235 tdb_chainunlock(tdb, kbuf);
236 errno = 0; /* paranoia */
237 return message_notify(pid);
240 tdb_chainunlock(tdb, kbuf);
241 errno = 0; /* paranoia */
245 /****************************************************************************
246 Retrieve the next message for the current process.
247 ****************************************************************************/
249 static BOOL message_recv(int *msg_type, pid_t *src, void **buf, size_t *len)
253 struct message_rec rec;
255 kbuf = message_key_pid(sys_getpid());
257 tdb_chainlock(tdb, kbuf);
259 dbuf = tdb_fetch(tdb, kbuf);
260 if (dbuf.dptr == NULL || dbuf.dsize == 0) goto failed;
262 memcpy(&rec, dbuf.dptr, sizeof(rec));
264 if (rec.msg_version != MESSAGE_VERSION) {
265 DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION));
270 (*buf) = (void *)malloc(rec.len);
271 if (!(*buf)) goto failed;
273 memcpy(*buf, dbuf.dptr+sizeof(rec), rec.len);
279 *msg_type = rec.msg_type;
282 if (dbuf.dsize - (sizeof(rec)+rec.len) > 0)
283 memmove(dbuf.dptr, dbuf.dptr+sizeof(rec)+rec.len, dbuf.dsize - (sizeof(rec)+rec.len));
284 dbuf.dsize -= sizeof(rec)+rec.len;
287 tdb_delete(tdb, kbuf);
289 tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
291 SAFE_FREE(dbuf.dptr);
292 tdb_chainunlock(tdb, kbuf);
296 tdb_chainunlock(tdb, kbuf);
300 /****************************************************************************
301 Receive and dispatch any messages pending for this process.
302 Notice that all dispatch handlers for a particular msg_type get called,
303 so you can register multiple handlers for a message.
304 ****************************************************************************/
306 void message_dispatch(void)
312 struct dispatch_fns *dfn;
314 if (!received_signal) return;
316 DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal));
320 while (message_recv(&msg_type, &src, &buf, &len)) {
321 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
322 if (dfn->msg_type == msg_type) {
323 DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type));
324 dfn->fn(msg_type, src, buf, len);
331 /****************************************************************************
332 Register a dispatch function for a particular message type.
333 ****************************************************************************/
335 void message_register(int msg_type,
336 void (*fn)(int msg_type, pid_t pid, void *buf, size_t len))
338 struct dispatch_fns *dfn;
340 dfn = (struct dispatch_fns *)malloc(sizeof(*dfn));
346 dfn->msg_type = msg_type;
349 DLIST_ADD(dispatch_fns, dfn);
353 DEBUG(0,("message_register: Not enough memory. malloc failed!\n"));
357 /****************************************************************************
358 De-register the function for a particular message type.
359 ****************************************************************************/
361 void message_deregister(int msg_type)
363 struct dispatch_fns *dfn, *next;
365 for (dfn = dispatch_fns; dfn; dfn = next) {
367 if (dfn->msg_type == msg_type) {
368 DLIST_REMOVE(dispatch_fns, dfn);
381 /****************************************************************************
382 Send one of the messages for the broadcast.
383 ****************************************************************************/
385 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
387 struct connections_data crec;
388 struct msg_all *msg_all = (struct msg_all *)state;
390 if (dbuf.dsize != sizeof(crec))
393 memcpy(&crec, dbuf.dptr, sizeof(crec));
398 /* if the msg send fails because the pid was not found (i.e. smbd died),
399 * the msg has already been deleted from the messages.tdb.*/
400 if (!message_send_pid(crec.pid, msg_all->msg_type, msg_all->buf, msg_all->len,
401 msg_all->duplicates)) {
403 /* if the pid was not found delete the entry from connections.tdb */
404 if (errno == ESRCH) {
405 DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n",
406 (unsigned int)crec.pid, crec.cnum, crec.name));
407 tdb_delete(the_tdb, kbuf);
413 /****************************************************************************
414 This is a useful function for sending messages to all smbd processes.
415 It isn't very efficient, but should be OK for the sorts of applications that
416 use it. When we need efficient broadcast we can add it.
417 ****************************************************************************/
419 BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type, void *buf, size_t len, BOOL duplicates_allowed)
421 struct msg_all msg_all;
423 msg_all.msg_type = msg_type;
426 msg_all.duplicates = duplicates_allowed;
428 tdb_traverse(conn_tdb, traverse_fn, &msg_all);