s4-rpc: remove some unnecessary #include lines
[nivanova/samba-autobuild/.git] / source4 / rpc_server / common / forward.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    forwarding of RPC calls to other tasks
5
6    Copyright (C) Andrew Tridgell 2009
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 "rpc_server/dcerpc_server.h"
24 #include "messaging/irpc.h"
25
26 struct dcesrv_forward_state {
27         const char *opname;
28         struct dcesrv_call_state *dce_call;
29 };
30
31 /*
32   called when the forwarded rpc request is finished
33  */
34 static void dcesrv_irpc_forward_callback(struct irpc_request *ireq)
35 {
36         struct dcesrv_forward_state *st = talloc_get_type(ireq->async.private_data, 
37                                                           struct dcesrv_forward_state);
38         const char *opname = st->opname;
39         NTSTATUS status;
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;
44         }
45         talloc_free(ireq);
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)));
50         }
51 }
52
53
54
55 /*
56   forward a RPC call using IRPC to another task
57  */
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)
62 {
63         struct server_id *sid;
64         struct irpc_request *ireq;
65         struct dcesrv_forward_state *st;
66
67         st = talloc(mem_ctx, struct dcesrv_forward_state);
68         if (st == NULL) {
69                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
70                 return;
71         }
72
73         st->dce_call = dce_call;
74         st->opname   = opname;
75
76         /* if the caller has said they can't support async calls
77            then fail the call */
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;
82                 return;
83         }
84
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;
90                 return;
91         }
92
93         /* forward the call */
94         ireq = irpc_call_send(dce_call->msg_ctx, sid[0], ndr_table, callid, r, mem_ctx);
95         if (ireq == NULL) {
96                 DEBUG(0,("%s: Failed to forward request to %s task\n", 
97                          opname, dest_task));
98                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
99                 return;
100         }
101
102         /* mark the request as replied async */
103         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
104
105         /* setup the callback */
106         ireq->async.fn = dcesrv_irpc_forward_callback;
107         ireq->async.private_data = st;
108 }