s4:samba_kcc: Use 'dburl' passed from command line rather than lp.samdb_url()
[Samba.git] / source3 / lib / messages_local.c
blobd535df1be27d70552ba8365a3fc9de70f0e41a23
1 /*
2 Unix SMB/CIFS implementation.
3 Samba internal messaging functions
4 Copyright (C) 2007 by Volker Lendecke
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 /**
21 @defgroup messages Internal messaging framework
23 @file messages.c
25 @brief Module 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
30 that process.
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
34 simple example.
36 @caution Dispatch functions must be able to cope with incoming
37 messages on an *odd* byte boundary.
39 This system doesn't have any inherent size limitations but is not
40 very efficient for large messages or when messages are sent in very
41 quick succession.
45 #include "includes.h"
46 #include "system/filesys.h"
47 #include "messages.h"
48 #include "serverid.h"
49 #include "lib/tdb_wrap/tdb_wrap.h"
50 #include "lib/param/param.h"
52 struct messaging_tdb_context {
53 struct messaging_context *msg_ctx;
54 struct tdb_wrap *tdb;
55 struct tevent_signal *se;
56 int received_messages;
57 bool *have_context;
60 static NTSTATUS messaging_tdb_send(struct messaging_context *msg_ctx,
61 struct server_id pid, int msg_type,
62 const DATA_BLOB *data,
63 struct messaging_backend *backend);
64 static void message_dispatch(struct messaging_context *msg_ctx);
66 static void messaging_tdb_signal_handler(struct tevent_context *ev_ctx,
67 struct tevent_signal *se,
68 int signum, int count,
69 void *_info, void *private_data)
71 struct messaging_tdb_context *ctx = talloc_get_type(private_data,
72 struct messaging_tdb_context);
74 ctx->received_messages++;
76 DEBUG(10, ("messaging_tdb_signal_handler: sig[%d] count[%d] msgs[%d]\n",
77 signum, count, ctx->received_messages));
79 message_dispatch(ctx->msg_ctx);
82 static int messaging_tdb_context_destructor(struct messaging_tdb_context *ctx);
84 /****************************************************************************
85 Initialise the messaging functions.
86 ****************************************************************************/
88 NTSTATUS messaging_tdb_init(struct messaging_context *msg_ctx,
89 TALLOC_CTX *mem_ctx,
90 struct messaging_backend **presult)
92 struct messaging_backend *result;
93 struct messaging_tdb_context *ctx;
94 struct loadparm_context *lp_ctx;
95 static bool have_context = false;
96 const char *fname;
98 if (have_context) {
99 DEBUG(0, ("No two messaging contexts per process\n"));
100 return NT_STATUS_OBJECT_NAME_COLLISION;
103 if (!(result = talloc(mem_ctx, struct messaging_backend))) {
104 DEBUG(0, ("talloc failed\n"));
105 return NT_STATUS_NO_MEMORY;
108 lp_ctx = loadparm_init_s3(result, loadparm_s3_helpers());
109 if (lp_ctx == NULL) {
110 DEBUG(0, ("loadparm_init_s3 failed\n"));
111 TALLOC_FREE(result);
112 return NT_STATUS_INTERNAL_ERROR;
115 ctx = talloc_zero(result, struct messaging_tdb_context);
116 if (!ctx) {
117 DEBUG(0, ("talloc failed\n"));
118 TALLOC_FREE(result);
119 return NT_STATUS_NO_MEMORY;
121 result->private_data = ctx;
122 result->send_fn = messaging_tdb_send;
124 ctx->msg_ctx = msg_ctx;
125 ctx->have_context = &have_context;
127 fname = lock_path("messages.tdb");
129 ctx->tdb = tdb_wrap_open(
130 ctx, fname, lpcfg_tdb_hash_size(lp_ctx, fname),
131 lpcfg_tdb_flags(lp_ctx, TDB_CLEAR_IF_FIRST|TDB_DEFAULT|
132 TDB_VOLATILE| TDB_INCOMPATIBLE_HASH),
133 O_RDWR|O_CREAT,0600);
135 talloc_unlink(result, lp_ctx);
137 if (!ctx->tdb) {
138 NTSTATUS status = map_nt_error_from_unix(errno);
139 DEBUG(2, ("ERROR: Failed to initialise messages database: "
140 "%s\n", strerror(errno)));
141 TALLOC_FREE(result);
142 return status;
145 ctx->se = tevent_add_signal(msg_ctx->event_ctx,
146 ctx,
147 SIGUSR1, 0,
148 messaging_tdb_signal_handler,
149 ctx);
150 if (!ctx->se) {
151 NTSTATUS status = map_nt_error_from_unix(errno);
152 DEBUG(0, ("ERROR: Failed to initialise messages signal handler: "
153 "%s\n", strerror(errno)));
154 TALLOC_FREE(result);
155 return status;
158 sec_init();
160 have_context = true;
161 talloc_set_destructor(ctx, messaging_tdb_context_destructor);
163 *presult = result;
164 return NT_STATUS_OK;
167 static int messaging_tdb_context_destructor(struct messaging_tdb_context *ctx)
169 SMB_ASSERT(*ctx->have_context);
170 *ctx->have_context = false;
171 return 0;
174 bool messaging_tdb_parent_init(TALLOC_CTX *mem_ctx)
176 struct tdb_wrap *db;
177 struct loadparm_context *lp_ctx;
178 const char *fname;
180 lp_ctx = loadparm_init_s3(mem_ctx, loadparm_s3_helpers());
181 if (lp_ctx == NULL) {
182 DEBUG(0, ("loadparm_init_s3 failed\n"));
183 return false;
187 * Open the tdb in the parent process (smbd) so that our
188 * CLEAR_IF_FIRST optimization in tdb_reopen_all can properly
189 * work.
192 fname = lock_path("messages.tdb");
193 db = tdb_wrap_open(
194 mem_ctx, fname, lpcfg_tdb_hash_size(lp_ctx, fname),
195 lpcfg_tdb_flags(lp_ctx, TDB_CLEAR_IF_FIRST|TDB_DEFAULT|
196 TDB_VOLATILE|TDB_INCOMPATIBLE_HASH),
197 O_RDWR|O_CREAT,0600);
198 talloc_unlink(mem_ctx, lp_ctx);
199 if (db == NULL) {
200 DEBUG(1, ("could not open messaging.tdb: %s\n",
201 strerror(errno)));
202 return false;
204 return true;
207 /*******************************************************************
208 Form a static tdb key from a pid.
209 ******************************************************************/
211 static TDB_DATA message_key_pid(TALLOC_CTX *mem_ctx, struct server_id pid)
213 char *key;
214 TDB_DATA kbuf;
216 key = talloc_asprintf(mem_ctx, "PID/%s", procid_str_static(&pid));
218 SMB_ASSERT(key != NULL);
220 kbuf.dptr = (uint8 *)key;
221 kbuf.dsize = strlen(key)+1;
222 return kbuf;
225 /*******************************************************************
226 Called when a process has terminated abnormally. Remove all messages
227 pending for it.
228 ******************************************************************/
230 NTSTATUS messaging_tdb_cleanup(struct messaging_context *msg_ctx,
231 struct server_id pid)
233 struct messaging_tdb_context *ctx = talloc_get_type(
234 msg_ctx->local->private_data,
235 struct messaging_tdb_context);
236 struct tdb_wrap *tdb = ctx->tdb;
237 TDB_DATA key;
238 TALLOC_CTX *frame = talloc_stackframe();
240 key = message_key_pid(frame, pid);
242 * We have to lock the key to avoid
243 * races in case the server_id was
244 * re-used and is active (a remote
245 * possibility, true). We only
246 * clean up the database if we
247 * know server_id doesn't exist
248 * while checked under the chainlock.
250 if (tdb_chainlock(tdb->tdb, key) != 0) {
251 TALLOC_FREE(frame);
252 return NT_STATUS_LOCK_NOT_GRANTED;
254 if (!serverid_exists(&pid)) {
255 (void)tdb_delete(tdb->tdb, key);
257 tdb_chainunlock(tdb->tdb, key);
258 TALLOC_FREE(frame);
259 return NT_STATUS_OK;
263 Fetch the messaging array for a process
266 static NTSTATUS messaging_tdb_fetch(TDB_CONTEXT *msg_tdb,
267 TDB_DATA key,
268 TALLOC_CTX *mem_ctx,
269 struct messaging_array **presult)
271 struct messaging_array *result;
272 TDB_DATA data;
273 DATA_BLOB blob;
274 enum ndr_err_code ndr_err;
276 if (!(result = talloc_zero(mem_ctx, struct messaging_array))) {
277 return NT_STATUS_NO_MEMORY;
280 data = tdb_fetch(msg_tdb, key);
282 if (data.dptr == NULL) {
283 *presult = result;
284 return NT_STATUS_OK;
287 blob = data_blob_const(data.dptr, data.dsize);
289 ndr_err = ndr_pull_struct_blob_all(
290 &blob, result, result,
291 (ndr_pull_flags_fn_t)ndr_pull_messaging_array);
293 SAFE_FREE(data.dptr);
295 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
296 TALLOC_FREE(result);
297 return ndr_map_error2ntstatus(ndr_err);
300 if (DEBUGLEVEL >= 10) {
301 DEBUG(10, ("messaging_tdb_fetch:\n"));
302 NDR_PRINT_DEBUG(messaging_array, result);
305 *presult = result;
306 return NT_STATUS_OK;
310 Store a messaging array for a pid
313 static NTSTATUS messaging_tdb_store(TDB_CONTEXT *msg_tdb,
314 TDB_DATA key,
315 struct messaging_array *array)
317 TDB_DATA data;
318 DATA_BLOB blob;
319 enum ndr_err_code ndr_err;
320 TALLOC_CTX *mem_ctx;
321 int ret;
323 if (array->num_messages == 0) {
324 tdb_delete(msg_tdb, key);
325 return NT_STATUS_OK;
328 if (!(mem_ctx = talloc_new(array))) {
329 return NT_STATUS_NO_MEMORY;
332 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, array,
333 (ndr_push_flags_fn_t)ndr_push_messaging_array);
335 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
336 talloc_free(mem_ctx);
337 return ndr_map_error2ntstatus(ndr_err);
340 if (DEBUGLEVEL >= 10) {
341 DEBUG(10, ("messaging_tdb_store:\n"));
342 NDR_PRINT_DEBUG(messaging_array, array);
345 data.dptr = blob.data;
346 data.dsize = blob.length;
348 ret = tdb_store(msg_tdb, key, data, TDB_REPLACE);
349 TALLOC_FREE(mem_ctx);
351 return (ret == 0) ? NT_STATUS_OK : NT_STATUS_INTERNAL_DB_CORRUPTION;
354 /****************************************************************************
355 Notify a process that it has a message. If the process doesn't exist
356 then delete its record in the database.
357 ****************************************************************************/
359 static NTSTATUS message_notify(struct server_id procid)
361 pid_t pid = procid.pid;
362 int ret;
363 uid_t euid = geteuid();
366 * Doing kill with a non-positive pid causes messages to be
367 * sent to places we don't want.
370 SMB_ASSERT(pid > 0);
371 if (pid <= 0) {
372 return NT_STATUS_INVALID_HANDLE;
375 if (euid != 0) {
376 /* If we're not root become so to send the message. */
377 save_re_uid();
378 set_effective_uid(0);
381 ret = kill(pid, SIGUSR1);
383 if (euid != 0) {
384 /* Go back to who we were. */
385 int saved_errno = errno;
386 restore_re_uid_fromroot();
387 errno = saved_errno;
390 if (ret == 0) {
391 return NT_STATUS_OK;
395 * Something has gone wrong
398 DEBUG(2,("message to process %d failed - %s\n", (int)pid,
399 strerror(errno)));
402 * No call to map_nt_error_from_unix -- don't want to link in
403 * errormap.o into lots of utils.
406 if (errno == ESRCH) return NT_STATUS_INVALID_HANDLE;
407 if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER;
408 if (errno == EPERM) return NT_STATUS_ACCESS_DENIED;
409 return NT_STATUS_UNSUCCESSFUL;
412 /****************************************************************************
413 Send a message to a particular pid.
414 ****************************************************************************/
416 static NTSTATUS messaging_tdb_send(struct messaging_context *msg_ctx,
417 struct server_id pid, int msg_type,
418 const DATA_BLOB *data,
419 struct messaging_backend *backend)
421 struct messaging_tdb_context *ctx = talloc_get_type(backend->private_data,
422 struct messaging_tdb_context);
423 struct messaging_array *msg_array;
424 struct messaging_rec *rec;
425 NTSTATUS status;
426 TDB_DATA key;
427 struct tdb_wrap *tdb = ctx->tdb;
428 TALLOC_CTX *frame = talloc_stackframe();
430 /* NULL pointer means implicit length zero. */
431 if (!data->data) {
432 SMB_ASSERT(data->length == 0);
436 * Doing kill with a non-positive pid causes messages to be
437 * sent to places we don't want.
440 SMB_ASSERT(procid_to_pid(&pid) > 0);
442 key = message_key_pid(frame, pid);
444 if (tdb_chainlock(tdb->tdb, key) != 0) {
445 TALLOC_FREE(frame);
446 return NT_STATUS_LOCK_NOT_GRANTED;
449 status = messaging_tdb_fetch(tdb->tdb, key, frame, &msg_array);
451 if (!NT_STATUS_IS_OK(status)) {
452 goto done;
455 if ((msg_type & MSG_FLAG_LOWPRIORITY)
456 && (msg_array->num_messages > 1000)) {
457 DEBUG(5, ("Dropping message for PID %s\n",
458 procid_str_static(&pid)));
459 status = NT_STATUS_INSUFFICIENT_RESOURCES;
460 goto done;
463 if (!(rec = talloc_realloc(frame, msg_array->messages,
464 struct messaging_rec,
465 msg_array->num_messages+1))) {
466 status = NT_STATUS_NO_MEMORY;
467 goto done;
470 rec[msg_array->num_messages].msg_version = MESSAGE_VERSION;
471 rec[msg_array->num_messages].msg_type = msg_type & MSG_TYPE_MASK;
472 rec[msg_array->num_messages].dest = pid;
473 rec[msg_array->num_messages].src = msg_ctx->id;
474 rec[msg_array->num_messages].buf = *data;
476 msg_array->messages = rec;
477 msg_array->num_messages += 1;
479 status = messaging_tdb_store(tdb->tdb, key, msg_array);
481 if (!NT_STATUS_IS_OK(status)) {
482 goto done;
485 status = message_notify(pid);
487 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
488 DEBUG(2, ("pid %s doesn't exist - deleting messages record\n",
489 procid_str_static(&pid)));
490 tdb_delete(tdb->tdb, message_key_pid(frame, pid));
493 done:
494 tdb_chainunlock(tdb->tdb, key);
495 TALLOC_FREE(frame);
496 return status;
499 /****************************************************************************
500 Retrieve all messages for a process.
501 ****************************************************************************/
503 static NTSTATUS retrieve_all_messages(TDB_CONTEXT *msg_tdb,
504 struct server_id id,
505 TALLOC_CTX *mem_ctx,
506 struct messaging_array **presult)
508 struct messaging_array *result;
509 TDB_DATA key = message_key_pid(mem_ctx, id);
510 NTSTATUS status;
512 if (tdb_chainlock(msg_tdb, key) != 0) {
513 TALLOC_FREE(key.dptr);
514 return NT_STATUS_LOCK_NOT_GRANTED;
517 status = messaging_tdb_fetch(msg_tdb, key, mem_ctx, &result);
520 * We delete the record here, tdb_set_max_dead keeps it around
522 tdb_delete(msg_tdb, key);
523 tdb_chainunlock(msg_tdb, key);
525 if (NT_STATUS_IS_OK(status)) {
526 *presult = result;
529 TALLOC_FREE(key.dptr);
531 return status;
534 /****************************************************************************
535 Receive and dispatch any messages pending for this process.
536 JRA changed Dec 13 2006. Only one message handler now permitted per type.
537 *NOTE*: Dispatch functions must be able to cope with incoming
538 messages on an *odd* byte boundary.
539 ****************************************************************************/
541 static void message_dispatch(struct messaging_context *msg_ctx)
543 struct messaging_tdb_context *ctx = talloc_get_type(msg_ctx->local->private_data,
544 struct messaging_tdb_context);
545 struct messaging_array *msg_array = NULL;
546 struct tdb_wrap *tdb = ctx->tdb;
547 NTSTATUS status;
548 uint32 i;
550 if (ctx->received_messages == 0) {
551 return;
554 DEBUG(10, ("message_dispatch: received_messages = %d\n",
555 ctx->received_messages));
557 status = retrieve_all_messages(tdb->tdb, msg_ctx->id, NULL, &msg_array);
558 if (!NT_STATUS_IS_OK(status)) {
559 DEBUG(0, ("message_dispatch: failed to retrieve messages: %s\n",
560 nt_errstr(status)));
561 return;
564 ctx->received_messages = 0;
566 for (i=0; i<msg_array->num_messages; i++) {
567 messaging_dispatch_rec(msg_ctx, &msg_array->messages[i]);
570 TALLOC_FREE(msg_array);
573 /** @} **/