s3/smbd: open the share_info.tdb on startup instead of tconx
[ira/wip.git] / source3 / rpc_client / ndr.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    libndr interface
5
6    Copyright (C) Jelmer Vernooij 2006
7    Copyright (C) Volker Lendecke 2009
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24
25 struct cli_do_rpc_ndr_state {
26         const struct ndr_interface_call *call;
27         prs_struct q_ps, r_ps;
28         void *r;
29 };
30
31 static void cli_do_rpc_ndr_done(struct tevent_req *subreq);
32
33 struct tevent_req *cli_do_rpc_ndr_send(TALLOC_CTX *mem_ctx,
34                                        struct tevent_context *ev,
35                                        struct rpc_pipe_client *cli,
36                                        const struct ndr_interface_table *table,
37                                        uint32_t opnum,
38                                        void *r)
39 {
40         struct tevent_req *req, *subreq;
41         struct cli_do_rpc_ndr_state *state;
42         struct ndr_push *push;
43         DATA_BLOB blob;
44         enum ndr_err_code ndr_err;
45         bool ret;
46
47         req = tevent_req_create(mem_ctx, &state,
48                                 struct cli_do_rpc_ndr_state);
49         if (req == NULL) {
50                 return NULL;
51         }
52
53         if (!ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax)
54             || (opnum >= table->num_calls)) {
55                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
56                 return tevent_req_post(req, ev);
57         }
58
59         state->r = r;
60         state->call = &table->calls[opnum];
61
62         push = ndr_push_init_ctx(talloc_tos(), NULL);
63         if (tevent_req_nomem(push, req)) {
64                 return tevent_req_post(req, ev);
65         }
66
67         ndr_err = state->call->ndr_push(push, NDR_IN, r);
68         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
69                 tevent_req_nterror(req, ndr_map_error2ntstatus(ndr_err));
70                 TALLOC_FREE(push);
71                 return tevent_req_post(req, ev);
72         }
73
74         blob = ndr_push_blob(push);
75         ret = prs_init_data_blob(&state->q_ps, &blob, state);
76         TALLOC_FREE(push);
77
78         if (!ret) {
79                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
80                 return tevent_req_post(req, ev);
81         }
82
83         subreq = rpc_api_pipe_req_send(state, ev, cli, opnum, &state->q_ps);
84         if (tevent_req_nomem(subreq, req)) {
85                 return tevent_req_post(req, ev);
86         }
87         tevent_req_set_callback(subreq, cli_do_rpc_ndr_done, req);
88         return req;
89 }
90
91 static void cli_do_rpc_ndr_done(struct tevent_req *subreq)
92 {
93         struct tevent_req *req = tevent_req_callback_data(
94                 subreq, struct tevent_req);
95         struct cli_do_rpc_ndr_state *state = tevent_req_data(
96                 req, struct cli_do_rpc_ndr_state);
97         NTSTATUS status;
98
99         status = rpc_api_pipe_req_recv(subreq, state, &state->r_ps);
100         TALLOC_FREE(subreq);
101         prs_mem_free(&state->q_ps);
102         if (!NT_STATUS_IS_OK(status)) {
103                 tevent_req_nterror(req, status);
104                 return;
105         }
106         tevent_req_done(req);
107 }
108
109 NTSTATUS cli_do_rpc_ndr_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
110 {
111         struct cli_do_rpc_ndr_state *state = tevent_req_data(
112                 req, struct cli_do_rpc_ndr_state);
113         struct ndr_pull *pull;
114         enum ndr_err_code ndr_err;
115         NTSTATUS status;
116         DATA_BLOB blob;
117         bool ret;
118
119         if (tevent_req_is_nterror(req, &status)) {
120                 return status;
121         }
122
123         ret = prs_data_blob(&state->r_ps, &blob, talloc_tos());
124         prs_mem_free(&state->r_ps);
125         if (!ret) {
126                 return NT_STATUS_NO_MEMORY;
127         }
128
129         pull = ndr_pull_init_blob(&blob, mem_ctx, NULL);
130         if (pull == NULL) {
131                 return NT_STATUS_NO_MEMORY;
132         }
133
134         /* have the ndr parser alloc memory for us */
135         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
136         ndr_err = state->call->ndr_pull(pull, NDR_OUT, state->r);
137         TALLOC_FREE(pull);
138
139         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
140                 return ndr_map_error2ntstatus(ndr_err);
141         }
142
143         return NT_STATUS_OK;
144 }
145
146 NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
147                         TALLOC_CTX *mem_ctx,
148                         const struct ndr_interface_table *table,
149                         uint32_t opnum, void *r)
150 {
151         TALLOC_CTX *frame = talloc_stackframe();
152         struct event_context *ev;
153         struct tevent_req *req;
154         NTSTATUS status = NT_STATUS_OK;
155
156         ev = event_context_init(frame);
157         if (ev == NULL) {
158                 status = NT_STATUS_NO_MEMORY;
159                 goto fail;
160         }
161
162         req = cli_do_rpc_ndr_send(frame, ev, cli, table, opnum, r);
163         if (req == NULL) {
164                 status = NT_STATUS_NO_MEMORY;
165                 goto fail;
166         }
167
168         if (!tevent_req_poll(req, ev)) {
169                 status = map_nt_error_from_unix(errno);
170                 goto fail;
171         }
172
173         status = cli_do_rpc_ndr_recv(req, mem_ctx);
174  fail:
175         TALLOC_FREE(frame);
176         return status;
177 }