2 Unix SMB/CIFS implementation.
4 Async transfer of winbindd_request and _response structs
6 Copyright (C) Volker Lendecke 2008
8 ** NOTE! The following LGPL license applies to the wbclient
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "wbc_async.h"
30 #define DBGC_CLASS DBGC_WINBIND
32 struct req_read_state {
33 struct winbindd_request *wb_req;
34 size_t max_extra_data;
38 static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data);
39 static void wb_req_read_done(struct tevent_req *subreq);
41 struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
42 struct tevent_context *ev,
43 int fd, size_t max_extra_data)
45 struct tevent_req *req, *subreq;
46 struct req_read_state *state;
48 req = tevent_req_create(mem_ctx, &state, struct req_read_state);
52 state->max_extra_data = max_extra_data;
54 subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
55 if (tevent_req_nomem(subreq, req)) {
56 return tevent_req_post(req, ev);
58 tevent_req_set_callback(subreq, wb_req_read_done, req);
62 static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
64 struct req_read_state *state = talloc_get_type_abort(
65 private_data, struct req_read_state);
66 struct winbindd_request *req = (struct winbindd_request *)buf;
69 if (req->length != sizeof(struct winbindd_request)) {
70 DEBUG(0, ("wb_req_read_len: Invalid request size "
71 "received: %d (expected %d)\n",
73 (int)sizeof(struct winbindd_request)));
76 return sizeof(struct winbindd_request) - 4;
79 if ((state->max_extra_data != 0)
80 && (req->extra_len > state->max_extra_data)) {
81 DEBUG(3, ("Got request with %d bytes extra data on "
82 "unprivileged socket\n", (int)req->extra_len));
86 return req->extra_len;
89 static void wb_req_read_done(struct tevent_req *subreq)
91 struct tevent_req *req = tevent_req_callback_data(
92 subreq, struct tevent_req);
93 struct req_read_state *state = tevent_req_data(
94 req, struct req_read_state);
98 state->ret = read_packet_recv(subreq, state, &buf, &err);
100 if (state->ret == -1) {
101 tevent_req_error(req, err);
105 state->wb_req = (struct winbindd_request *)buf;
107 if (state->wb_req->extra_len != 0) {
108 state->wb_req->extra_data.data =
109 (char *)buf + sizeof(struct winbindd_request);
111 state->wb_req->extra_data.data = NULL;
113 tevent_req_done(req);
116 ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
117 struct winbindd_request **preq, int *err)
119 struct req_read_state *state = tevent_req_data(
120 req, struct req_read_state);
122 if (tevent_req_is_unix_error(req, err)) {
125 *preq = talloc_move(mem_ctx, &state->wb_req);
129 struct req_write_state {
134 static void wb_req_write_done(struct tevent_req *subreq);
136 struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
137 struct tevent_context *ev,
138 struct tevent_queue *queue, int fd,
139 struct winbindd_request *wb_req)
141 struct tevent_req *req, *subreq;
142 struct req_write_state *state;
145 req = tevent_req_create(mem_ctx, &state, struct req_write_state);
150 state->iov[0].iov_base = (void *)wb_req;
151 state->iov[0].iov_len = sizeof(struct winbindd_request);
153 if (wb_req->extra_len != 0) {
154 state->iov[1].iov_base = (void *)wb_req->extra_data.data;
155 state->iov[1].iov_len = wb_req->extra_len;
159 subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
160 if (tevent_req_nomem(subreq, req)) {
161 return tevent_req_post(req, ev);
163 tevent_req_set_callback(subreq, wb_req_write_done, req);
167 static void wb_req_write_done(struct tevent_req *subreq)
169 struct tevent_req *req = tevent_req_callback_data(
170 subreq, struct tevent_req);
171 struct req_write_state *state = tevent_req_data(
172 req, struct req_write_state);
175 state->ret = writev_recv(subreq, &err);
177 if (state->ret < 0) {
178 tevent_req_error(req, err);
181 tevent_req_done(req);
184 ssize_t wb_req_write_recv(struct tevent_req *req, int *err)
186 struct req_write_state *state = tevent_req_data(
187 req, struct req_write_state);
189 if (tevent_req_is_unix_error(req, err)) {
195 struct resp_read_state {
196 struct winbindd_response *wb_resp;
200 static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
201 static void wb_resp_read_done(struct tevent_req *subreq);
203 struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
204 struct tevent_context *ev, int fd)
206 struct tevent_req *req, *subreq;
207 struct resp_read_state *state;
209 req = tevent_req_create(mem_ctx, &state, struct resp_read_state);
214 subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
215 if (tevent_req_nomem(subreq, req)) {
216 return tevent_req_post(req, ev);
218 tevent_req_set_callback(subreq, wb_resp_read_done, req);
222 static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
224 struct winbindd_response *resp = (struct winbindd_response *)buf;
227 if (resp->length < sizeof(struct winbindd_response)) {
228 DEBUG(0, ("wb_resp_read_len: Invalid response size "
229 "received: %d (expected at least%d)\n",
231 (int)sizeof(struct winbindd_response)));
235 return resp->length - buflen;
238 static void wb_resp_read_done(struct tevent_req *subreq)
240 struct tevent_req *req = tevent_req_callback_data(
241 subreq, struct tevent_req);
242 struct resp_read_state *state = tevent_req_data(
243 req, struct resp_read_state);
247 state->ret = read_packet_recv(subreq, state, &buf, &err);
249 if (state->ret == -1) {
250 tevent_req_error(req, err);
254 state->wb_resp = (struct winbindd_response *)buf;
256 if (state->wb_resp->length > sizeof(struct winbindd_response)) {
257 state->wb_resp->extra_data.data =
258 (char *)buf + sizeof(struct winbindd_response);
260 state->wb_resp->extra_data.data = NULL;
262 tevent_req_done(req);
265 ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
266 struct winbindd_response **presp, int *err)
268 struct resp_read_state *state = tevent_req_data(
269 req, struct resp_read_state);
271 if (tevent_req_is_unix_error(req, err)) {
274 *presp = talloc_move(mem_ctx, &state->wb_resp);
278 struct resp_write_state {
283 static void wb_resp_write_done(struct tevent_req *subreq);
285 struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
286 struct tevent_context *ev,
287 struct tevent_queue *queue, int fd,
288 struct winbindd_response *wb_resp)
290 struct tevent_req *req, *subreq;
291 struct resp_write_state *state;
294 req = tevent_req_create(mem_ctx, &state, struct resp_write_state);
299 state->iov[0].iov_base = (void *)wb_resp;
300 state->iov[0].iov_len = sizeof(struct winbindd_response);
302 if (wb_resp->length > sizeof(struct winbindd_response)) {
303 state->iov[1].iov_base = (void *)wb_resp->extra_data.data;
304 state->iov[1].iov_len =
305 wb_resp->length - sizeof(struct winbindd_response);
309 subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
310 if (tevent_req_nomem(subreq, req)) {
311 return tevent_req_post(req, ev);
313 tevent_req_set_callback(subreq, wb_resp_write_done, req);
317 static void wb_resp_write_done(struct tevent_req *subreq)
319 struct tevent_req *req = tevent_req_callback_data(
320 subreq, struct tevent_req);
321 struct resp_write_state *state = tevent_req_data(
322 req, struct resp_write_state);
325 state->ret = writev_recv(subreq, &err);
327 if (state->ret < 0) {
328 tevent_req_error(req, err);
331 tevent_req_done(req);
334 ssize_t wb_resp_write_recv(struct tevent_req *req, int *err)
336 struct resp_write_state *state = tevent_req_data(
337 req, struct resp_write_state);
339 if (tevent_req_is_unix_error(req, err)) {
345 struct wb_simple_trans_state {
346 struct tevent_context *ev;
348 struct winbindd_response *wb_resp;
351 static void wb_simple_trans_write_done(struct tevent_req *subreq);
352 static void wb_simple_trans_read_done(struct tevent_req *subreq);
354 struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx,
355 struct tevent_context *ev,
356 struct tevent_queue *queue, int fd,
357 struct winbindd_request *wb_req)
359 struct tevent_req *req, *subreq;
360 struct wb_simple_trans_state *state;
362 req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state);
367 wb_req->length = sizeof(struct winbindd_request);
372 subreq = wb_req_write_send(state, ev, queue, fd, wb_req);
373 if (tevent_req_nomem(subreq, req)) {
374 return tevent_req_post(req, ev);
376 tevent_req_set_callback(subreq, wb_simple_trans_write_done, req);
381 static void wb_simple_trans_write_done(struct tevent_req *subreq)
383 struct tevent_req *req = tevent_req_callback_data(
384 subreq, struct tevent_req);
385 struct wb_simple_trans_state *state = tevent_req_data(
386 req, struct wb_simple_trans_state);
390 ret = wb_req_write_recv(subreq, &err);
393 tevent_req_error(req, err);
396 subreq = wb_resp_read_send(state, state->ev, state->fd);
397 if (tevent_req_nomem(subreq, req)) {
400 tevent_req_set_callback(subreq, wb_simple_trans_read_done, req);
403 static void wb_simple_trans_read_done(struct tevent_req *subreq)
405 struct tevent_req *req = tevent_req_callback_data(
406 subreq, struct tevent_req);
407 struct wb_simple_trans_state *state = tevent_req_data(
408 req, struct wb_simple_trans_state);
412 ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err);
415 tevent_req_error(req, err);
419 tevent_req_done(req);
422 int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
423 struct winbindd_response **presponse, int *err)
425 struct wb_simple_trans_state *state = tevent_req_data(
426 req, struct wb_simple_trans_state);
428 if (tevent_req_is_unix_error(req, err)) {
431 *presponse = talloc_move(mem_ctx, &state->wb_resp);