Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Samba internal messaging functions
5 :
6 : Copyright (C) Andrew Tridgell 2004
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "lib/events/events.h"
24 : #include "lib/util/server_id.h"
25 : #include "system/filesys.h"
26 : #include "messaging/messaging.h"
27 : #include "messaging/messaging_internal.h"
28 : #include "../lib/util/dlinklist.h"
29 : #include "lib/socket/socket.h"
30 : #include "librpc/gen_ndr/ndr_irpc.h"
31 : #include "lib/messaging/irpc.h"
32 : #include "../lib/util/unix_privs.h"
33 : #include "librpc/rpc/dcerpc.h"
34 : #include "cluster/cluster.h"
35 : #include "../lib/util/tevent_ntstatus.h"
36 : #include "lib/param/param.h"
37 : #include "lib/util/server_id_db.h"
38 : #include "lib/util/talloc_report_printf.h"
39 : #include "lib/messaging/messages_dgm.h"
40 : #include "lib/messaging/messages_dgm_ref.h"
41 : #include "../source3/lib/messages_util.h"
42 : #include <tdb.h>
43 : #include "lib/util/idtree.h"
44 :
45 : /* change the message version with any incompatible changes in the protocol */
46 : #define IMESSAGING_VERSION 1
47 :
48 : /*
49 : a pending irpc call
50 : */
51 : struct irpc_request {
52 : struct irpc_request *prev, *next;
53 : struct imessaging_context *msg_ctx;
54 : int callid;
55 : struct {
56 : void (*handler)(struct irpc_request *irpc, struct irpc_message *m);
57 : void *private_data;
58 : } incoming;
59 : };
60 :
61 : /* we have a linked list of dispatch handlers for each msg_type that
62 : this messaging server can deal with */
63 : struct dispatch_fn {
64 : struct dispatch_fn *next, *prev;
65 : uint32_t msg_type;
66 : void *private_data;
67 : msg_callback_t fn;
68 : };
69 :
70 : /* an individual message */
71 :
72 : static void irpc_handler(struct imessaging_context *,
73 : void *,
74 : uint32_t,
75 : struct server_id,
76 : size_t,
77 : int *,
78 : DATA_BLOB *);
79 :
80 :
81 : /*
82 : A useful function for testing the message system.
83 : */
84 2725 : static void ping_message(struct imessaging_context *msg,
85 : void *private_data,
86 : uint32_t msg_type,
87 : struct server_id src,
88 : size_t num_fds,
89 : int *fds,
90 : DATA_BLOB *data)
91 : {
92 0 : struct server_id_buf idbuf;
93 :
94 2725 : if (num_fds != 0) {
95 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
96 0 : return;
97 : }
98 :
99 2725 : DEBUG(1,("INFO: Received PING message from server %s [%.*s]\n",
100 : server_id_str_buf(src, &idbuf), (int)data->length,
101 : data->data?(const char *)data->data:""));
102 2725 : imessaging_send(msg, src, MSG_PONG, data);
103 : }
104 :
105 0 : static void pool_message(struct imessaging_context *msg,
106 : void *private_data,
107 : uint32_t msg_type,
108 : struct server_id src,
109 : size_t num_fds,
110 : int *fds,
111 : DATA_BLOB *data)
112 : {
113 0 : FILE *f = NULL;
114 :
115 0 : if (num_fds != 1) {
116 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
117 0 : return;
118 : }
119 :
120 0 : f = fdopen(fds[0], "w");
121 0 : if (f == NULL) {
122 0 : DBG_DEBUG("fopen failed: %s\n", strerror(errno));
123 0 : return;
124 : }
125 :
126 0 : talloc_full_report_printf(NULL, f);
127 0 : fclose(f);
128 : }
129 :
130 0 : static void ringbuf_log_msg(struct imessaging_context *msg,
131 : void *private_data,
132 : uint32_t msg_type,
133 : struct server_id src,
134 : size_t num_fds,
135 : int *fds,
136 : DATA_BLOB *data)
137 : {
138 0 : char *log = debug_get_ringbuf();
139 0 : size_t logsize = debug_get_ringbuf_size();
140 0 : DATA_BLOB blob;
141 :
142 0 : if (num_fds != 0) {
143 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
144 0 : return;
145 : }
146 :
147 0 : if (log == NULL) {
148 0 : log = discard_const_p(char, "*disabled*\n");
149 0 : logsize = strlen(log) + 1;
150 : }
151 :
152 0 : blob.data = (uint8_t *)log;
153 0 : blob.length = logsize;
154 :
155 0 : imessaging_send(msg, src, MSG_RINGBUF_LOG, &blob);
156 : }
157 :
158 : /****************************************************************************
159 : Receive a "set debug level" message.
160 : ****************************************************************************/
161 :
162 0 : static void debug_imessage(struct imessaging_context *msg_ctx,
163 : void *private_data,
164 : uint32_t msg_type,
165 : struct server_id src,
166 : size_t num_fds,
167 : int *fds,
168 : DATA_BLOB *data)
169 : {
170 0 : const char *params_str = (const char *)data->data;
171 0 : struct server_id_buf src_buf;
172 0 : struct server_id dst = imessaging_get_server_id(msg_ctx);
173 0 : struct server_id_buf dst_buf;
174 :
175 0 : if (num_fds != 0) {
176 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
177 0 : return;
178 : }
179 :
180 : /* Check, it's a proper string! */
181 0 : if (params_str[(data->length)-1] != '\0') {
182 0 : DBG_ERR("Invalid debug message from pid %s to pid %s\n",
183 : server_id_str_buf(src, &src_buf),
184 : server_id_str_buf(dst, &dst_buf));
185 0 : return;
186 : }
187 :
188 0 : DBG_ERR("INFO: Remote set of debug to `%s' (pid %s from pid %s)\n",
189 : params_str,
190 : server_id_str_buf(dst, &dst_buf),
191 : server_id_str_buf(src, &src_buf));
192 :
193 0 : debug_parse_levels(params_str);
194 : }
195 :
196 : /****************************************************************************
197 : Return current debug level.
198 : ****************************************************************************/
199 :
200 0 : static void debuglevel_imessage(struct imessaging_context *msg_ctx,
201 : void *private_data,
202 : uint32_t msg_type,
203 : struct server_id src,
204 : size_t num_fds,
205 : int *fds,
206 : DATA_BLOB *data)
207 : {
208 0 : char *message = debug_list_class_names_and_levels();
209 0 : DATA_BLOB blob = data_blob_null;
210 0 : struct server_id_buf src_buf;
211 0 : struct server_id dst = imessaging_get_server_id(msg_ctx);
212 0 : struct server_id_buf dst_buf;
213 :
214 0 : if (num_fds != 0) {
215 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
216 0 : return;
217 : }
218 :
219 0 : DBG_DEBUG("Received REQ_DEBUGLEVEL message (pid %s from pid %s)\n",
220 : server_id_str_buf(dst, &dst_buf),
221 : server_id_str_buf(src, &src_buf));
222 :
223 0 : if (message == NULL) {
224 0 : DBG_ERR("debug_list_class_names_and_levels returned NULL\n");
225 0 : return;
226 : }
227 :
228 0 : blob = data_blob_string_const_null(message);
229 0 : imessaging_send(msg_ctx, src, MSG_DEBUGLEVEL, &blob);
230 :
231 0 : TALLOC_FREE(message);
232 : }
233 :
234 : /*
235 : return uptime of messaging server via irpc
236 : */
237 0 : static NTSTATUS irpc_uptime(struct irpc_message *msg,
238 : struct irpc_uptime *r)
239 : {
240 0 : struct imessaging_context *ctx = talloc_get_type(msg->private_data, struct imessaging_context);
241 0 : *r->out.start_time = timeval_to_nttime(&ctx->start_time);
242 0 : return NT_STATUS_OK;
243 : }
244 :
245 96452 : static struct dispatch_fn *imessaging_find_dispatch(
246 : struct imessaging_context *msg, uint32_t msg_type)
247 : {
248 : /* temporary IDs use an idtree, the rest use a array of pointers */
249 96452 : if (msg_type >= MSG_TMP_BASE) {
250 32260 : return (struct dispatch_fn *)idr_find(msg->dispatch_tree,
251 : msg_type);
252 : }
253 64192 : if (msg_type < msg->num_types) {
254 64192 : return msg->dispatch[msg_type];
255 : }
256 0 : return NULL;
257 : }
258 :
259 : /*
260 : Register a dispatch function for a particular message type.
261 : */
262 3314073 : NTSTATUS imessaging_register(struct imessaging_context *msg, void *private_data,
263 : uint32_t msg_type, msg_callback_t fn)
264 : {
265 136663 : struct dispatch_fn *d;
266 :
267 : /* possibly expand dispatch array */
268 3314073 : if (msg_type >= msg->num_types) {
269 51249 : struct dispatch_fn **dp;
270 51249 : uint32_t i;
271 1241133 : dp = talloc_realloc(msg, msg->dispatch, struct dispatch_fn *, msg_type+1);
272 1241133 : NT_STATUS_HAVE_NO_MEMORY(dp);
273 1241133 : msg->dispatch = dp;
274 744145691 : for (i=msg->num_types;i<=msg_type;i++) {
275 742904558 : msg->dispatch[i] = NULL;
276 : }
277 1241133 : msg->num_types = msg_type+1;
278 : }
279 :
280 3314073 : d = talloc_zero(msg->dispatch, struct dispatch_fn);
281 3314073 : NT_STATUS_HAVE_NO_MEMORY(d);
282 3314073 : d->msg_type = msg_type;
283 3314073 : d->private_data = private_data;
284 3314073 : d->fn = fn;
285 :
286 3314073 : DLIST_ADD(msg->dispatch[msg_type], d);
287 :
288 3314073 : return NT_STATUS_OK;
289 : }
290 :
291 : /*
292 : register a temporary message handler. The msg_type is allocated
293 : above MSG_TMP_BASE
294 : */
295 8 : NTSTATUS imessaging_register_tmp(struct imessaging_context *msg, void *private_data,
296 : msg_callback_t fn, uint32_t *msg_type)
297 : {
298 3 : struct dispatch_fn *d;
299 3 : int id;
300 :
301 8 : d = talloc_zero(msg->dispatch, struct dispatch_fn);
302 8 : NT_STATUS_HAVE_NO_MEMORY(d);
303 8 : d->private_data = private_data;
304 8 : d->fn = fn;
305 :
306 8 : id = idr_get_new_above(msg->dispatch_tree, d, MSG_TMP_BASE, UINT16_MAX);
307 8 : if (id == -1) {
308 0 : talloc_free(d);
309 0 : return NT_STATUS_TOO_MANY_CONTEXT_IDS;
310 : }
311 :
312 8 : d->msg_type = (uint32_t)id;
313 8 : (*msg_type) = d->msg_type;
314 :
315 8 : return NT_STATUS_OK;
316 : }
317 :
318 : /*
319 : De-register the function for a particular message type. Return the number of
320 : functions deregistered.
321 : */
322 4580 : size_t imessaging_deregister(struct imessaging_context *msg, uint32_t msg_type, void *private_data)
323 : {
324 0 : struct dispatch_fn *d, *next;
325 4580 : size_t removed = 0;
326 :
327 4580 : if (msg_type >= msg->num_types) {
328 5 : d = (struct dispatch_fn *)idr_find(msg->dispatch_tree,
329 : msg_type);
330 5 : if (!d) return 0;
331 5 : idr_remove(msg->dispatch_tree, msg_type);
332 5 : talloc_free(d);
333 5 : return 1;
334 : }
335 :
336 9212 : for (d = msg->dispatch[msg_type]; d; d = next) {
337 4637 : next = d->next;
338 4637 : if (d->private_data == private_data) {
339 4575 : DLIST_REMOVE(msg->dispatch[msg_type], d);
340 4575 : talloc_free(d);
341 4575 : ++removed;
342 : }
343 : }
344 :
345 4575 : return removed;
346 : }
347 :
348 : /*
349 : */
350 129641 : int imessaging_cleanup(struct imessaging_context *msg)
351 : {
352 129641 : return 0;
353 : }
354 :
355 : static void imessaging_dgm_recv(struct tevent_context *ev,
356 : const uint8_t *buf, size_t buf_len,
357 : int *fds, size_t num_fds,
358 : void *private_data);
359 :
360 : /* Keep a list of imessaging contexts */
361 : static struct imessaging_context *msg_ctxs;
362 :
363 : /*
364 : * A process has terminated, clean-up any names it has registered.
365 : */
366 809 : NTSTATUS imessaging_process_cleanup(
367 : struct imessaging_context *msg_ctx,
368 : pid_t pid)
369 : {
370 809 : struct irpc_name_records *names = NULL;
371 809 : uint32_t i = 0;
372 809 : uint32_t j = 0;
373 809 : TALLOC_CTX *mem_ctx = talloc_new(NULL);
374 :
375 809 : if (mem_ctx == NULL) {
376 0 : DBG_ERR("OOM unable to clean up messaging for process (%d)\n",
377 : pid);
378 0 : return NT_STATUS_NO_MEMORY;
379 : }
380 :
381 809 : names = irpc_all_servers(msg_ctx, mem_ctx);
382 809 : if (names == NULL) {
383 0 : TALLOC_FREE(mem_ctx);
384 0 : return NT_STATUS_OK;
385 : }
386 15979 : for (i = 0; i < names->num_records; i++) {
387 33325 : for (j = 0; j < names->names[i]->count; j++) {
388 18155 : if (names->names[i]->ids[j].pid == pid) {
389 951 : int ret = server_id_db_prune_name(
390 : msg_ctx->names,
391 877 : names->names[i]->name,
392 877 : names->names[i]->ids[j]);
393 951 : if (ret != 0 && ret != ENOENT) {
394 0 : TALLOC_FREE(mem_ctx);
395 0 : return map_nt_error_from_unix_common(
396 : ret);
397 : }
398 : }
399 : }
400 : }
401 809 : TALLOC_FREE(mem_ctx);
402 809 : return NT_STATUS_OK;
403 : }
404 :
405 457482 : static int imessaging_context_destructor(struct imessaging_context *msg)
406 : {
407 457482 : struct irpc_request *irpc = NULL;
408 457482 : struct irpc_request *next = NULL;
409 :
410 457482 : for (irpc = msg->requests; irpc != NULL; irpc = next) {
411 0 : next = irpc->next;
412 :
413 0 : DLIST_REMOVE(msg->requests, irpc);
414 0 : irpc->callid = -1;
415 : }
416 :
417 457482 : DLIST_REMOVE(msg_ctxs, msg);
418 457482 : TALLOC_FREE(msg->msg_dgm_ref);
419 457482 : return 0;
420 : }
421 :
422 : /*
423 : * Cleanup messaging dgm contexts on a specific event context.
424 : *
425 : * We must make sure to unref all messaging_dgm_ref's *before* the
426 : * tevent context goes away. Only when the last ref is freed, the
427 : * refcounted messaging dgm context will be freed.
428 : */
429 587 : void imessaging_dgm_unref_ev(struct tevent_context *ev)
430 : {
431 587 : struct imessaging_context *msg = NULL;
432 :
433 2999 : for (msg = msg_ctxs; msg != NULL; msg = msg->next) {
434 2412 : if (msg->ev == ev) {
435 1720 : TALLOC_FREE(msg->msg_dgm_ref);
436 : }
437 : }
438 587 : }
439 :
440 57967 : static NTSTATUS imessaging_reinit(struct imessaging_context *msg)
441 : {
442 57967 : int ret = -1;
443 :
444 57967 : TALLOC_FREE(msg->msg_dgm_ref);
445 :
446 57967 : if (msg->discard_incoming) {
447 24514 : msg->num_incoming_listeners = 0;
448 : } else {
449 33453 : msg->num_incoming_listeners = 1;
450 : }
451 :
452 57967 : msg->server_id.pid = getpid();
453 :
454 57967 : msg->msg_dgm_ref = messaging_dgm_ref(msg,
455 : msg->ev,
456 : &msg->server_id.unique_id,
457 : msg->sock_dir,
458 : msg->lock_dir,
459 : imessaging_dgm_recv,
460 : msg,
461 : &ret);
462 :
463 57967 : if (msg->msg_dgm_ref == NULL) {
464 0 : DEBUG(2, ("messaging_dgm_ref failed: %s\n",
465 : strerror(ret)));
466 0 : return map_nt_error_from_unix_common(ret);
467 : }
468 :
469 57967 : server_id_db_reinit(msg->names, msg->server_id);
470 57967 : return NT_STATUS_OK;
471 : }
472 :
473 : /*
474 : * Must be called after a fork.
475 : */
476 16651 : NTSTATUS imessaging_reinit_all(void)
477 : {
478 16651 : struct imessaging_context *msg = NULL;
479 :
480 74618 : for (msg = msg_ctxs; msg != NULL; msg = msg->next) {
481 57967 : NTSTATUS status = imessaging_reinit(msg);
482 57967 : if (!NT_STATUS_IS_OK(status)) {
483 0 : return status;
484 : }
485 : }
486 16651 : return NT_STATUS_OK;
487 : }
488 :
489 : /*
490 : create the listening socket and setup the dispatcher
491 : */
492 413658 : static struct imessaging_context *imessaging_init_internal(
493 : TALLOC_CTX *mem_ctx,
494 : bool discard_incoming,
495 : struct loadparm_context *lp_ctx,
496 : struct server_id server_id,
497 : struct tevent_context *ev)
498 : {
499 17082 : NTSTATUS status;
500 17082 : struct imessaging_context *msg;
501 17082 : bool ok;
502 17082 : int ret;
503 413658 : const char *lock_dir = NULL;
504 413658 : int tdb_flags = TDB_INCOMPATIBLE_HASH | TDB_CLEAR_IF_FIRST;
505 :
506 413658 : if (ev == NULL) {
507 0 : return NULL;
508 : }
509 :
510 413658 : msg = talloc_zero(mem_ctx, struct imessaging_context);
511 413658 : if (msg == NULL) {
512 0 : return NULL;
513 : }
514 413658 : msg->ev = ev;
515 413658 : msg->discard_incoming = discard_incoming;
516 413658 : if (msg->discard_incoming) {
517 283164 : msg->num_incoming_listeners = 0;
518 : } else {
519 130494 : msg->num_incoming_listeners = 1;
520 : }
521 :
522 413658 : talloc_set_destructor(msg, imessaging_context_destructor);
523 :
524 : /* create the messaging directory if needed */
525 :
526 413658 : lock_dir = lpcfg_lock_directory(lp_ctx);
527 413658 : if (lock_dir == NULL) {
528 0 : goto fail;
529 : }
530 :
531 413658 : msg->sock_dir = lpcfg_private_path(msg, lp_ctx, "msg.sock");
532 413658 : if (msg->sock_dir == NULL) {
533 0 : goto fail;
534 : }
535 413658 : ok = directory_create_or_exist_strict(msg->sock_dir, geteuid(), 0700);
536 413658 : if (!ok) {
537 14 : goto fail;
538 : }
539 :
540 413644 : msg->lock_dir = lpcfg_lock_path(msg, lp_ctx, "msg.lock");
541 413644 : if (msg->lock_dir == NULL) {
542 0 : goto fail;
543 : }
544 413644 : ok = directory_create_or_exist_strict(msg->lock_dir, geteuid(), 0755);
545 413644 : if (!ok) {
546 0 : goto fail;
547 : }
548 :
549 413644 : msg->msg_dgm_ref = messaging_dgm_ref(
550 : msg, ev, &server_id.unique_id, msg->sock_dir, msg->lock_dir,
551 : imessaging_dgm_recv, msg, &ret);
552 :
553 413644 : if (msg->msg_dgm_ref == NULL) {
554 8 : goto fail;
555 : }
556 :
557 413636 : msg->server_id = server_id;
558 413636 : msg->idr = idr_init(msg);
559 413636 : if (msg->idr == NULL) {
560 0 : goto fail;
561 : }
562 :
563 413636 : msg->dispatch_tree = idr_init(msg);
564 413636 : if (msg->dispatch_tree == NULL) {
565 0 : goto fail;
566 : }
567 :
568 413636 : msg->start_time = timeval_current();
569 :
570 413636 : tdb_flags |= lpcfg_tdb_flags(lp_ctx, 0);
571 :
572 : /*
573 : * This context holds a destructor that cleans up any names
574 : * registered on this context on talloc_free()
575 : */
576 413636 : msg->names = server_id_db_init(msg, server_id, lock_dir, 0, tdb_flags);
577 413636 : if (msg->names == NULL) {
578 0 : goto fail;
579 : }
580 :
581 413636 : status = imessaging_register(msg, NULL, MSG_PING, ping_message);
582 413636 : if (!NT_STATUS_IS_OK(status)) {
583 0 : goto fail;
584 : }
585 413636 : status = imessaging_register(msg, NULL, MSG_REQ_POOL_USAGE,
586 : pool_message);
587 413636 : if (!NT_STATUS_IS_OK(status)) {
588 0 : goto fail;
589 : }
590 413636 : status = imessaging_register(msg, NULL, MSG_IRPC, irpc_handler);
591 413636 : if (!NT_STATUS_IS_OK(status)) {
592 0 : goto fail;
593 : }
594 413636 : status = imessaging_register(msg, NULL, MSG_REQ_RINGBUF_LOG,
595 : ringbuf_log_msg);
596 413636 : if (!NT_STATUS_IS_OK(status)) {
597 0 : goto fail;
598 : }
599 413636 : status = imessaging_register(msg, NULL, MSG_DEBUG,
600 : debug_imessage);
601 413636 : if (!NT_STATUS_IS_OK(status)) {
602 0 : goto fail;
603 : }
604 413636 : status = imessaging_register(msg, NULL, MSG_REQ_DEBUGLEVEL,
605 : debuglevel_imessage);
606 413636 : if (!NT_STATUS_IS_OK(status)) {
607 0 : goto fail;
608 : }
609 413636 : status = IRPC_REGISTER(msg, irpc, IRPC_UPTIME, irpc_uptime, msg);
610 413636 : if (!NT_STATUS_IS_OK(status)) {
611 0 : goto fail;
612 : }
613 : #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
614 : /*
615 : * Register handlers for messages specific to developer and
616 : * self test builds
617 : */
618 413636 : status = imessaging_register_extra_handlers(msg);
619 413636 : if (!NT_STATUS_IS_OK(status)) {
620 0 : goto fail;
621 : }
622 : #endif /* defined(DEVELOPER) || defined(ENABLE_SELFTEST) */
623 :
624 413636 : DLIST_ADD(msg_ctxs, msg);
625 :
626 396556 : return msg;
627 22 : fail:
628 22 : talloc_free(msg);
629 22 : return NULL;
630 : }
631 :
632 : /*
633 : create the listening socket and setup the dispatcher
634 : */
635 130494 : struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
636 : struct loadparm_context *lp_ctx,
637 : struct server_id server_id,
638 : struct tevent_context *ev)
639 : {
640 130494 : bool discard_incoming = false;
641 130494 : return imessaging_init_internal(mem_ctx,
642 : discard_incoming,
643 : lp_ctx,
644 : server_id,
645 : ev);
646 : }
647 :
648 283164 : struct imessaging_context *imessaging_init_discard_incoming(
649 : TALLOC_CTX *mem_ctx,
650 : struct loadparm_context *lp_ctx,
651 : struct server_id server_id,
652 : struct tevent_context *ev)
653 : {
654 283164 : bool discard_incoming = true;
655 283164 : return imessaging_init_internal(mem_ctx,
656 : discard_incoming,
657 : lp_ctx,
658 : server_id,
659 : ev);
660 : }
661 :
662 : struct imessaging_post_state {
663 : struct imessaging_context *msg_ctx;
664 : struct imessaging_post_state **busy_ref;
665 : size_t buf_len;
666 : uint8_t buf[];
667 : };
668 :
669 3140 : static int imessaging_post_state_destructor(struct imessaging_post_state *state)
670 : {
671 3140 : if (state->busy_ref != NULL) {
672 0 : *state->busy_ref = NULL;
673 0 : state->busy_ref = NULL;
674 : }
675 3140 : return 0;
676 : }
677 :
678 8 : static void imessaging_post_handler(struct tevent_context *ev,
679 : struct tevent_immediate *ti,
680 : void *private_data)
681 : {
682 8 : struct imessaging_post_state *state = talloc_get_type_abort(
683 : private_data, struct imessaging_post_state);
684 :
685 8 : if (state == NULL) {
686 0 : return;
687 : }
688 :
689 : /*
690 : * In usecases like using messaging_client_init() with irpc processing
691 : * we may free the imessaging_context during the messaging handler.
692 : * imessaging_post_state is a child of imessaging_context and
693 : * might be implicitly free'ed before the explicit TALLOC_FREE(state).
694 : *
695 : * The busy_ref pointer makes sure the destructor clears
696 : * the local 'state' variable.
697 : */
698 :
699 8 : SMB_ASSERT(state->busy_ref == NULL);
700 8 : state->busy_ref = &state;
701 :
702 8 : imessaging_dgm_recv(ev, state->buf, state->buf_len, NULL, 0,
703 8 : state->msg_ctx);
704 :
705 8 : state->busy_ref = NULL;
706 8 : TALLOC_FREE(state);
707 : }
708 :
709 3140 : static int imessaging_post_self(struct imessaging_context *msg,
710 : const uint8_t *buf, size_t buf_len)
711 : {
712 0 : struct tevent_immediate *ti;
713 0 : struct imessaging_post_state *state;
714 :
715 3140 : state = talloc_size(
716 : msg, offsetof(struct imessaging_post_state, buf) + buf_len);
717 3140 : if (state == NULL) {
718 0 : return ENOMEM;
719 : }
720 3140 : talloc_set_name_const(state, "struct imessaging_post_state");
721 :
722 3140 : talloc_set_destructor(state, imessaging_post_state_destructor);
723 :
724 3140 : ti = tevent_create_immediate(state);
725 3140 : if (ti == NULL) {
726 0 : TALLOC_FREE(state);
727 0 : return ENOMEM;
728 : }
729 :
730 3140 : state->msg_ctx = msg;
731 3140 : state->busy_ref = NULL;
732 3140 : state->buf_len = buf_len;
733 3140 : memcpy(state->buf, buf, buf_len);
734 :
735 3140 : tevent_schedule_immediate(ti, msg->ev, imessaging_post_handler,
736 0 : state);
737 :
738 3140 : return 0;
739 : }
740 :
741 365203 : static void imessaging_dgm_recv(struct tevent_context *ev,
742 : const uint8_t *buf, size_t buf_len,
743 : int *fds, size_t num_fds,
744 : void *private_data)
745 : {
746 365203 : struct imessaging_context *msg = talloc_get_type_abort(
747 : private_data, struct imessaging_context);
748 132324 : uint32_t msg_type;
749 132324 : struct server_id src, dst;
750 132324 : struct server_id_buf srcbuf, dstbuf;
751 132324 : DATA_BLOB data;
752 :
753 365203 : if (buf_len < MESSAGE_HDR_LENGTH) {
754 : /* Invalid message, ignore */
755 120014 : return;
756 : }
757 :
758 365203 : if (msg->num_incoming_listeners == 0) {
759 585 : struct server_id_buf selfbuf;
760 :
761 116874 : message_hdr_get(&msg_type, &src, &dst, buf);
762 :
763 116874 : DBG_DEBUG("not listening - discarding message from "
764 : "src[%s] to dst[%s] (self[%s]) type=0x%x "
765 : "on %s event context\n",
766 : server_id_str_buf(src, &srcbuf),
767 : server_id_str_buf(dst, &dstbuf),
768 : server_id_str_buf(msg->server_id, &selfbuf),
769 : (unsigned)msg_type,
770 : (ev != msg->ev) ? "different" : "main");
771 116874 : return;
772 : }
773 :
774 248329 : if (ev != msg->ev) {
775 0 : int ret;
776 3140 : ret = imessaging_post_self(msg, buf, buf_len);
777 3140 : if (ret != 0) {
778 0 : DBG_WARNING("imessaging_post_self failed: %s\n",
779 : strerror(ret));
780 : }
781 3140 : return;
782 : }
783 :
784 245189 : message_hdr_get(&msg_type, &src, &dst, buf);
785 :
786 245189 : data.data = discard_const_p(uint8_t, buf + MESSAGE_HDR_LENGTH);
787 245189 : data.length = buf_len - MESSAGE_HDR_LENGTH;
788 :
789 245189 : if ((cluster_id_equal(&dst, &msg->server_id)) ||
790 178842 : ((dst.task_id == 0) && (msg->server_id.pid == 0))) {
791 66347 : struct dispatch_fn *d, *next;
792 :
793 96452 : DEBUG(10, ("%s: dst %s matches my id: %s, type=0x%x\n",
794 : __func__,
795 : server_id_str_buf(dst, &dstbuf),
796 : server_id_str_buf(msg->server_id, &srcbuf),
797 : (unsigned)msg_type));
798 :
799 96452 : d = imessaging_find_dispatch(msg, msg_type);
800 :
801 254161 : for (; d; d = next) {
802 91362 : next = d->next;
803 91362 : d->fn(msg,
804 : d->private_data,
805 : d->msg_type,
806 : src,
807 : num_fds,
808 : fds,
809 : &data);
810 : }
811 : } else {
812 148737 : DEBUG(10, ("%s: Ignoring type=0x%x dst %s, I am %s, \n",
813 : __func__, (unsigned)msg_type,
814 : server_id_str_buf(dst, &dstbuf),
815 : server_id_str_buf(msg->server_id, &srcbuf)));
816 : }
817 : }
818 :
819 : /*
820 : A hack, for the short term until we get 'client only' messaging in place
821 : */
822 243137 : struct imessaging_context *imessaging_client_init(TALLOC_CTX *mem_ctx,
823 : struct loadparm_context *lp_ctx,
824 : struct tevent_context *ev)
825 : {
826 497981 : struct server_id id = {
827 243137 : .pid = getpid(),
828 243137 : .task_id = generate_random(),
829 : .vnn = NONCLUSTER_VNN,
830 :
831 : /* This is because we are not in the s3 serverid database */
832 : .unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY,
833 : };
834 :
835 243137 : return imessaging_init_discard_incoming(mem_ctx, lp_ctx, id, ev);
836 : }
837 :
838 : /*
839 : a list of registered irpc server functions
840 : */
841 : struct irpc_list {
842 : struct irpc_list *next, *prev;
843 : struct GUID uuid;
844 : const struct ndr_interface_table *table;
845 : int callnum;
846 : irpc_function_t fn;
847 : void *private_data;
848 : };
849 :
850 :
851 : /*
852 : register a irpc server function
853 : */
854 417663 : NTSTATUS irpc_register(struct imessaging_context *msg_ctx,
855 : const struct ndr_interface_table *table,
856 : int callnum, irpc_function_t fn, void *private_data)
857 : {
858 17124 : struct irpc_list *irpc;
859 :
860 : /* override an existing handler, if any */
861 424640 : for (irpc=msg_ctx->irpc; irpc; irpc=irpc->next) {
862 6977 : if (irpc->table == table && irpc->callnum == callnum) {
863 0 : break;
864 : }
865 : }
866 417663 : if (irpc == NULL) {
867 417663 : irpc = talloc(msg_ctx, struct irpc_list);
868 417663 : NT_STATUS_HAVE_NO_MEMORY(irpc);
869 417663 : DLIST_ADD(msg_ctx->irpc, irpc);
870 : }
871 :
872 417663 : irpc->table = table;
873 417663 : irpc->callnum = callnum;
874 417663 : irpc->fn = fn;
875 417663 : irpc->private_data = private_data;
876 417663 : irpc->uuid = irpc->table->syntax_id.uuid;
877 :
878 417663 : return NT_STATUS_OK;
879 : }
880 :
881 :
882 : /*
883 : handle an incoming irpc reply message
884 : */
885 22996 : static void irpc_handler_reply(struct imessaging_context *msg_ctx, struct irpc_message *m)
886 : {
887 16556 : struct irpc_request *irpc;
888 :
889 22996 : irpc = (struct irpc_request *)idr_find(msg_ctx->idr, m->header.callid);
890 22996 : if (irpc == NULL) return;
891 :
892 20851 : irpc->incoming.handler(irpc, m);
893 : }
894 :
895 : /*
896 : send a irpc reply
897 : */
898 21810 : NTSTATUS irpc_send_reply(struct irpc_message *m, NTSTATUS status)
899 : {
900 16534 : struct ndr_push *push;
901 16534 : DATA_BLOB packet;
902 16534 : enum ndr_err_code ndr_err;
903 :
904 21810 : m->header.status = status;
905 :
906 : /* setup the reply */
907 21810 : push = ndr_push_init_ctx(m->ndr);
908 21810 : if (push == NULL) {
909 0 : status = NT_STATUS_NO_MEMORY;
910 0 : goto failed;
911 : }
912 :
913 21810 : m->header.flags |= IRPC_FLAG_REPLY;
914 21810 : m->header.creds.token= NULL;
915 :
916 : /* construct the packet */
917 21810 : ndr_err = ndr_push_irpc_header(push, NDR_SCALARS|NDR_BUFFERS, &m->header);
918 21810 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
919 0 : status = ndr_map_error2ntstatus(ndr_err);
920 0 : goto failed;
921 : }
922 :
923 21810 : ndr_err = m->irpc->table->calls[m->irpc->callnum].ndr_push(push, NDR_OUT, m->data);
924 21810 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
925 0 : status = ndr_map_error2ntstatus(ndr_err);
926 0 : goto failed;
927 : }
928 :
929 : /* send the reply message */
930 21810 : packet = ndr_push_blob(push);
931 21810 : status = imessaging_send(m->msg_ctx, m->from, MSG_IRPC, &packet);
932 21810 : if (!NT_STATUS_IS_OK(status)) goto failed;
933 :
934 21810 : failed:
935 21810 : talloc_free(m);
936 21810 : return status;
937 : }
938 :
939 : /*
940 : handle an incoming irpc request message
941 : */
942 29179 : static void irpc_handler_request(struct imessaging_context *msg_ctx,
943 : struct irpc_message *m)
944 : {
945 16534 : struct irpc_list *i;
946 16534 : void *r;
947 16534 : enum ndr_err_code ndr_err;
948 :
949 77098 : for (i=msg_ctx->irpc; i; i=i->next) {
950 71578 : if (GUID_equal(&i->uuid, &m->header.uuid) &&
951 58402 : i->table->syntax_id.if_version == m->header.if_version &&
952 58402 : i->callnum == m->header.callnum) {
953 7125 : break;
954 : }
955 : }
956 :
957 29179 : if (i == NULL) {
958 : /* no registered handler for this message */
959 5520 : talloc_free(m);
960 5520 : return;
961 : }
962 :
963 : /* allocate space for the structure */
964 23659 : r = talloc_zero_size(m->ndr, i->table->calls[m->header.callnum].struct_size);
965 23659 : if (r == NULL) goto failed;
966 :
967 23659 : m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
968 :
969 : /* parse the request data */
970 23659 : ndr_err = i->table->calls[i->callnum].ndr_pull(m->ndr, NDR_IN, r);
971 23659 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
972 :
973 : /* make the call */
974 23659 : m->private_data= i->private_data;
975 23659 : m->defer_reply = false;
976 23659 : m->no_reply = false;
977 23659 : m->msg_ctx = msg_ctx;
978 23659 : m->irpc = i;
979 23659 : m->data = r;
980 :
981 23659 : m->header.status = i->fn(m, r);
982 :
983 23659 : if (m->no_reply) {
984 : /* the server function won't ever be replying to this request */
985 1849 : talloc_free(m);
986 1849 : return;
987 : }
988 :
989 21810 : if (m->defer_reply) {
990 : /* the server function has asked to defer the reply to later */
991 1026 : talloc_steal(msg_ctx, m);
992 1026 : return;
993 : }
994 :
995 20784 : irpc_send_reply(m, m->header.status);
996 20784 : return;
997 :
998 0 : failed:
999 0 : talloc_free(m);
1000 : }
1001 :
1002 : /*
1003 : handle an incoming irpc message
1004 : */
1005 52175 : static void irpc_handler(struct imessaging_context *msg_ctx,
1006 : void *private_data,
1007 : uint32_t msg_type,
1008 : struct server_id src,
1009 : size_t num_fds,
1010 : int *fds,
1011 : DATA_BLOB *packet)
1012 : {
1013 33090 : struct irpc_message *m;
1014 33090 : enum ndr_err_code ndr_err;
1015 :
1016 52175 : if (num_fds != 0) {
1017 0 : DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
1018 0 : return;
1019 : }
1020 :
1021 52175 : m = talloc(msg_ctx, struct irpc_message);
1022 52175 : if (m == NULL) goto failed;
1023 :
1024 52175 : m->from = src;
1025 :
1026 52175 : m->ndr = ndr_pull_init_blob(packet, m);
1027 52175 : if (m->ndr == NULL) goto failed;
1028 :
1029 52175 : m->ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
1030 :
1031 52175 : ndr_err = ndr_pull_irpc_header(m->ndr, NDR_BUFFERS|NDR_SCALARS, &m->header);
1032 52175 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
1033 :
1034 52175 : if (m->header.flags & IRPC_FLAG_REPLY) {
1035 22996 : irpc_handler_reply(msg_ctx, m);
1036 : } else {
1037 29179 : irpc_handler_request(msg_ctx, m);
1038 : }
1039 19085 : return;
1040 :
1041 0 : failed:
1042 0 : talloc_free(m);
1043 : }
1044 :
1045 :
1046 : /*
1047 : destroy a irpc request
1048 : */
1049 25515 : static int irpc_destructor(struct irpc_request *irpc)
1050 : {
1051 25515 : if (irpc->callid != -1) {
1052 25515 : DLIST_REMOVE(irpc->msg_ctx->requests, irpc);
1053 25515 : idr_remove(irpc->msg_ctx->idr, irpc->callid);
1054 25515 : if (irpc->msg_ctx->discard_incoming) {
1055 2825 : SMB_ASSERT(irpc->msg_ctx->num_incoming_listeners > 0);
1056 : } else {
1057 22690 : SMB_ASSERT(irpc->msg_ctx->num_incoming_listeners > 1);
1058 : }
1059 25515 : irpc->msg_ctx->num_incoming_listeners -= 1;
1060 25515 : irpc->callid = -1;
1061 : }
1062 :
1063 25515 : return 0;
1064 : }
1065 :
1066 : /*
1067 : add a string name that this irpc server can be called on
1068 :
1069 : It will be removed from the DB either via irpc_remove_name or on
1070 : talloc_free(msg_ctx->names).
1071 : */
1072 31980 : NTSTATUS irpc_add_name(struct imessaging_context *msg_ctx, const char *name)
1073 : {
1074 198 : int ret;
1075 :
1076 31980 : ret = server_id_db_add(msg_ctx->names, name);
1077 31980 : if (ret != 0) {
1078 0 : return map_nt_error_from_unix_common(ret);
1079 : }
1080 31980 : return NT_STATUS_OK;
1081 : }
1082 :
1083 22275 : static int all_servers_func(const char *name, unsigned num_servers,
1084 : const struct server_id *servers,
1085 : void *private_data)
1086 : {
1087 22275 : struct irpc_name_records *name_records = talloc_get_type(
1088 : private_data, struct irpc_name_records);
1089 1150 : struct irpc_name_record *name_record;
1090 1150 : uint32_t i;
1091 :
1092 1150 : name_records->names
1093 22275 : = talloc_realloc(name_records, name_records->names,
1094 : struct irpc_name_record *, name_records->num_records+1);
1095 22275 : if (!name_records->names) {
1096 0 : return -1;
1097 : }
1098 :
1099 23425 : name_records->names[name_records->num_records] = name_record
1100 22275 : = talloc(name_records->names,
1101 : struct irpc_name_record);
1102 22275 : if (!name_record) {
1103 0 : return -1;
1104 : }
1105 :
1106 22275 : name_records->num_records++;
1107 :
1108 22275 : name_record->name = talloc_strdup(name_record, name);
1109 22275 : if (!name_record->name) {
1110 0 : return -1;
1111 : }
1112 :
1113 22275 : name_record->count = num_servers;
1114 22275 : name_record->ids = talloc_array(name_record, struct server_id,
1115 : num_servers);
1116 22275 : if (name_record->ids == NULL) {
1117 0 : return -1;
1118 : }
1119 48797 : for (i=0;i<name_record->count;i++) {
1120 26522 : name_record->ids[i] = servers[i];
1121 : }
1122 21125 : return 0;
1123 : }
1124 :
1125 : /*
1126 : return a list of server ids for a server name
1127 : */
1128 1031 : struct irpc_name_records *irpc_all_servers(struct imessaging_context *msg_ctx,
1129 : TALLOC_CTX *mem_ctx)
1130 : {
1131 60 : int ret;
1132 1031 : struct irpc_name_records *name_records = talloc_zero(mem_ctx, struct irpc_name_records);
1133 1031 : if (name_records == NULL) {
1134 0 : return NULL;
1135 : }
1136 :
1137 1031 : ret = server_id_db_traverse_read(msg_ctx->names, all_servers_func,
1138 : name_records);
1139 1031 : if (ret == -1) {
1140 0 : TALLOC_FREE(name_records);
1141 0 : return NULL;
1142 : }
1143 :
1144 971 : return name_records;
1145 : }
1146 :
1147 : /*
1148 : remove a name from a messaging context
1149 : */
1150 58 : void irpc_remove_name(struct imessaging_context *msg_ctx, const char *name)
1151 : {
1152 58 : server_id_db_remove(msg_ctx->names, name);
1153 58 : }
1154 :
1155 2 : struct server_id imessaging_get_server_id(struct imessaging_context *msg_ctx)
1156 : {
1157 2 : return msg_ctx->server_id;
1158 : }
1159 :
1160 : struct irpc_bh_state {
1161 : struct imessaging_context *msg_ctx;
1162 : struct server_id server_id;
1163 : const struct ndr_interface_table *table;
1164 : uint32_t timeout;
1165 : struct security_token *token;
1166 : };
1167 :
1168 25515 : static bool irpc_bh_is_connected(struct dcerpc_binding_handle *h)
1169 : {
1170 25515 : struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
1171 : struct irpc_bh_state);
1172 :
1173 25515 : if (!hs->msg_ctx) {
1174 0 : return false;
1175 : }
1176 :
1177 8959 : return true;
1178 : }
1179 :
1180 4275 : static uint32_t irpc_bh_set_timeout(struct dcerpc_binding_handle *h,
1181 : uint32_t timeout)
1182 : {
1183 4275 : struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
1184 : struct irpc_bh_state);
1185 4275 : uint32_t old = hs->timeout;
1186 :
1187 4275 : hs->timeout = timeout;
1188 :
1189 4275 : return old;
1190 : }
1191 :
1192 : struct irpc_bh_raw_call_state {
1193 : struct irpc_request *irpc;
1194 : uint32_t opnum;
1195 : DATA_BLOB in_data;
1196 : DATA_BLOB in_packet;
1197 : DATA_BLOB out_data;
1198 : };
1199 :
1200 : static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
1201 : struct irpc_message *m);
1202 :
1203 25515 : static struct tevent_req *irpc_bh_raw_call_send(TALLOC_CTX *mem_ctx,
1204 : struct tevent_context *ev,
1205 : struct dcerpc_binding_handle *h,
1206 : const struct GUID *object,
1207 : uint32_t opnum,
1208 : uint32_t in_flags,
1209 : const uint8_t *in_data,
1210 : size_t in_length)
1211 : {
1212 16556 : struct irpc_bh_state *hs =
1213 25515 : dcerpc_binding_handle_data(h,
1214 : struct irpc_bh_state);
1215 16556 : struct tevent_req *req;
1216 16556 : struct irpc_bh_raw_call_state *state;
1217 16556 : bool ok;
1218 16556 : struct irpc_header header;
1219 16556 : struct ndr_push *ndr;
1220 16556 : NTSTATUS status;
1221 16556 : enum ndr_err_code ndr_err;
1222 :
1223 25515 : req = tevent_req_create(mem_ctx, &state,
1224 : struct irpc_bh_raw_call_state);
1225 25515 : if (req == NULL) {
1226 0 : return NULL;
1227 : }
1228 25515 : state->opnum = opnum;
1229 25515 : state->in_data.data = discard_const_p(uint8_t, in_data);
1230 25515 : state->in_data.length = in_length;
1231 :
1232 25515 : ok = irpc_bh_is_connected(h);
1233 25515 : if (!ok) {
1234 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
1235 0 : return tevent_req_post(req, ev);
1236 : }
1237 :
1238 25515 : state->irpc = talloc_zero(state, struct irpc_request);
1239 25515 : if (tevent_req_nomem(state->irpc, req)) {
1240 0 : return tevent_req_post(req, ev);
1241 : }
1242 :
1243 25515 : state->irpc->msg_ctx = hs->msg_ctx;
1244 34474 : state->irpc->callid = idr_get_new(hs->msg_ctx->idr,
1245 8959 : state->irpc, UINT16_MAX);
1246 25515 : if (state->irpc->callid == -1) {
1247 0 : tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
1248 0 : return tevent_req_post(req, ev);
1249 : }
1250 25515 : state->irpc->incoming.handler = irpc_bh_raw_call_incoming_handler;
1251 25515 : state->irpc->incoming.private_data = req;
1252 :
1253 : /* make sure we accept incoming messages */
1254 25515 : SMB_ASSERT(state->irpc->msg_ctx->num_incoming_listeners < UINT64_MAX);
1255 25515 : state->irpc->msg_ctx->num_incoming_listeners += 1;
1256 25515 : DLIST_ADD_END(state->irpc->msg_ctx->requests, state->irpc);
1257 25515 : talloc_set_destructor(state->irpc, irpc_destructor);
1258 :
1259 : /* setup the header */
1260 25515 : header.uuid = hs->table->syntax_id.uuid;
1261 :
1262 25515 : header.if_version = hs->table->syntax_id.if_version;
1263 25515 : header.callid = state->irpc->callid;
1264 25515 : header.callnum = state->opnum;
1265 25515 : header.flags = 0;
1266 25515 : header.status = NT_STATUS_OK;
1267 25515 : header.creds.token= hs->token;
1268 :
1269 : /* construct the irpc packet */
1270 25515 : ndr = ndr_push_init_ctx(state->irpc);
1271 25515 : if (tevent_req_nomem(ndr, req)) {
1272 0 : return tevent_req_post(req, ev);
1273 : }
1274 :
1275 25515 : ndr_err = ndr_push_irpc_header(ndr, NDR_SCALARS|NDR_BUFFERS, &header);
1276 25515 : status = ndr_map_error2ntstatus(ndr_err);
1277 25515 : if (!NT_STATUS_IS_OK(status)) {
1278 0 : tevent_req_nterror(req, status);
1279 0 : return tevent_req_post(req, ev);
1280 : }
1281 :
1282 25515 : ndr_err = ndr_push_bytes(ndr, in_data, in_length);
1283 25515 : status = ndr_map_error2ntstatus(ndr_err);
1284 25515 : if (!NT_STATUS_IS_OK(status)) {
1285 0 : tevent_req_nterror(req, status);
1286 0 : return tevent_req_post(req, ev);
1287 : }
1288 :
1289 : /* and send it */
1290 25515 : state->in_packet = ndr_push_blob(ndr);
1291 42071 : status = imessaging_send(hs->msg_ctx, hs->server_id,
1292 25515 : MSG_IRPC, &state->in_packet);
1293 25515 : if (!NT_STATUS_IS_OK(status)) {
1294 0 : tevent_req_nterror(req, status);
1295 0 : return tevent_req_post(req, ev);
1296 : }
1297 :
1298 25515 : if (hs->timeout != IRPC_CALL_TIMEOUT_INF) {
1299 : /* set timeout-callback in case caller wants that */
1300 24549 : ok = tevent_req_set_endtime(req, ev, timeval_current_ofs(hs->timeout, 0));
1301 24549 : if (!ok) {
1302 0 : return tevent_req_post(req, ev);
1303 : }
1304 : }
1305 :
1306 8959 : return req;
1307 : }
1308 :
1309 20851 : static void irpc_bh_raw_call_incoming_handler(struct irpc_request *irpc,
1310 : struct irpc_message *m)
1311 : {
1312 16556 : struct tevent_req *req =
1313 20851 : talloc_get_type_abort(irpc->incoming.private_data,
1314 : struct tevent_req);
1315 16556 : struct irpc_bh_raw_call_state *state =
1316 20851 : tevent_req_data(req,
1317 : struct irpc_bh_raw_call_state);
1318 :
1319 20851 : talloc_steal(state, m);
1320 :
1321 20851 : if (!NT_STATUS_IS_OK(m->header.status)) {
1322 224 : tevent_req_nterror(req, m->header.status);
1323 224 : return;
1324 : }
1325 :
1326 20627 : state->out_data = data_blob_talloc(state,
1327 : m->ndr->data + m->ndr->offset,
1328 : m->ndr->data_size - m->ndr->offset);
1329 20627 : if ((m->ndr->data_size - m->ndr->offset) > 0 && !state->out_data.data) {
1330 0 : tevent_req_oom(req);
1331 0 : return;
1332 : }
1333 :
1334 20627 : tevent_req_done(req);
1335 : }
1336 :
1337 20851 : static NTSTATUS irpc_bh_raw_call_recv(struct tevent_req *req,
1338 : TALLOC_CTX *mem_ctx,
1339 : uint8_t **out_data,
1340 : size_t *out_length,
1341 : uint32_t *out_flags)
1342 : {
1343 16556 : struct irpc_bh_raw_call_state *state =
1344 20851 : tevent_req_data(req,
1345 : struct irpc_bh_raw_call_state);
1346 16556 : NTSTATUS status;
1347 :
1348 20851 : if (tevent_req_is_nterror(req, &status)) {
1349 224 : tevent_req_received(req);
1350 224 : return status;
1351 : }
1352 :
1353 20627 : *out_data = talloc_move(mem_ctx, &state->out_data.data);
1354 20627 : *out_length = state->out_data.length;
1355 20627 : *out_flags = 0;
1356 20627 : tevent_req_received(req);
1357 20627 : return NT_STATUS_OK;
1358 : }
1359 :
1360 : struct irpc_bh_disconnect_state {
1361 : uint8_t _dummy;
1362 : };
1363 :
1364 0 : static struct tevent_req *irpc_bh_disconnect_send(TALLOC_CTX *mem_ctx,
1365 : struct tevent_context *ev,
1366 : struct dcerpc_binding_handle *h)
1367 : {
1368 0 : struct irpc_bh_state *hs = dcerpc_binding_handle_data(h,
1369 : struct irpc_bh_state);
1370 0 : struct tevent_req *req;
1371 0 : struct irpc_bh_disconnect_state *state;
1372 0 : bool ok;
1373 :
1374 0 : req = tevent_req_create(mem_ctx, &state,
1375 : struct irpc_bh_disconnect_state);
1376 0 : if (req == NULL) {
1377 0 : return NULL;
1378 : }
1379 :
1380 0 : ok = irpc_bh_is_connected(h);
1381 0 : if (!ok) {
1382 0 : tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
1383 0 : return tevent_req_post(req, ev);
1384 : }
1385 :
1386 0 : hs->msg_ctx = NULL;
1387 :
1388 0 : tevent_req_done(req);
1389 0 : return tevent_req_post(req, ev);
1390 : }
1391 :
1392 0 : static NTSTATUS irpc_bh_disconnect_recv(struct tevent_req *req)
1393 : {
1394 0 : NTSTATUS status;
1395 :
1396 0 : if (tevent_req_is_nterror(req, &status)) {
1397 0 : tevent_req_received(req);
1398 0 : return status;
1399 : }
1400 :
1401 0 : tevent_req_received(req);
1402 0 : return NT_STATUS_OK;
1403 : }
1404 :
1405 25515 : static bool irpc_bh_ref_alloc(struct dcerpc_binding_handle *h)
1406 : {
1407 25515 : return true;
1408 : }
1409 :
1410 46142 : static void irpc_bh_do_ndr_print(struct dcerpc_binding_handle *h,
1411 : ndr_flags_type ndr_flags,
1412 : const void *_struct_ptr,
1413 : const struct ndr_interface_call *call)
1414 : {
1415 46142 : void *struct_ptr = discard_const(_struct_ptr);
1416 46142 : bool print_in = false;
1417 46142 : bool print_out = false;
1418 :
1419 46142 : if (DEBUGLEVEL >= 11) {
1420 0 : print_in = true;
1421 0 : print_out = true;
1422 : }
1423 :
1424 46142 : if (ndr_flags & NDR_IN) {
1425 25515 : if (print_in) {
1426 0 : ndr_print_function_debug(call->ndr_print,
1427 0 : call->name,
1428 : ndr_flags,
1429 : struct_ptr);
1430 : }
1431 : }
1432 46142 : if (ndr_flags & NDR_OUT) {
1433 20627 : if (print_out) {
1434 0 : ndr_print_function_debug(call->ndr_print,
1435 0 : call->name,
1436 : ndr_flags,
1437 : struct_ptr);
1438 : }
1439 : }
1440 46142 : }
1441 :
1442 : static const struct dcerpc_binding_handle_ops irpc_bh_ops = {
1443 : .name = "wbint",
1444 : .is_connected = irpc_bh_is_connected,
1445 : .set_timeout = irpc_bh_set_timeout,
1446 : .raw_call_send = irpc_bh_raw_call_send,
1447 : .raw_call_recv = irpc_bh_raw_call_recv,
1448 : .disconnect_send = irpc_bh_disconnect_send,
1449 : .disconnect_recv = irpc_bh_disconnect_recv,
1450 :
1451 : .ref_alloc = irpc_bh_ref_alloc,
1452 : .do_ndr_print = irpc_bh_do_ndr_print,
1453 : };
1454 :
1455 : /* initialise a irpc binding handle */
1456 8982 : struct dcerpc_binding_handle *irpc_binding_handle(TALLOC_CTX *mem_ctx,
1457 : struct imessaging_context *msg_ctx,
1458 : struct server_id server_id,
1459 : const struct ndr_interface_table *table)
1460 : {
1461 29 : struct dcerpc_binding_handle *h;
1462 29 : struct irpc_bh_state *hs;
1463 :
1464 8982 : h = dcerpc_binding_handle_create(mem_ctx,
1465 : &irpc_bh_ops,
1466 : NULL,
1467 : table,
1468 : &hs,
1469 : struct irpc_bh_state,
1470 : __location__);
1471 8982 : if (h == NULL) {
1472 0 : return NULL;
1473 : }
1474 8982 : hs->msg_ctx = msg_ctx;
1475 8982 : hs->server_id = server_id;
1476 8982 : hs->table = table;
1477 8982 : hs->timeout = IRPC_CALL_TIMEOUT;
1478 :
1479 8982 : return h;
1480 : }
1481 :
1482 9225 : struct dcerpc_binding_handle *irpc_binding_handle_by_name(TALLOC_CTX *mem_ctx,
1483 : struct imessaging_context *msg_ctx,
1484 : const char *dest_task,
1485 : const struct ndr_interface_table *table)
1486 : {
1487 47 : struct dcerpc_binding_handle *h;
1488 47 : unsigned num_sids;
1489 47 : struct server_id *sids;
1490 47 : struct server_id sid;
1491 47 : NTSTATUS status;
1492 :
1493 : /* find the server task */
1494 :
1495 9225 : status = irpc_servers_byname(msg_ctx, mem_ctx, dest_task,
1496 : &num_sids, &sids);
1497 9225 : if (!NT_STATUS_IS_OK(status)) {
1498 250 : errno = EADDRNOTAVAIL;
1499 250 : return NULL;
1500 : }
1501 8975 : sid = sids[0];
1502 8975 : talloc_free(sids);
1503 :
1504 8975 : h = irpc_binding_handle(mem_ctx, msg_ctx,
1505 : sid, table);
1506 8975 : if (h == NULL) {
1507 0 : return NULL;
1508 : }
1509 :
1510 8953 : return h;
1511 : }
1512 :
1513 2113 : void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle *h,
1514 : struct security_token *token)
1515 : {
1516 0 : struct irpc_bh_state *hs =
1517 2113 : dcerpc_binding_handle_data(h,
1518 : struct irpc_bh_state);
1519 :
1520 2113 : hs->token = token;
1521 2113 : }
|