2 Unix SMB/CIFS implementation.
4 Samba internal messaging functions
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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/>.
23 #include "lib/events/events.h"
24 #include "system/filesys.h"
25 #include "messaging/messaging.h"
26 #include "../lib/util/dlinklist.h"
27 #include "lib/socket/socket.h"
28 #include "librpc/gen_ndr/ndr_irpc.h"
29 #include "lib/messaging/irpc.h"
30 #include "../lib/util/unix_privs.h"
31 #include "librpc/rpc/dcerpc.h"
32 #include "cluster/cluster.h"
33 #include "../lib/util/tevent_ntstatus.h"
34 #include "lib/param/param.h"
35 #include "lib/util/server_id_db.h"
36 #include "lib/util/talloc_report.h"
37 #include "../source3/lib/messages_dgm.h"
38 #include "../source3/lib/messages_dgm_ref.h"
39 #include "../source3/lib/messages_util.h"
42 /* change the message version with any incompatible changes in the protocol */
43 #define IMESSAGING_VERSION 1
49 struct imessaging_context
*msg_ctx
;
52 void (*handler
)(struct irpc_request
*irpc
, struct irpc_message
*m
);
57 struct imessaging_context
{
58 struct imessaging_context
*prev
, *next
;
59 struct server_id server_id
;
62 struct dispatch_fn
**dispatch
;
64 struct idr_context
*dispatch_tree
;
65 struct irpc_list
*irpc
;
66 struct idr_context
*idr
;
67 struct server_id_db
*names
;
68 struct timeval start_time
;
72 /* we have a linked list of dispatch handlers for each msg_type that
73 this messaging server can deal with */
75 struct dispatch_fn
*next
, *prev
;
81 /* an individual message */
83 static void irpc_handler(struct imessaging_context
*, void *,
84 uint32_t, struct server_id
, DATA_BLOB
*);
88 A useful function for testing the message system.
90 static void ping_message(struct imessaging_context
*msg
, void *private_data
,
91 uint32_t msg_type
, struct server_id src
, DATA_BLOB
*data
)
93 struct server_id_buf idbuf
;
94 DEBUG(1,("INFO: Received PING message from server %s [%.*s]\n",
95 server_id_str_buf(src
, &idbuf
), (int)data
->length
,
96 data
->data
?(const char *)data
->data
:""));
97 imessaging_send(msg
, src
, MSG_PONG
, data
);
100 static void pool_message(struct imessaging_context
*msg
, void *private_data
,
101 uint32_t msg_type
, struct server_id src
,
106 report
= talloc_report_str(msg
, NULL
);
108 if (report
!= NULL
) {
109 DATA_BLOB blob
= { .data
= (uint8_t *)report
,
110 .length
= talloc_get_size(report
) - 1};
111 imessaging_send(msg
, src
, MSG_POOL_USAGE
, &blob
);
117 return uptime of messaging server via irpc
119 static NTSTATUS
irpc_uptime(struct irpc_message
*msg
,
120 struct irpc_uptime
*r
)
122 struct imessaging_context
*ctx
= talloc_get_type(msg
->private_data
, struct imessaging_context
);
123 *r
->out
.start_time
= timeval_to_nttime(&ctx
->start_time
);
127 static struct dispatch_fn
*imessaging_find_dispatch(
128 struct imessaging_context
*msg
, uint32_t msg_type
)
130 /* temporary IDs use an idtree, the rest use a array of pointers */
131 if (msg_type
>= MSG_TMP_BASE
) {
132 return (struct dispatch_fn
*)idr_find(msg
->dispatch_tree
,
135 if (msg_type
< msg
->num_types
) {
136 return msg
->dispatch
[msg_type
];
142 Register a dispatch function for a particular message type.
144 NTSTATUS
imessaging_register(struct imessaging_context
*msg
, void *private_data
,
145 uint32_t msg_type
, msg_callback_t fn
)
147 struct dispatch_fn
*d
;
149 /* possibly expand dispatch array */
150 if (msg_type
>= msg
->num_types
) {
151 struct dispatch_fn
**dp
;
153 dp
= talloc_realloc(msg
, msg
->dispatch
, struct dispatch_fn
*, msg_type
+1);
154 NT_STATUS_HAVE_NO_MEMORY(dp
);
156 for (i
=msg
->num_types
;i
<=msg_type
;i
++) {
157 msg
->dispatch
[i
] = NULL
;
159 msg
->num_types
= msg_type
+1;
162 d
= talloc_zero(msg
->dispatch
, struct dispatch_fn
);
163 NT_STATUS_HAVE_NO_MEMORY(d
);
164 d
->msg_type
= msg_type
;
165 d
->private_data
= private_data
;
168 DLIST_ADD(msg
->dispatch
[msg_type
], d
);
174 register a temporary message handler. The msg_type is allocated
177 NTSTATUS
imessaging_register_tmp(struct imessaging_context
*msg
, void *private_data
,
178 msg_callback_t fn
, uint32_t *msg_type
)
180 struct dispatch_fn
*d
;
183 d
= talloc_zero(msg
->dispatch
, struct dispatch_fn
);
184 NT_STATUS_HAVE_NO_MEMORY(d
);
185 d
->private_data
= private_data
;
188 id
= idr_get_new_above(msg
->dispatch_tree
, d
, MSG_TMP_BASE
, UINT16_MAX
);
191 return NT_STATUS_TOO_MANY_CONTEXT_IDS
;
194 d
->msg_type
= (uint32_t)id
;
195 (*msg_type
) = d
->msg_type
;
201 De-register the function for a particular message type.
203 void imessaging_deregister(struct imessaging_context
*msg
, uint32_t msg_type
, void *private_data
)
205 struct dispatch_fn
*d
, *next
;
207 if (msg_type
>= msg
->num_types
) {
208 d
= (struct dispatch_fn
*)idr_find(msg
->dispatch_tree
,
211 idr_remove(msg
->dispatch_tree
, msg_type
);
216 for (d
= msg
->dispatch
[msg_type
]; d
; d
= next
) {
218 if (d
->private_data
== private_data
) {
219 DLIST_REMOVE(msg
->dispatch
[msg_type
], d
);
226 Send a message to a particular server
228 NTSTATUS
imessaging_send(struct imessaging_context
*msg
, struct server_id server
,
229 uint32_t msg_type
, const DATA_BLOB
*data
)
231 uint8_t hdr
[MESSAGE_HDR_LENGTH
];
237 if (!cluster_node_equal(&msg
->server_id
, &server
)) {
238 /* No cluster in source4... */
242 message_hdr_put(hdr
, msg_type
, msg
->server_id
, server
);
244 iov
[0] = (struct iovec
) { .iov_base
= &hdr
, .iov_len
= sizeof(hdr
) };
248 iov
[1] = (struct iovec
) { .iov_base
= data
->data
,
249 .iov_len
= data
->length
};
258 ret
= messaging_dgm_send(pid
, iov
, num_iov
, NULL
, 0);
261 priv
= root_privileges();
262 ret
= messaging_dgm_send(pid
, iov
, num_iov
, NULL
, 0);
267 return map_nt_error_from_unix_common(ret
);
273 Send a message to a particular server, with the message containing a single pointer
275 NTSTATUS
imessaging_send_ptr(struct imessaging_context
*msg
, struct server_id server
,
276 uint32_t msg_type
, void *ptr
)
280 blob
.data
= (uint8_t *)&ptr
;
281 blob
.length
= sizeof(void *);
283 return imessaging_send(msg
, server
, msg_type
, &blob
);
289 int imessaging_cleanup(struct imessaging_context
*msg
)
297 static void imessaging_dgm_recv(const uint8_t *buf
, size_t buf_len
,
298 int *fds
, size_t num_fds
,
301 /* Keep a list of imessaging contexts */
302 static struct imessaging_context
*msg_ctxs
;
304 static int imessaging_context_destructor(struct imessaging_context
*msg
)
306 DLIST_REMOVE(msg_ctxs
, msg
);
307 TALLOC_FREE(msg
->msg_dgm_ref
);
312 * Cleanup messaging dgm contexts
314 * We must make sure to unref all messaging_dgm_ref's *before* the
315 * tevent context goes away. Only when the last ref is freed, the
316 * refcounted messaging dgm context will be freed.
318 void imessaging_dgm_unref_all(void)
320 struct imessaging_context
*msg
= NULL
;
322 for (msg
= msg_ctxs
; msg
!= NULL
; msg
= msg
->next
) {
323 TALLOC_FREE(msg
->msg_dgm_ref
);
328 create the listening socket and setup the dispatcher
330 struct imessaging_context
*imessaging_init(TALLOC_CTX
*mem_ctx
,
331 struct loadparm_context
*lp_ctx
,
332 struct server_id server_id
,
333 struct tevent_context
*ev
)
335 struct imessaging_context
*msg
;
338 const char *lock_dir
= NULL
;
339 int tdb_flags
= TDB_INCOMPATIBLE_HASH
| TDB_CLEAR_IF_FIRST
;
345 msg
= talloc_zero(mem_ctx
, struct imessaging_context
);
350 talloc_set_destructor(msg
, imessaging_context_destructor
);
352 /* create the messaging directory if needed */
354 lock_dir
= lpcfg_lock_directory(lp_ctx
);
355 if (lock_dir
== NULL
) {
359 msg
->sock_dir
= lpcfg_private_path(msg
, lp_ctx
, "msg.sock");
360 if (msg
->sock_dir
== NULL
) {
363 ok
= directory_create_or_exist_strict(msg
->sock_dir
, geteuid(), 0700);
368 msg
->lock_dir
= lpcfg_lock_path(msg
, lp_ctx
, "msg.lock");
369 if (msg
->lock_dir
== NULL
) {
372 ok
= directory_create_or_exist_strict(msg
->lock_dir
, geteuid(), 0755);
377 msg
->msg_dgm_ref
= messaging_dgm_ref(
378 msg
, ev
, &server_id
.unique_id
, msg
->sock_dir
, msg
->lock_dir
,
379 imessaging_dgm_recv
, msg
, &ret
);
381 if (msg
->msg_dgm_ref
== NULL
) {
385 msg
->server_id
= server_id
;
386 msg
->idr
= idr_init(msg
);
387 if (msg
->idr
== NULL
) {
391 msg
->dispatch_tree
= idr_init(msg
);
392 if (msg
->dispatch_tree
== NULL
) {
396 msg
->start_time
= timeval_current();
398 tdb_flags
|= lpcfg_tdb_flags(lp_ctx
, 0);
400 msg
->names
= server_id_db_init(msg
, server_id
, lock_dir
, 0, tdb_flags
);
401 if (msg
->names
== NULL
) {
405 imessaging_register(msg
, NULL
, MSG_PING
, ping_message
);
406 imessaging_register(msg
, NULL
, MSG_REQ_POOL_USAGE
, pool_message
);
407 imessaging_register(msg
, NULL
, MSG_IRPC
, irpc_handler
);
408 IRPC_REGISTER(msg
, irpc
, IRPC_UPTIME
, irpc_uptime
, msg
);
410 DLIST_ADD(msg_ctxs
, msg
);
418 static void imessaging_dgm_recv(const uint8_t *buf
, size_t buf_len
,
419 int *fds
, size_t num_fds
,
422 struct imessaging_context
*msg
= talloc_get_type_abort(
423 private_data
, struct imessaging_context
);
425 struct server_id src
, dst
;
426 struct server_id_buf srcbuf
, dstbuf
;
429 if (buf_len
< MESSAGE_HDR_LENGTH
) {
430 /* Invalid message, ignore */
434 message_hdr_get(&msg_type
, &src
, &dst
, buf
);
436 data
.data
= discard_const_p(uint8_t, buf
+ MESSAGE_HDR_LENGTH
);
437 data
.length
= buf_len
- MESSAGE_HDR_LENGTH
;
439 if ((cluster_id_equal(&dst
, &msg
->server_id
)) ||
440 ((dst
.task_id
== 0) && (msg
->server_id
.pid
== 0))) {
441 struct dispatch_fn
*d
, *next
;
443 DEBUG(10, ("%s: dst %s matches my id: %s, type=0x%x\n",
445 server_id_str_buf(dst
, &dstbuf
),
446 server_id_str_buf(msg
->server_id
, &srcbuf
),
447 (unsigned)msg_type
));
449 d
= imessaging_find_dispatch(msg
, msg_type
);
451 for (; d
; d
= next
) {
453 d
->fn(msg
, d
->private_data
, d
->msg_type
, src
, &data
);
456 DEBUG(10, ("%s: Ignoring type=0x%x dst %s, I am %s, \n",
457 __func__
, (unsigned)msg_type
,
458 server_id_str_buf(dst
, &dstbuf
),
459 server_id_str_buf(msg
->server_id
, &srcbuf
)));
464 A hack, for the short term until we get 'client only' messaging in place
466 struct imessaging_context
*imessaging_client_init(TALLOC_CTX
*mem_ctx
,
467 struct loadparm_context
*lp_ctx
,
468 struct tevent_context
*ev
)
473 id
.task_id
= generate_random();
474 id
.vnn
= NONCLUSTER_VNN
;
476 /* This is because we are not in the s3 serverid database */
477 id
.unique_id
= SERVERID_UNIQUE_ID_NOT_TO_VERIFY
;
479 return imessaging_init(mem_ctx
, lp_ctx
, id
, ev
);
482 a list of registered irpc server functions
485 struct irpc_list
*next
, *prev
;
487 const struct ndr_interface_table
*table
;
495 register a irpc server function
497 NTSTATUS
irpc_register(struct imessaging_context
*msg_ctx
,
498 const struct ndr_interface_table
*table
,
499 int callnum
, irpc_function_t fn
, void *private_data
)
501 struct irpc_list
*irpc
;
503 /* override an existing handler, if any */
504 for (irpc
=msg_ctx
->irpc
; irpc
; irpc
=irpc
->next
) {
505 if (irpc
->table
== table
&& irpc
->callnum
== callnum
) {
510 irpc
= talloc(msg_ctx
, struct irpc_list
);
511 NT_STATUS_HAVE_NO_MEMORY(irpc
);
512 DLIST_ADD(msg_ctx
->irpc
, irpc
);
516 irpc
->callnum
= callnum
;
518 irpc
->private_data
= private_data
;
519 irpc
->uuid
= irpc
->table
->syntax_id
.uuid
;
526 handle an incoming irpc reply message
528 static void irpc_handler_reply(struct imessaging_context
*msg_ctx
, struct irpc_message
*m
)
530 struct irpc_request
*irpc
;
532 irpc
= (struct irpc_request
*)idr_find(msg_ctx
->idr
, m
->header
.callid
);
533 if (irpc
== NULL
) return;
535 irpc
->incoming
.handler(irpc
, m
);
541 NTSTATUS
irpc_send_reply(struct irpc_message
*m
, NTSTATUS status
)
543 struct ndr_push
*push
;
545 enum ndr_err_code ndr_err
;
547 m
->header
.status
= status
;
549 /* setup the reply */
550 push
= ndr_push_init_ctx(m
->ndr
);
552 status
= NT_STATUS_NO_MEMORY
;
556 m
->header
.flags
|= IRPC_FLAG_REPLY
;
557 m
->header
.creds
.token
= NULL
;
559 /* construct the packet */
560 ndr_err
= ndr_push_irpc_header(push
, NDR_SCALARS
|NDR_BUFFERS
, &m
->header
);
561 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
562 status
= ndr_map_error2ntstatus(ndr_err
);
566 ndr_err
= m
->irpc
->table
->calls
[m
->irpc
->callnum
].ndr_push(push
, NDR_OUT
, m
->data
);
567 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
568 status
= ndr_map_error2ntstatus(ndr_err
);
572 /* send the reply message */
573 packet
= ndr_push_blob(push
);
574 status
= imessaging_send(m
->msg_ctx
, m
->from
, MSG_IRPC
, &packet
);
575 if (!NT_STATUS_IS_OK(status
)) goto failed
;
583 handle an incoming irpc request message
585 static void irpc_handler_request(struct imessaging_context
*msg_ctx
,
586 struct irpc_message
*m
)
590 enum ndr_err_code ndr_err
;
592 for (i
=msg_ctx
->irpc
; i
; i
=i
->next
) {
593 if (GUID_equal(&i
->uuid
, &m
->header
.uuid
) &&
594 i
->table
->syntax_id
.if_version
== m
->header
.if_version
&&
595 i
->callnum
== m
->header
.callnum
) {
601 /* no registered handler for this message */
606 /* allocate space for the structure */
607 r
= talloc_zero_size(m
->ndr
, i
->table
->calls
[m
->header
.callnum
].struct_size
);
608 if (r
== NULL
) goto failed
;
610 m
->ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
612 /* parse the request data */
613 ndr_err
= i
->table
->calls
[i
->callnum
].ndr_pull(m
->ndr
, NDR_IN
, r
);
614 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) goto failed
;
617 m
->private_data
= i
->private_data
;
618 m
->defer_reply
= false;
620 m
->msg_ctx
= msg_ctx
;
624 m
->header
.status
= i
->fn(m
, r
);
627 /* the server function won't ever be replying to this request */
632 if (m
->defer_reply
) {
633 /* the server function has asked to defer the reply to later */
634 talloc_steal(msg_ctx
, m
);
638 irpc_send_reply(m
, m
->header
.status
);
646 handle an incoming irpc message
648 static void irpc_handler(struct imessaging_context
*msg_ctx
, void *private_data
,
649 uint32_t msg_type
, struct server_id src
, DATA_BLOB
*packet
)
651 struct irpc_message
*m
;
652 enum ndr_err_code ndr_err
;
654 m
= talloc(msg_ctx
, struct irpc_message
);
655 if (m
== NULL
) goto failed
;
659 m
->ndr
= ndr_pull_init_blob(packet
, m
);
660 if (m
->ndr
== NULL
) goto failed
;
662 m
->ndr
->flags
|= LIBNDR_FLAG_REF_ALLOC
;
664 ndr_err
= ndr_pull_irpc_header(m
->ndr
, NDR_BUFFERS
|NDR_SCALARS
, &m
->header
);
665 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) goto failed
;
667 if (m
->header
.flags
& IRPC_FLAG_REPLY
) {
668 irpc_handler_reply(msg_ctx
, m
);
670 irpc_handler_request(msg_ctx
, m
);
680 destroy a irpc request
682 static int irpc_destructor(struct irpc_request
*irpc
)
684 if (irpc
->callid
!= -1) {
685 idr_remove(irpc
->msg_ctx
->idr
, irpc
->callid
);
693 add a string name that this irpc server can be called on
695 NTSTATUS
irpc_add_name(struct imessaging_context
*msg_ctx
, const char *name
)
699 ret
= server_id_db_add(msg_ctx
->names
, name
);
701 return map_nt_error_from_unix_common(ret
);
707 return a list of server ids for a server name
709 NTSTATUS
irpc_servers_byname(struct imessaging_context
*msg_ctx
,
710 TALLOC_CTX
*mem_ctx
, const char *name
,
711 unsigned *num_servers
,
712 struct server_id
**servers
)
716 ret
= server_id_db_lookup(msg_ctx
->names
, name
, mem_ctx
,
717 num_servers
, servers
);
719 return map_nt_error_from_unix_common(ret
);
724 static int all_servers_func(const char *name
, unsigned num_servers
,
725 const struct server_id
*servers
,
728 struct irpc_name_records
*name_records
= talloc_get_type(
729 private_data
, struct irpc_name_records
);
730 struct irpc_name_record
*name_record
;
734 = talloc_realloc(name_records
, name_records
->names
,
735 struct irpc_name_record
*, name_records
->num_records
+1);
736 if (!name_records
->names
) {
740 name_records
->names
[name_records
->num_records
] = name_record
741 = talloc(name_records
->names
,
742 struct irpc_name_record
);
747 name_records
->num_records
++;
749 name_record
->name
= talloc_strdup(name_record
, name
);
750 if (!name_record
->name
) {
754 name_record
->count
= num_servers
;
755 name_record
->ids
= talloc_array(name_record
, struct server_id
,
757 if (name_record
->ids
== NULL
) {
760 for (i
=0;i
<name_record
->count
;i
++) {
761 name_record
->ids
[i
] = servers
[i
];
767 return a list of server ids for a server name
769 struct irpc_name_records
*irpc_all_servers(struct imessaging_context
*msg_ctx
,
773 struct irpc_name_records
*name_records
= talloc_zero(mem_ctx
, struct irpc_name_records
);
774 if (name_records
== NULL
) {
778 ret
= server_id_db_traverse_read(msg_ctx
->names
, all_servers_func
,
781 TALLOC_FREE(name_records
);
789 remove a name from a messaging context
791 void irpc_remove_name(struct imessaging_context
*msg_ctx
, const char *name
)
793 server_id_db_remove(msg_ctx
->names
, name
);
796 struct server_id
imessaging_get_server_id(struct imessaging_context
*msg_ctx
)
798 return msg_ctx
->server_id
;
801 struct irpc_bh_state
{
802 struct imessaging_context
*msg_ctx
;
803 struct server_id server_id
;
804 const struct ndr_interface_table
*table
;
806 struct security_token
*token
;
809 static bool irpc_bh_is_connected(struct dcerpc_binding_handle
*h
)
811 struct irpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
812 struct irpc_bh_state
);
821 static uint32_t irpc_bh_set_timeout(struct dcerpc_binding_handle
*h
,
824 struct irpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
825 struct irpc_bh_state
);
826 uint32_t old
= hs
->timeout
;
828 hs
->timeout
= timeout
;
833 struct irpc_bh_raw_call_state
{
834 struct irpc_request
*irpc
;
841 static void irpc_bh_raw_call_incoming_handler(struct irpc_request
*irpc
,
842 struct irpc_message
*m
);
844 static struct tevent_req
*irpc_bh_raw_call_send(TALLOC_CTX
*mem_ctx
,
845 struct tevent_context
*ev
,
846 struct dcerpc_binding_handle
*h
,
847 const struct GUID
*object
,
850 const uint8_t *in_data
,
853 struct irpc_bh_state
*hs
=
854 dcerpc_binding_handle_data(h
,
855 struct irpc_bh_state
);
856 struct tevent_req
*req
;
857 struct irpc_bh_raw_call_state
*state
;
859 struct irpc_header header
;
860 struct ndr_push
*ndr
;
862 enum ndr_err_code ndr_err
;
864 req
= tevent_req_create(mem_ctx
, &state
,
865 struct irpc_bh_raw_call_state
);
869 state
->opnum
= opnum
;
870 state
->in_data
.data
= discard_const_p(uint8_t, in_data
);
871 state
->in_data
.length
= in_length
;
873 ok
= irpc_bh_is_connected(h
);
875 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
876 return tevent_req_post(req
, ev
);
879 state
->irpc
= talloc_zero(state
, struct irpc_request
);
880 if (tevent_req_nomem(state
->irpc
, req
)) {
881 return tevent_req_post(req
, ev
);
884 state
->irpc
->msg_ctx
= hs
->msg_ctx
;
885 state
->irpc
->callid
= idr_get_new(hs
->msg_ctx
->idr
,
886 state
->irpc
, UINT16_MAX
);
887 if (state
->irpc
->callid
== -1) {
888 tevent_req_nterror(req
, NT_STATUS_INSUFFICIENT_RESOURCES
);
889 return tevent_req_post(req
, ev
);
891 state
->irpc
->incoming
.handler
= irpc_bh_raw_call_incoming_handler
;
892 state
->irpc
->incoming
.private_data
= req
;
894 talloc_set_destructor(state
->irpc
, irpc_destructor
);
896 /* setup the header */
897 header
.uuid
= hs
->table
->syntax_id
.uuid
;
899 header
.if_version
= hs
->table
->syntax_id
.if_version
;
900 header
.callid
= state
->irpc
->callid
;
901 header
.callnum
= state
->opnum
;
903 header
.status
= NT_STATUS_OK
;
904 header
.creds
.token
= hs
->token
;
906 /* construct the irpc packet */
907 ndr
= ndr_push_init_ctx(state
->irpc
);
908 if (tevent_req_nomem(ndr
, req
)) {
909 return tevent_req_post(req
, ev
);
912 ndr_err
= ndr_push_irpc_header(ndr
, NDR_SCALARS
|NDR_BUFFERS
, &header
);
913 status
= ndr_map_error2ntstatus(ndr_err
);
914 if (!NT_STATUS_IS_OK(status
)) {
915 tevent_req_nterror(req
, status
);
916 return tevent_req_post(req
, ev
);
919 ndr_err
= ndr_push_bytes(ndr
, in_data
, in_length
);
920 status
= ndr_map_error2ntstatus(ndr_err
);
921 if (!NT_STATUS_IS_OK(status
)) {
922 tevent_req_nterror(req
, status
);
923 return tevent_req_post(req
, ev
);
927 state
->in_packet
= ndr_push_blob(ndr
);
928 status
= imessaging_send(hs
->msg_ctx
, hs
->server_id
,
929 MSG_IRPC
, &state
->in_packet
);
930 if (!NT_STATUS_IS_OK(status
)) {
931 tevent_req_nterror(req
, status
);
932 return tevent_req_post(req
, ev
);
935 if (hs
->timeout
!= IRPC_CALL_TIMEOUT_INF
) {
936 /* set timeout-callback in case caller wants that */
937 ok
= tevent_req_set_endtime(req
, ev
, timeval_current_ofs(hs
->timeout
, 0));
939 return tevent_req_post(req
, ev
);
946 static void irpc_bh_raw_call_incoming_handler(struct irpc_request
*irpc
,
947 struct irpc_message
*m
)
949 struct tevent_req
*req
=
950 talloc_get_type_abort(irpc
->incoming
.private_data
,
952 struct irpc_bh_raw_call_state
*state
=
954 struct irpc_bh_raw_call_state
);
956 talloc_steal(state
, m
);
958 if (!NT_STATUS_IS_OK(m
->header
.status
)) {
959 tevent_req_nterror(req
, m
->header
.status
);
963 state
->out_data
= data_blob_talloc(state
,
964 m
->ndr
->data
+ m
->ndr
->offset
,
965 m
->ndr
->data_size
- m
->ndr
->offset
);
966 if ((m
->ndr
->data_size
- m
->ndr
->offset
) > 0 && !state
->out_data
.data
) {
971 tevent_req_done(req
);
974 static NTSTATUS
irpc_bh_raw_call_recv(struct tevent_req
*req
,
980 struct irpc_bh_raw_call_state
*state
=
982 struct irpc_bh_raw_call_state
);
985 if (tevent_req_is_nterror(req
, &status
)) {
986 tevent_req_received(req
);
990 *out_data
= talloc_move(mem_ctx
, &state
->out_data
.data
);
991 *out_length
= state
->out_data
.length
;
993 tevent_req_received(req
);
997 struct irpc_bh_disconnect_state
{
1001 static struct tevent_req
*irpc_bh_disconnect_send(TALLOC_CTX
*mem_ctx
,
1002 struct tevent_context
*ev
,
1003 struct dcerpc_binding_handle
*h
)
1005 struct irpc_bh_state
*hs
= dcerpc_binding_handle_data(h
,
1006 struct irpc_bh_state
);
1007 struct tevent_req
*req
;
1008 struct irpc_bh_disconnect_state
*state
;
1011 req
= tevent_req_create(mem_ctx
, &state
,
1012 struct irpc_bh_disconnect_state
);
1017 ok
= irpc_bh_is_connected(h
);
1019 tevent_req_nterror(req
, NT_STATUS_CONNECTION_DISCONNECTED
);
1020 return tevent_req_post(req
, ev
);
1025 tevent_req_done(req
);
1026 return tevent_req_post(req
, ev
);
1029 static NTSTATUS
irpc_bh_disconnect_recv(struct tevent_req
*req
)
1033 if (tevent_req_is_nterror(req
, &status
)) {
1034 tevent_req_received(req
);
1038 tevent_req_received(req
);
1039 return NT_STATUS_OK
;
1042 static bool irpc_bh_ref_alloc(struct dcerpc_binding_handle
*h
)
1047 static const struct dcerpc_binding_handle_ops irpc_bh_ops
= {
1049 .is_connected
= irpc_bh_is_connected
,
1050 .set_timeout
= irpc_bh_set_timeout
,
1051 .raw_call_send
= irpc_bh_raw_call_send
,
1052 .raw_call_recv
= irpc_bh_raw_call_recv
,
1053 .disconnect_send
= irpc_bh_disconnect_send
,
1054 .disconnect_recv
= irpc_bh_disconnect_recv
,
1056 .ref_alloc
= irpc_bh_ref_alloc
,
1059 /* initialise a irpc binding handle */
1060 struct dcerpc_binding_handle
*irpc_binding_handle(TALLOC_CTX
*mem_ctx
,
1061 struct imessaging_context
*msg_ctx
,
1062 struct server_id server_id
,
1063 const struct ndr_interface_table
*table
)
1065 struct dcerpc_binding_handle
*h
;
1066 struct irpc_bh_state
*hs
;
1068 h
= dcerpc_binding_handle_create(mem_ctx
,
1073 struct irpc_bh_state
,
1078 hs
->msg_ctx
= msg_ctx
;
1079 hs
->server_id
= server_id
;
1081 hs
->timeout
= IRPC_CALL_TIMEOUT
;
1086 struct dcerpc_binding_handle
*irpc_binding_handle_by_name(TALLOC_CTX
*mem_ctx
,
1087 struct imessaging_context
*msg_ctx
,
1088 const char *dest_task
,
1089 const struct ndr_interface_table
*table
)
1091 struct dcerpc_binding_handle
*h
;
1093 struct server_id
*sids
;
1094 struct server_id sid
;
1097 /* find the server task */
1099 status
= irpc_servers_byname(msg_ctx
, mem_ctx
, dest_task
,
1101 if (!NT_STATUS_IS_OK(status
)) {
1102 errno
= EADDRNOTAVAIL
;
1108 h
= irpc_binding_handle(mem_ctx
, msg_ctx
,
1117 void irpc_binding_handle_add_security_token(struct dcerpc_binding_handle
*h
,
1118 struct security_token
*token
)
1120 struct irpc_bh_state
*hs
=
1121 dcerpc_binding_handle_data(h
,
1122 struct irpc_bh_state
);