00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include "includes.h"
00049
00050
00051 static TDB_CONTEXT *tdb;
00052 static int received_signal;
00053
00054
00055 #define MESSAGE_VERSION 1
00056
00057 struct message_rec {
00058 int msg_version;
00059 int msg_type;
00060 struct process_id dest;
00061 struct process_id src;
00062 size_t len;
00063 };
00064
00065
00066 static struct dispatch_fns {
00067 struct dispatch_fns *next, *prev;
00068 int msg_type;
00069 void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len,
00070 void *private_data);
00071 void *private_data;
00072 } *dispatch_fns;
00073
00074
00075
00076
00077
00078 void gfree_messages(void)
00079 {
00080 struct dispatch_fns *dfn, *next;
00081
00082
00083 dfn = dispatch_fns;
00084 while( dfn ) {
00085 next = dfn->next;
00086 DLIST_REMOVE(dispatch_fns, dfn);
00087 SAFE_FREE(dfn);
00088 dfn = next;
00089 }
00090 }
00091
00092
00093
00094
00095
00096 static void sig_usr1(void)
00097 {
00098 received_signal = 1;
00099 sys_select_signal(SIGUSR1);
00100 }
00101
00102
00103
00104
00105
00106 static void ping_message(int msg_type, struct process_id src,
00107 void *buf, size_t len, void *private_data)
00108 {
00109 const char *msg = buf ? (const char *)buf : "none";
00110
00111 DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
00112 procid_str_static(&src), msg));
00113 message_send_pid(src, MSG_PONG, buf, len, True);
00114 }
00115
00116
00117
00118
00119
00120 BOOL message_init(void)
00121 {
00122 sec_init();
00123
00124 if (tdb)
00125 return True;
00126
00127 tdb = tdb_open_log(lock_path("messages.tdb"),
00128 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
00129 O_RDWR|O_CREAT,0600);
00130
00131 if (!tdb) {
00132 DEBUG(0,("ERROR: Failed to initialise messages database\n"));
00133 return False;
00134 }
00135
00136
00137 tdb_set_max_dead(tdb, 5);
00138
00139 CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
00140
00141 message_register(MSG_PING, ping_message, NULL);
00142
00143
00144
00145 register_msg_pool_usage();
00146 register_dmalloc_msgs();
00147
00148 return True;
00149 }
00150
00151
00152
00153
00154
00155 static TDB_DATA message_key_pid(struct process_id pid)
00156 {
00157 static char key[20];
00158 TDB_DATA kbuf;
00159
00160 slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid));
00161
00162 kbuf.dptr = (char *)key;
00163 kbuf.dsize = strlen(key)+1;
00164 return kbuf;
00165 }
00166
00167
00168
00169
00170
00171
00172 static NTSTATUS message_notify(struct process_id procid)
00173 {
00174 pid_t pid = procid.pid;
00175 int ret;
00176 uid_t euid = geteuid();
00177
00178
00179
00180
00181
00182
00183 SMB_ASSERT(pid > 0);
00184
00185 if (euid != 0) {
00186
00187 save_re_uid();
00188 set_effective_uid(0);
00189 }
00190
00191 ret = kill(pid, SIGUSR1);
00192
00193 if (euid != 0) {
00194
00195 int saved_errno = errno;
00196 restore_re_uid_fromroot();
00197 errno = saved_errno;
00198 }
00199
00200 if (ret == -1) {
00201 if (errno == ESRCH) {
00202 DEBUG(2,("pid %d doesn't exist - deleting messages record\n",
00203 (int)pid));
00204 tdb_delete(tdb, message_key_pid(procid));
00205
00206
00207
00208
00209 return NT_STATUS_INVALID_HANDLE;
00210 }
00211
00212 DEBUG(2,("message to process %d failed - %s\n", (int)pid,
00213 strerror(errno)));
00214
00215
00216
00217
00218
00219
00220 if (errno == EINVAL) return NT_STATUS_INVALID_PARAMETER;
00221 if (errno == EPERM) return NT_STATUS_ACCESS_DENIED;
00222 return NT_STATUS_UNSUCCESSFUL;
00223 }
00224
00225 return NT_STATUS_OK;
00226 }
00227
00228
00229
00230
00231
00232 static NTSTATUS message_send_pid_internal(struct process_id pid, int msg_type,
00233 const void *buf, size_t len,
00234 BOOL duplicates_allowed,
00235 unsigned int timeout)
00236 {
00237 TDB_DATA kbuf;
00238 TDB_DATA dbuf;
00239 TDB_DATA old_dbuf;
00240 struct message_rec rec;
00241 char *ptr;
00242 struct message_rec prec;
00243
00244
00245 if (!buf) {
00246 SMB_ASSERT(len == 0);
00247 }
00248
00249
00250
00251
00252
00253
00254 SMB_ASSERT(procid_to_pid(&pid) > 0);
00255
00256 rec.msg_version = MESSAGE_VERSION;
00257 rec.msg_type = msg_type;
00258 rec.dest = pid;
00259 rec.src = procid_self();
00260 rec.len = buf ? len : 0;
00261
00262 kbuf = message_key_pid(pid);
00263
00264 dbuf.dptr = (char *)SMB_MALLOC(len + sizeof(rec));
00265 if (!dbuf.dptr) {
00266 return NT_STATUS_NO_MEMORY;
00267 }
00268
00269 memcpy(dbuf.dptr, &rec, sizeof(rec));
00270 if (len > 0 && buf)
00271 memcpy((void *)((char*)dbuf.dptr+sizeof(rec)), buf, len);
00272
00273 dbuf.dsize = len + sizeof(rec);
00274
00275 if (duplicates_allowed) {
00276
00277
00278
00279
00280 if (timeout) {
00281 if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
00282 DEBUG(0,("message_send_pid_internal: failed to get "
00283 "chainlock with timeout %ul.\n", timeout));
00284 SAFE_FREE(dbuf.dptr);
00285 return NT_STATUS_IO_TIMEOUT;
00286 }
00287 } else {
00288 if (tdb_chainlock(tdb, kbuf) == -1) {
00289 DEBUG(0,("message_send_pid_internal: failed to get "
00290 "chainlock.\n"));
00291 SAFE_FREE(dbuf.dptr);
00292 return NT_STATUS_LOCK_NOT_GRANTED;
00293 }
00294 }
00295 tdb_append(tdb, kbuf, dbuf);
00296 tdb_chainunlock(tdb, kbuf);
00297
00298 SAFE_FREE(dbuf.dptr);
00299 errno = 0;
00300 return message_notify(pid);
00301 }
00302
00303
00304 if (timeout) {
00305 if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) {
00306 DEBUG(0,("message_send_pid_internal: failed to get chainlock "
00307 "with timeout %ul.\n", timeout));
00308 SAFE_FREE(dbuf.dptr);
00309 return NT_STATUS_IO_TIMEOUT;
00310 }
00311 } else {
00312 if (tdb_chainlock(tdb, kbuf) == -1) {
00313 DEBUG(0,("message_send_pid_internal: failed to get "
00314 "chainlock.\n"));
00315 SAFE_FREE(dbuf.dptr);
00316 return NT_STATUS_LOCK_NOT_GRANTED;
00317 }
00318 }
00319
00320 old_dbuf = tdb_fetch(tdb, kbuf);
00321
00322 if (!old_dbuf.dptr) {
00323
00324
00325 tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
00326 tdb_chainunlock(tdb, kbuf);
00327
00328 SAFE_FREE(dbuf.dptr);
00329 errno = 0;
00330 return message_notify(pid);
00331 }
00332
00333
00334
00335 for(ptr = (char *)old_dbuf.dptr; ptr < old_dbuf.dptr + old_dbuf.dsize; ) {
00336
00337
00338
00339
00340
00341
00342 if (!memcmp(ptr, &rec, sizeof(rec))) {
00343 if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) {
00344 tdb_chainunlock(tdb, kbuf);
00345 DEBUG(10,("message_send_pid_internal: discarding "
00346 "duplicate message.\n"));
00347 SAFE_FREE(dbuf.dptr);
00348 SAFE_FREE(old_dbuf.dptr);
00349 return NT_STATUS_OK;
00350 }
00351 }
00352 memcpy(&prec, ptr, sizeof(prec));
00353 ptr += sizeof(rec) + prec.len;
00354 }
00355
00356
00357
00358 tdb_append(tdb, kbuf, dbuf);
00359 tdb_chainunlock(tdb, kbuf);
00360
00361 SAFE_FREE(old_dbuf.dptr);
00362 SAFE_FREE(dbuf.dptr);
00363
00364 errno = 0;
00365 return message_notify(pid);
00366 }
00367
00368
00369
00370
00371
00372 NTSTATUS message_send_pid(struct process_id pid, int msg_type, const void *buf,
00373 size_t len, BOOL duplicates_allowed)
00374 {
00375 return message_send_pid_internal(pid, msg_type, buf, len,
00376 duplicates_allowed, 0);
00377 }
00378
00379
00380
00381
00382
00383 NTSTATUS message_send_pid_with_timeout(struct process_id pid, int msg_type,
00384 const void *buf, size_t len,
00385 BOOL duplicates_allowed, unsigned int timeout)
00386 {
00387 return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed,
00388 timeout);
00389 }
00390
00391
00392
00393
00394
00395 unsigned int messages_pending_for_pid(struct process_id pid)
00396 {
00397 TDB_DATA kbuf;
00398 TDB_DATA dbuf;
00399 char *buf;
00400 unsigned int message_count = 0;
00401
00402 kbuf = message_key_pid(pid);
00403
00404 dbuf = tdb_fetch(tdb, kbuf);
00405 if (dbuf.dptr == NULL || dbuf.dsize == 0) {
00406 SAFE_FREE(dbuf.dptr);
00407 return 0;
00408 }
00409
00410 for (buf = dbuf.dptr; dbuf.dsize > sizeof(struct message_rec);) {
00411 struct message_rec rec;
00412 memcpy(&rec, buf, sizeof(rec));
00413 buf += (sizeof(rec) + rec.len);
00414 dbuf.dsize -= (sizeof(rec) + rec.len);
00415 message_count++;
00416 }
00417
00418 SAFE_FREE(dbuf.dptr);
00419 return message_count;
00420 }
00421
00422
00423
00424
00425
00426 static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
00427 {
00428 TDB_DATA kbuf;
00429 TDB_DATA dbuf;
00430 TDB_DATA null_dbuf;
00431
00432 ZERO_STRUCT(null_dbuf);
00433
00434 *msgs_buf = NULL;
00435 *total_len = 0;
00436
00437 kbuf = message_key_pid(pid_to_procid(sys_getpid()));
00438
00439 if (tdb_chainlock(tdb, kbuf) == -1)
00440 return False;
00441
00442 dbuf = tdb_fetch(tdb, kbuf);
00443
00444
00445
00446
00447 tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE);
00448 tdb_chainunlock(tdb, kbuf);
00449
00450 if (dbuf.dptr == NULL || dbuf.dsize == 0) {
00451 SAFE_FREE(dbuf.dptr);
00452 return False;
00453 }
00454
00455 *msgs_buf = dbuf.dptr;
00456 *total_len = dbuf.dsize;
00457
00458 return True;
00459 }
00460
00461
00462
00463
00464
00465 static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type,
00466 struct process_id *src, char **buf, size_t *len)
00467 {
00468 struct message_rec rec;
00469 char *ret_buf = *buf;
00470
00471 *buf = NULL;
00472 *len = 0;
00473
00474 if (total_len - (ret_buf - msgs_buf) < sizeof(rec))
00475 return False;
00476
00477 memcpy(&rec, ret_buf, sizeof(rec));
00478 ret_buf += sizeof(rec);
00479
00480 if (rec.msg_version != MESSAGE_VERSION) {
00481 DEBUG(0,("message version %d received (expected %d)\n", rec.msg_version, MESSAGE_VERSION));
00482 return False;
00483 }
00484
00485 if (rec.len > 0) {
00486 if (total_len - (ret_buf - msgs_buf) < rec.len)
00487 return False;
00488 }
00489
00490 *len = rec.len;
00491 *msg_type = rec.msg_type;
00492 *src = rec.src;
00493 *buf = ret_buf;
00494
00495 return True;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505 void message_dispatch(void)
00506 {
00507 int msg_type;
00508 struct process_id src;
00509 char *buf;
00510 char *msgs_buf;
00511 size_t len, total_len;
00512 int n_handled;
00513
00514 if (!received_signal)
00515 return;
00516
00517 DEBUG(10,("message_dispatch: received_signal = %d\n", received_signal));
00518
00519 received_signal = 0;
00520
00521 if (!retrieve_all_messages(&msgs_buf, &total_len))
00522 return;
00523
00524 for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) {
00525 struct dispatch_fns *dfn;
00526
00527 DEBUG(10,("message_dispatch: received msg_type=%d "
00528 "src_pid=%u\n", msg_type,
00529 (unsigned int) procid_to_pid(&src)));
00530
00531 n_handled = 0;
00532 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
00533 if (dfn->msg_type == msg_type) {
00534 DEBUG(10,("message_dispatch: processing message of type %d.\n", msg_type));
00535 dfn->fn(msg_type, src,
00536 len ? (void *)buf : NULL, len,
00537 dfn->private_data);
00538 n_handled++;
00539 break;
00540 }
00541 }
00542 if (!n_handled) {
00543 DEBUG(5,("message_dispatch: warning: no handler registed for "
00544 "msg_type %d in pid %u\n",
00545 msg_type, (unsigned int)sys_getpid()));
00546 }
00547 }
00548 SAFE_FREE(msgs_buf);
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558 void message_register(int msg_type,
00559 void (*fn)(int msg_type, struct process_id pid,
00560 void *buf, size_t len,
00561 void *private_data),
00562 void *private_data)
00563 {
00564 struct dispatch_fns *dfn;
00565
00566 for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
00567 if (dfn->msg_type == msg_type) {
00568 dfn->fn = fn;
00569 return;
00570 }
00571 }
00572
00573 dfn = SMB_MALLOC_P(struct dispatch_fns);
00574
00575 if (dfn != NULL) {
00576
00577 ZERO_STRUCTPN(dfn);
00578
00579 dfn->msg_type = msg_type;
00580 dfn->fn = fn;
00581 dfn->private_data = private_data;
00582
00583 DLIST_ADD(dispatch_fns, dfn);
00584 }
00585 else {
00586
00587 DEBUG(0,("message_register: Not enough memory. malloc failed!\n"));
00588 }
00589 }
00590
00591
00592
00593
00594
00595 void message_deregister(int msg_type)
00596 {
00597 struct dispatch_fns *dfn, *next;
00598
00599 for (dfn = dispatch_fns; dfn; dfn = next) {
00600 next = dfn->next;
00601 if (dfn->msg_type == msg_type) {
00602 DLIST_REMOVE(dispatch_fns, dfn);
00603 SAFE_FREE(dfn);
00604 return;
00605 }
00606 }
00607 }
00608
00609 struct msg_all {
00610 int msg_type;
00611 uint32 msg_flag;
00612 const void *buf;
00613 size_t len;
00614 BOOL duplicates;
00615 int n_sent;
00616 };
00617
00618
00619
00620
00621
00622 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
00623 {
00624 struct connections_data crec;
00625 struct msg_all *msg_all = (struct msg_all *)state;
00626 NTSTATUS status;
00627
00628 if (dbuf.dsize != sizeof(crec))
00629 return 0;
00630
00631 memcpy(&crec, dbuf.dptr, sizeof(crec));
00632
00633 if (crec.cnum != -1)
00634 return 0;
00635
00636
00637
00638 if(!(crec.bcast_msg_flags & msg_all->msg_flag))
00639 return 0;
00640
00641
00642
00643
00644 status = message_send_pid(crec.pid, msg_all->msg_type,
00645 msg_all->buf, msg_all->len,
00646 msg_all->duplicates);
00647
00648 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_HANDLE)) {
00649
00650
00651
00652 DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
00653 procid_str_static(&crec.pid), crec.cnum, crec.servicename));
00654 tdb_delete(the_tdb, kbuf);
00655 }
00656 msg_all->n_sent++;
00657 return 0;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
00673 const void *buf, size_t len,
00674 BOOL duplicates_allowed,
00675 int *n_sent)
00676 {
00677 struct msg_all msg_all;
00678
00679 msg_all.msg_type = msg_type;
00680 if (msg_type < 1000)
00681 msg_all.msg_flag = FLAG_MSG_GENERAL;
00682 else if (msg_type > 1000 && msg_type < 2000)
00683 msg_all.msg_flag = FLAG_MSG_NMBD;
00684 else if (msg_type > 2000 && msg_type < 2100)
00685 msg_all.msg_flag = FLAG_MSG_PRINT_NOTIFY;
00686 else if (msg_type > 2100 && msg_type < 3000)
00687 msg_all.msg_flag = FLAG_MSG_PRINT_GENERAL;
00688 else if (msg_type > 3000 && msg_type < 4000)
00689 msg_all.msg_flag = FLAG_MSG_SMBD;
00690 else
00691 return False;
00692
00693 msg_all.buf = buf;
00694 msg_all.len = len;
00695 msg_all.duplicates = duplicates_allowed;
00696 msg_all.n_sent = 0;
00697
00698 tdb_traverse(conn_tdb, traverse_fn, &msg_all);
00699 if (n_sent)
00700 *n_sent = msg_all.n_sent;
00701 return True;
00702 }
00703
00704
00705
00706
00707
00708
00709 void message_block(void)
00710 {
00711 BlockSignals(True, SIGUSR1);
00712 }
00713
00714 void message_unblock(void)
00715 {
00716 BlockSignals(False, SIGUSR1);
00717 }
00718
00719
00720
00721
00722
00723
00724 struct messaging_callback {
00725 struct messaging_callback *prev, *next;
00726 uint32 msg_type;
00727 void (*fn)(struct messaging_context *msg, void *private_data,
00728 uint32_t msg_type,
00729 struct server_id server_id, DATA_BLOB *data);
00730 void *private_data;
00731 };
00732
00733 struct messaging_context {
00734 struct server_id id;
00735 struct messaging_callback *callbacks;
00736 };
00737
00738 static int messaging_context_destructor(struct messaging_context *ctx)
00739 {
00740 struct messaging_callback *cb;
00741
00742 for (cb = ctx->callbacks; cb; cb = cb->next) {
00743
00744
00745
00746
00747 message_deregister(cb->msg_type);
00748 }
00749 return 0;
00750 }
00751
00752 struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx,
00753 struct server_id server_id,
00754 struct event_context *ev)
00755 {
00756 struct messaging_context *ctx;
00757
00758 if (!(ctx = TALLOC_ZERO_P(mem_ctx, struct messaging_context))) {
00759 return NULL;
00760 }
00761
00762 ctx->id = server_id;
00763 talloc_set_destructor(ctx, messaging_context_destructor);
00764 return ctx;
00765 }
00766
00767 static void messaging_callback(int msg_type, struct process_id pid,
00768 void *buf, size_t len, void *private_data)
00769 {
00770 struct messaging_context *ctx = talloc_get_type_abort(
00771 private_data, struct messaging_context);
00772 struct messaging_callback *cb, *next;
00773
00774 for (cb = ctx->callbacks; cb; cb = next) {
00775
00776
00777
00778 next = cb->next;
00779
00780 if (msg_type == cb->msg_type) {
00781 DATA_BLOB blob;
00782 struct server_id id;
00783
00784 blob.data = (uint8 *)buf;
00785 blob.length = len;
00786 id.id = pid;
00787
00788 cb->fn(ctx, cb->private_data, msg_type, id, &blob);
00789 }
00790 }
00791 }
00792
00793
00794
00795
00796
00797 NTSTATUS messaging_register(struct messaging_context *ctx, void *private_data,
00798 uint32_t msg_type,
00799 void (*fn)(struct messaging_context *msg,
00800 void *private_data,
00801 uint32_t msg_type,
00802 struct server_id server_id,
00803 DATA_BLOB *data))
00804 {
00805 struct messaging_callback *cb;
00806
00807 if (!(cb = talloc(ctx, struct messaging_callback))) {
00808 return NT_STATUS_NO_MEMORY;
00809 }
00810
00811 cb->msg_type = msg_type;
00812 cb->fn = fn;
00813 cb->private_data = private_data;
00814
00815 DLIST_ADD(ctx->callbacks, cb);
00816 message_register(msg_type, messaging_callback, ctx);
00817 return NT_STATUS_OK;
00818 }
00819
00820
00821
00822
00823 void messaging_deregister(struct messaging_context *ctx, uint32_t msg_type,
00824 void *private_data)
00825 {
00826 struct messaging_callback *cb, *next;
00827
00828 for (cb = ctx->callbacks; cb; cb = next) {
00829 next = cb->next;
00830 if ((cb->msg_type == msg_type)
00831 && (cb->private_data == private_data)) {
00832 DLIST_REMOVE(ctx->callbacks, cb);
00833 TALLOC_FREE(cb);
00834 }
00835 }
00836 }
00837
00838
00839
00840
00841 NTSTATUS messaging_send(struct messaging_context *msg,
00842 struct server_id server,
00843 uint32_t msg_type, DATA_BLOB *data)
00844 {
00845 return message_send_pid_internal(server.id, msg_type, data->data,
00846 data->length, True, 0);
00847 }
00848
00849