2 Unix SMB/CIFS implementation.
6 Copyright (C) Jelmer Vernooij 2006
7 Copyright (C) Volker Lendecke 2009
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.
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.
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/>.
25 struct cli_do_rpc_ndr_state {
26 const struct ndr_interface_call *call;
27 prs_struct q_ps, r_ps;
31 static void cli_do_rpc_ndr_done(struct tevent_req *subreq);
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,
40 struct tevent_req *req, *subreq;
41 struct cli_do_rpc_ndr_state *state;
42 struct ndr_push *push;
44 enum ndr_err_code ndr_err;
47 req = tevent_req_create(mem_ctx, &state,
48 struct cli_do_rpc_ndr_state);
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);
60 state->call = &table->calls[opnum];
62 push = ndr_push_init_ctx(talloc_tos(), NULL);
63 if (tevent_req_nomem(push, req)) {
64 return tevent_req_post(req, ev);
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));
71 return tevent_req_post(req, ev);
74 blob = ndr_push_blob(push);
75 ret = prs_init_data_blob(&state->q_ps, &blob, state);
79 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
80 return tevent_req_post(req, ev);
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);
87 tevent_req_set_callback(subreq, cli_do_rpc_ndr_done, req);
91 static void cli_do_rpc_ndr_done(struct tevent_req *subreq)
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);
99 status = rpc_api_pipe_req_recv(subreq, state, &state->r_ps);
101 prs_mem_free(&state->q_ps);
102 if (!NT_STATUS_IS_OK(status)) {
103 tevent_req_nterror(req, status);
106 tevent_req_done(req);
109 NTSTATUS cli_do_rpc_ndr_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
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;
119 if (tevent_req_is_nterror(req, &status)) {
123 ret = prs_data_blob(&state->r_ps, &blob, talloc_tos());
124 prs_mem_free(&state->r_ps);
126 return NT_STATUS_NO_MEMORY;
129 pull = ndr_pull_init_blob(&blob, mem_ctx, NULL);
131 return NT_STATUS_NO_MEMORY;
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);
139 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
140 return ndr_map_error2ntstatus(ndr_err);
146 NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
148 const struct ndr_interface_table *table,
149 uint32_t opnum, void *r)
151 TALLOC_CTX *frame = talloc_stackframe();
152 struct event_context *ev;
153 struct tevent_req *req;
154 NTSTATUS status = NT_STATUS_OK;
156 ev = event_context_init(frame);
158 status = NT_STATUS_NO_MEMORY;
162 req = cli_do_rpc_ndr_send(frame, ev, cli, table, opnum, r);
164 status = NT_STATUS_NO_MEMORY;
168 if (!tevent_req_poll(req, ev)) {
169 status = map_nt_error_from_unix(errno);
173 status = cli_do_rpc_ndr_recv(req, mem_ctx);