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/>.
23 #include "rpc_server/dcerpc_server.h"
24 #include "messaging/irpc.h"
26 struct dcesrv_forward_state
{
28 struct dcesrv_call_state
*dce_call
;
32 called when the forwarded rpc request is finished
34 static void dcesrv_irpc_forward_callback(struct irpc_request
*ireq
)
36 struct dcesrv_forward_state
*st
= talloc_get_type(ireq
->async
.private_data
,
37 struct dcesrv_forward_state
);
38 const char *opname
= st
->opname
;
40 if (!NT_STATUS_IS_OK(ireq
->status
)) {
41 DEBUG(0,("IRPC callback failed for %s - %s\n",
42 opname
, nt_errstr(ireq
->status
)));
43 st
->dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
46 status
= dcesrv_reply(st
->dce_call
);
47 if (!NT_STATUS_IS_OK(status
)) {
48 DEBUG(0,("%s_handler: dcesrv_reply() failed - %s\n",
49 opname
, nt_errstr(status
)));
56 forward a RPC call using IRPC to another task
58 void dcesrv_irpc_forward_rpc_call(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
59 void *r
, uint32_t callid
,
60 const struct ndr_interface_table
*ndr_table
,
61 const char *dest_task
, const char *opname
)
63 struct server_id
*sid
;
64 struct irpc_request
*ireq
;
65 struct dcesrv_forward_state
*st
;
67 st
= talloc(mem_ctx
, struct dcesrv_forward_state
);
69 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
73 st
->dce_call
= dce_call
;
76 /* if the caller has said they can't support async calls
78 if (!(dce_call
->state_flags
& DCESRV_CALL_STATE_FLAG_MAY_ASYNC
)) {
79 /* we're not allowed to reply async */
80 DEBUG(0,("%s: Not available synchronously\n", dest_task
));
81 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
85 /* find the server task */
86 sid
= irpc_servers_byname(dce_call
->msg_ctx
, mem_ctx
, dest_task
);
87 if (sid
== NULL
|| sid
[0].id
== 0) {
88 DEBUG(0,("%s: Unable to find %s task\n", dest_task
, opname
));
89 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
93 /* forward the call */
94 ireq
= irpc_call_send(dce_call
->msg_ctx
, sid
[0], ndr_table
, callid
, r
, mem_ctx
);
96 DEBUG(0,("%s: Failed to forward request to %s task\n",
98 dce_call
->fault_code
= DCERPC_FAULT_CANT_PERFORM
;
102 /* mark the request as replied async */
103 dce_call
->state_flags
|= DCESRV_CALL_STATE_FLAG_ASYNC
;
105 /* setup the callback */
106 ireq
->async
.fn
= dcesrv_irpc_forward_callback
;
107 ireq
->async
.private_data
= st
;