2 Unix SMB/CIFS implementation.
4 dcerpc pipe handle functions
6 Copyright (C) Stefan Metzmacher 2010,2013
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/>.
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "librpc/rpc/dcerpc.h"
26 #include "rpc_common.h"
28 struct dcerpc_pipe_handle_connection {
29 const char *chunk_struct_name;
30 size_t chunk_struct_size;
31 struct dcerpc_pipe_handle *p;
35 struct dcerpc_pipe_handle {
37 const struct dcerpc_pipe_handle_ops *ops;
39 struct dcerpc_pipe_handle_connection *pc;
40 struct tevent_req *current_req;
43 struct dcerpc_pipe_handle_connection *dcerpc_pipe_handle_connection_create(
45 const char *chunk_struct_name,
46 size_t chunk_struct_size)
48 struct dcerpc_pipe_handle_connection *pc;
50 pc = talloc_zero(mem_ctx, struct dcerpc_pipe_handle_connection);
55 pc->chunk_struct_name = talloc_strdup(pc, chunk_struct_name);
56 if (pc->chunk_struct_name == NULL) {
61 pc->chunk_struct_size = chunk_struct_size;
66 bool _dcerpc_pipe_handle_connection_connect(
67 struct dcerpc_pipe_handle_connection *pc,
68 const char *chunk_struct_name,
69 size_t chunk_struct_size,
70 struct dcerpc_pipe_handle *p,
73 if (pc->chunk_struct_size != chunk_struct_size) {
77 if (strcmp(pc->chunk_struct_name, chunk_struct_name) != 0) {
89 void dcerpc_pipe_handle_connection_disconnect(
90 struct dcerpc_pipe_handle_connection *pc)
103 static int dcerpc_pipe_handle_destructor(struct dcerpc_pipe_handle *p)
105 dcerpc_pipe_handle_connection_disconnect(p->pc);
107 if (p->current_req) {
108 tevent_req_received(p->current_req);
114 struct dcerpc_pipe_handle *_dcerpc_pipe_handle_create(
116 const struct dcerpc_pipe_handle_ops *ops,
120 const char *location)
122 struct dcerpc_pipe_handle *p;
123 void **ppstate = (void **)pstate;
126 p = talloc_zero(mem_ctx, struct dcerpc_pipe_handle);
131 p->location = location;
133 state = talloc_zero_size(p, psize);
138 talloc_set_name_const(state, type);
140 p->private_data = state;
142 talloc_set_destructor(p, dcerpc_pipe_handle_destructor);
148 void *_dcerpc_pipe_handle_data(struct dcerpc_pipe_handle *p)
150 return p->private_data;
153 struct dcerpc_pipe_handle_push_state {
154 const struct dcerpc_pipe_handle_ops *ops;
155 struct dcerpc_pipe_handle *p;
158 static int dcerpc_pipe_handle_push_state_destructor(
159 struct dcerpc_pipe_handle_push_state *state)
162 state->p->current_req = NULL;
168 static void dcerpc_pipe_handle_push_done(struct tevent_req *subreq);
170 struct tevent_req *dcerpc_pipe_handle_push_send(TALLOC_CTX *mem_ctx,
171 struct tevent_context *ev,
172 struct dcerpc_pipe_handle_connection *pc,
173 const void *chunk_ptr)
175 struct dcerpc_pipe_handle *p = pc->p;
176 struct tevent_req *req;
177 struct dcerpc_pipe_handle_push_state *state;
178 struct tevent_req *subreq;
180 req = tevent_req_create(mem_ctx, &state,
181 struct dcerpc_pipe_handle_push_state);
187 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
188 return tevent_req_post(req, ev);
192 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
193 return tevent_req_post(req, ev);
196 if (p->current_req) {
197 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
198 return tevent_req_post(req, ev);
204 talloc_set_destructor(state, dcerpc_pipe_handle_push_state_destructor);
205 p->current_req = req;
207 subreq = p->ops->chunk_push_send(state, ev, p, chunk_ptr);
208 if (tevent_req_nomem(subreq, req)) {
209 return tevent_req_post(req, ev);
212 tevent_req_set_callback(subreq, dcerpc_pipe_handle_push_done, req);
217 static void dcerpc_pipe_handle_push_done(struct tevent_req *subreq)
219 struct tevent_req *req =
220 tevent_req_callback_data(subreq,
222 struct dcerpc_pipe_handle_push_state *state =
224 struct dcerpc_pipe_handle_push_state);
227 status = state->ops->chunk_push_recv(subreq);
229 if (tevent_req_nterror(req, status)) {
233 tevent_req_done(req);
236 NTSTATUS dcerpc_pipe_handle_push_recv(struct tevent_req *req)
238 return tevent_req_simple_recv_ntstatus(req);
241 struct dcerpc_pipe_handle_pull_state {
242 const struct dcerpc_pipe_handle_ops *ops;
243 struct dcerpc_pipe_handle *p;
246 static int dcerpc_pipe_handle_pull_state_destructor(
247 struct dcerpc_pipe_handle_pull_state *state)
250 state->p->current_req = NULL;
256 static void dcerpc_pipe_handle_pull_done(struct tevent_req *subreq);
258 struct tevent_req *dcerpc_pipe_handle_pull_send(TALLOC_CTX *mem_ctx,
259 struct tevent_context *ev,
260 struct dcerpc_pipe_handle_connection *pc,
264 struct dcerpc_pipe_handle *p = pc->p;
265 struct tevent_req *req;
266 struct dcerpc_pipe_handle_pull_state *state;
267 struct tevent_req *subreq;
269 req = tevent_req_create(mem_ctx, &state,
270 struct dcerpc_pipe_handle_pull_state);
276 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
277 return tevent_req_post(req, ev);
281 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
282 return tevent_req_post(req, ev);
285 if (p->current_req) {
286 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
287 return tevent_req_post(req, ev);
293 talloc_set_destructor(state, dcerpc_pipe_handle_pull_state_destructor);
294 p->current_req = req;
296 subreq = p->ops->chunk_pull_send(state, ev, p, chunk_mem, chunk_ptr);
297 if (tevent_req_nomem(subreq, req)) {
298 return tevent_req_post(req, ev);
301 tevent_req_set_callback(subreq, dcerpc_pipe_handle_pull_done, req);
306 static void dcerpc_pipe_handle_pull_done(struct tevent_req *subreq)
308 struct tevent_req *req =
309 tevent_req_callback_data(subreq,
311 struct dcerpc_pipe_handle_pull_state *state =
313 struct dcerpc_pipe_handle_pull_state);
316 status = state->ops->chunk_pull_recv(subreq);
318 if (tevent_req_nterror(req, status)) {
322 tevent_req_done(req);
325 NTSTATUS dcerpc_pipe_handle_pull_recv(struct tevent_req *req)
327 return tevent_req_simple_recv_ntstatus(req);