2 Unix SMB/CIFS implementation.
4 forwarding of RPC calls to other tasks
6 Copyright (C) Andrew Tridgell 2009
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/>.
24 #include "rpc_server/dcerpc_server.h"
25 #include "librpc/gen_ndr/dcerpc.h"
26 #include "rpc_server/common/common.h"
27 #include "messaging/irpc.h"
28 #include "auth/auth.h"
31 struct dcesrv_forward_state
{
33 struct dcesrv_call_state
*dce_call
;
37 called when the forwarded rpc request is finished
39 static void dcesrv_irpc_forward_callback(struct tevent_req
*subreq
)
41 struct dcesrv_forward_state
*st
=
42 tevent_req_callback_data(subreq
,
43 struct dcesrv_forward_state
);
44 const char *opname
= st
->opname
;
47 status
= dcerpc_binding_handle_call_recv(subreq
);
49 if (!NT_STATUS_IS_OK(status
)) {
50 DEBUG(0,("IRPC callback failed for %s - %s\n",
51 opname
, nt_errstr(status
)));
52 st
->dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
54 status
= dcesrv_reply(st
->dce_call
);
55 if (!NT_STATUS_IS_OK(status
)) {
56 DEBUG(0,("%s_handler: dcesrv_reply() failed - %s\n",
57 opname
, nt_errstr(status
)));
64 * Forward a RPC call using IRPC to another task
66 void dcesrv_irpc_forward_rpc_call(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
67 void *r
, uint32_t callid
,
68 const struct ndr_interface_table
*ndr_table
,
69 const char *dest_task
, const char *opname
,
72 struct dcesrv_forward_state
*st
;
73 struct dcerpc_binding_handle
*binding_handle
;
74 struct tevent_req
*subreq
;
75 struct security_token
*token
;
77 st
= talloc(mem_ctx
, struct dcesrv_forward_state
);
79 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
83 st
->dce_call
= dce_call
;
86 /* if the caller has said they can't support async calls
88 if (!(dce_call
->state_flags
& DCESRV_CALL_STATE_FLAG_MAY_ASYNC
)) {
89 /* we're not allowed to reply async */
90 DEBUG(0,("%s: Not available synchronously\n", dest_task
));
91 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
95 binding_handle
= irpc_binding_handle_by_name(st
, dce_call
->msg_ctx
,
96 dest_task
, ndr_table
);
97 if (binding_handle
== NULL
) {
98 DEBUG(0,("%s: Failed to forward request to %s task\n",
100 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
104 /* reset timeout for the handle */
105 dcerpc_binding_handle_set_timeout(binding_handle
, timeout
);
107 /* add security token to the handle*/
108 token
= dce_call
->conn
->auth_state
.session_info
->security_token
;
109 irpc_binding_handle_add_security_token(binding_handle
, token
);
111 /* forward the call */
112 subreq
= dcerpc_binding_handle_call_send(st
, dce_call
->event_ctx
,
117 if (subreq
== NULL
) {
118 DEBUG(0,("%s: Failed to forward request to %s task\n",
120 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
124 /* mark the request as replied async */
125 dce_call
->state_flags
|= DCESRV_CALL_STATE_FLAG_ASYNC
;
127 /* setup the callback */
128 tevent_req_set_callback(subreq
, dcesrv_irpc_forward_callback
, st
);