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