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)
97 if (pc->p->current_req != NULL) {
98 tevent_req_nterror(pc->p->current_req,
99 NT_STATUS_RPC_PIPE_CLOSED);
107 static int dcerpc_pipe_handle_destructor(struct dcerpc_pipe_handle *p)
109 dcerpc_pipe_handle_connection_disconnect(p->pc);
113 struct dcerpc_pipe_handle *_dcerpc_pipe_handle_create(
115 const struct dcerpc_pipe_handle_ops *ops,
119 const char *location)
121 struct dcerpc_pipe_handle *p;
122 void **ppstate = (void **)pstate;
125 p = talloc_zero(mem_ctx, struct dcerpc_pipe_handle);
130 p->location = location;
132 state = talloc_zero_size(p, psize);
137 talloc_set_name_const(state, type);
139 p->private_data = state;
141 talloc_set_destructor(p, dcerpc_pipe_handle_destructor);
147 void *_dcerpc_pipe_handle_data(struct dcerpc_pipe_handle *p)
149 return p->private_data;
152 struct dcerpc_pipe_handle_push_state {
153 const struct dcerpc_pipe_handle_ops *ops;
154 struct dcerpc_pipe_handle *p;
157 static int dcerpc_pipe_handle_push_state_destructor(
158 struct dcerpc_pipe_handle_push_state *state)
160 if (state->p != NULL) {
161 state->p->current_req = NULL;
167 static void dcerpc_pipe_handle_push_done(struct tevent_req *subreq);
169 struct tevent_req *dcerpc_pipe_handle_push_send(TALLOC_CTX *mem_ctx,
170 struct tevent_context *ev,
171 struct dcerpc_pipe_handle_connection *pc,
172 const void *chunk_ptr)
174 struct dcerpc_pipe_handle *p = pc->p;
175 struct tevent_req *req;
176 struct dcerpc_pipe_handle_push_state *state;
177 struct tevent_req *subreq;
179 req = tevent_req_create(mem_ctx, &state,
180 struct dcerpc_pipe_handle_push_state);
186 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
187 return tevent_req_post(req, ev);
191 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
192 return tevent_req_post(req, ev);
195 if (p->current_req) {
196 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
197 return tevent_req_post(req, ev);
203 tevent_req_defer_callback(req, ev);
205 talloc_set_destructor(state, dcerpc_pipe_handle_push_state_destructor);
206 p->current_req = req;
208 subreq = p->ops->chunk_push_send(state, ev, p, chunk_ptr);
209 if (tevent_req_nomem(subreq, req)) {
210 return tevent_req_post(req, ev);
213 tevent_req_set_callback(subreq, dcerpc_pipe_handle_push_done, req);
218 static void dcerpc_pipe_handle_push_done(struct tevent_req *subreq)
220 struct tevent_req *req =
221 tevent_req_callback_data(subreq,
223 struct dcerpc_pipe_handle_push_state *state =
225 struct dcerpc_pipe_handle_push_state);
228 status = state->ops->chunk_push_recv(subreq);
230 state->p->current_req = NULL;
232 if (tevent_req_nterror(req, status)) {
236 tevent_req_done(req);
239 NTSTATUS dcerpc_pipe_handle_push_recv(struct tevent_req *req)
241 return tevent_req_simple_recv_ntstatus(req);
244 struct dcerpc_pipe_handle_pull_state {
245 const struct dcerpc_pipe_handle_ops *ops;
246 struct dcerpc_pipe_handle *p;
249 static int dcerpc_pipe_handle_pull_state_destructor(
250 struct dcerpc_pipe_handle_pull_state *state)
252 if (state->p != NULL) {
253 state->p->current_req = NULL;
259 static void dcerpc_pipe_handle_pull_done(struct tevent_req *subreq);
261 struct tevent_req *dcerpc_pipe_handle_pull_send(TALLOC_CTX *mem_ctx,
262 struct tevent_context *ev,
263 struct dcerpc_pipe_handle_connection *pc,
267 struct dcerpc_pipe_handle *p = pc->p;
268 struct tevent_req *req;
269 struct dcerpc_pipe_handle_pull_state *state;
270 struct tevent_req *subreq;
272 req = tevent_req_create(mem_ctx, &state,
273 struct dcerpc_pipe_handle_pull_state);
279 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
280 return tevent_req_post(req, ev);
284 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
285 return tevent_req_post(req, ev);
288 if (p->current_req) {
289 tevent_req_nterror(req, NT_STATUS_RPC_PIPE_DISCIPLINE_ERROR);
290 return tevent_req_post(req, ev);
296 tevent_req_defer_callback(req, ev);
298 talloc_set_destructor(state, dcerpc_pipe_handle_pull_state_destructor);
299 p->current_req = req;
301 subreq = p->ops->chunk_pull_send(state, ev, p, chunk_mem, chunk_ptr);
302 if (tevent_req_nomem(subreq, req)) {
303 return tevent_req_post(req, ev);
306 tevent_req_set_callback(subreq, dcerpc_pipe_handle_pull_done, req);
311 static void dcerpc_pipe_handle_pull_done(struct tevent_req *subreq)
313 struct tevent_req *req =
314 tevent_req_callback_data(subreq,
316 struct dcerpc_pipe_handle_pull_state *state =
318 struct dcerpc_pipe_handle_pull_state);
321 status = state->ops->chunk_pull_recv(subreq);
323 state->p->current_req = NULL;
325 if (tevent_req_nterror(req, status)) {
329 tevent_req_done(req);
332 NTSTATUS dcerpc_pipe_handle_pull_recv(struct tevent_req *req)
334 return tevent_req_simple_recv_ntstatus(req);