s4-ldb: cope better with corruption of tdb records
[Samba/aatanasov.git] / source3 / rpc_client / ndr.c
blobf9af2f5f7ad51b2706c08bced067bbc1924b508a
1 /*
2 Unix SMB/CIFS implementation.
4 libndr interface
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/>.
23 #include "includes.h"
25 struct cli_do_rpc_ndr_state {
26 const struct ndr_interface_call *call;
27 prs_struct q_ps, r_ps;
28 void *r;
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,
37 uint32_t opnum,
38 void *r)
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;
47 req = tevent_req_create(mem_ctx, &state,
48 struct cli_do_rpc_ndr_state);
49 if (req == NULL) {
50 return NULL;
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);
59 state->r = r;
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));
70 TALLOC_FREE(push);
71 return tevent_req_post(req, ev);
74 blob = ndr_push_blob(push);
75 ret = prs_init_data_blob(&state->q_ps, &blob, state);
76 TALLOC_FREE(push);
78 if (!ret) {
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);
88 return 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);
97 NTSTATUS status;
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;
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;
115 NTSTATUS status;
116 DATA_BLOB blob;
117 bool ret;
119 if (tevent_req_is_nterror(req, &status)) {
120 return status;
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;
129 pull = ndr_pull_init_blob(&blob, mem_ctx, NULL);
130 if (pull == 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);
137 TALLOC_FREE(pull);
139 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
140 return ndr_map_error2ntstatus(ndr_err);
143 return NT_STATUS_OK;
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)
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);
157 if (ev == NULL) {
158 status = NT_STATUS_NO_MEMORY;
159 goto fail;
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;
168 if (!tevent_req_poll(req, ev)) {
169 status = map_nt_error_from_unix(errno);
170 goto fail;
173 status = cli_do_rpc_ndr_recv(req, mem_ctx);
174 fail:
175 TALLOC_FREE(frame);
176 return status;