2 Unix SMB/CIFS implementation.
4 Async transfer of winbindd_request and _response structs
6 Copyright (C) Volker Lendecke 2008
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/>.
26 #define DBGC_CLASS DBGC_WINBIND
28 struct req_read_state {
29 struct winbindd_request *wb_req;
30 struct event_context *ev;
31 size_t max_extra_data;
35 static void wb_req_read_len(struct async_req *subreq);
36 static void wb_req_read_main(struct async_req *subreq);
37 static void wb_req_read_extra(struct async_req *subreq);
39 struct async_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
40 struct event_context *ev,
41 int fd, size_t max_extra_data)
43 struct async_req *result, *subreq;
44 struct req_read_state *state;
46 result = async_req_new(mem_ctx, ev);
51 state = talloc(result, struct req_read_state);
55 result->private_data = state;
59 state->max_extra_data = max_extra_data;
60 state->wb_req = talloc(state, struct winbindd_request);
61 if (state->wb_req == NULL) {
65 subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length),
66 sizeof(state->wb_req->length), 0);
71 subreq->async.fn = wb_req_read_len;
72 subreq->async.priv = result;
80 static void wb_req_read_len(struct async_req *subreq)
82 struct async_req *req = talloc_get_type_abort(
83 subreq->async.priv, struct async_req);
84 struct req_read_state *state = talloc_get_type_abort(
85 req->private_data, struct req_read_state);
88 status = recvall_recv(subreq);
90 if (!NT_STATUS_IS_OK(status)) {
91 async_req_error(req, status);
95 if (state->wb_req->length != sizeof(struct winbindd_request)) {
96 DEBUG(0, ("wb_req_read_len: Invalid request size received: "
97 "%d (expected %d)\n", (int)state->wb_req->length,
98 (int)sizeof(struct winbindd_request)));
99 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
103 subreq = recvall_send(
104 req, state->ev, state->fd, (uint32 *)(state->wb_req)+1,
105 sizeof(struct winbindd_request) - sizeof(uint32), 0);
106 if (async_req_nomem(subreq, req)) {
110 subreq->async.fn = wb_req_read_main;
111 subreq->async.priv = req;
114 static void wb_req_read_main(struct async_req *subreq)
116 struct async_req *req = talloc_get_type_abort(
117 subreq->async.priv, struct async_req);
118 struct req_read_state *state = talloc_get_type_abort(
119 req->private_data, struct req_read_state);
122 status = recvall_recv(subreq);
124 if (!NT_STATUS_IS_OK(status)) {
125 async_req_error(req, status);
129 if ((state->max_extra_data != 0)
130 && (state->wb_req->extra_len > state->max_extra_data)) {
131 DEBUG(3, ("Got request with %d bytes extra data on "
132 "unprivileged socket\n",
133 (int)state->wb_req->extra_len));
134 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
138 if (state->wb_req->extra_len == 0) {
143 state->wb_req->extra_data.data = TALLOC_ARRAY(
144 state->wb_req, char, state->wb_req->extra_len + 1);
145 if (async_req_nomem(state->wb_req->extra_data.data, req)) {
149 state->wb_req->extra_data.data[state->wb_req->extra_len] = 0;
151 subreq = recvall_send(
152 req, state->ev, state->fd, state->wb_req->extra_data.data,
153 state->wb_req->extra_len, 0);
154 if (async_req_nomem(subreq, req)) {
158 subreq->async.fn = wb_req_read_extra;
159 subreq->async.priv = req;
162 static void wb_req_read_extra(struct async_req *subreq)
164 struct async_req *req = talloc_get_type_abort(
165 subreq->async.priv, struct async_req);
168 status = recvall_recv(subreq);
170 if (!NT_STATUS_IS_OK(status)) {
171 async_req_error(req, status);
178 NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
179 struct winbindd_request **preq)
181 struct req_read_state *state = talloc_get_type_abort(
182 req->private_data, struct req_read_state);
185 if (async_req_is_error(req, &status)) {
188 *preq = talloc_move(mem_ctx, &state->wb_req);
192 struct req_write_state {
193 struct winbindd_request *wb_req;
194 struct event_context *ev;
198 static void wb_req_write_main(struct async_req *subreq);
199 static void wb_req_write_extra(struct async_req *subreq);
201 struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
202 struct event_context *ev, int fd,
203 struct winbindd_request *wb_req)
205 struct async_req *result, *subreq;
206 struct req_write_state *state;
208 result = async_req_new(mem_ctx, ev);
209 if (result == NULL) {
213 state = talloc(result, struct req_write_state);
217 result->private_data = state;
221 state->wb_req = wb_req;
223 subreq = sendall_send(state, state->ev, state->fd, state->wb_req,
224 sizeof(struct winbindd_request), 0);
225 if (subreq == NULL) {
229 subreq->async.fn = wb_req_write_main;
230 subreq->async.priv = result;
238 static void wb_req_write_main(struct async_req *subreq)
240 struct async_req *req = talloc_get_type_abort(
241 subreq->async.priv, struct async_req);
242 struct req_write_state *state = talloc_get_type_abort(
243 req->private_data, struct req_write_state);
246 status = sendall_recv(subreq);
248 if (!NT_STATUS_IS_OK(status)) {
249 async_req_error(req, status);
253 if (state->wb_req->extra_len == 0) {
258 subreq = sendall_send(state, state->ev, state->fd,
259 state->wb_req->extra_data.data,
260 state->wb_req->extra_len, 0);
261 if (async_req_nomem(subreq, req)) {
265 subreq->async.fn = wb_req_write_extra;
266 subreq->async.priv = req;
269 static void wb_req_write_extra(struct async_req *subreq)
271 struct async_req *req = talloc_get_type_abort(
272 subreq->async.priv, struct async_req);
275 status = sendall_recv(subreq);
277 if (!NT_STATUS_IS_OK(status)) {
278 async_req_error(req, status);
285 NTSTATUS wb_req_write_recv(struct async_req *req)
287 return async_req_simple_recv(req);
290 struct resp_read_state {
291 struct winbindd_response *wb_resp;
292 struct event_context *ev;
293 size_t max_extra_data;
297 static void wb_resp_read_len(struct async_req *subreq);
298 static void wb_resp_read_main(struct async_req *subreq);
299 static void wb_resp_read_extra(struct async_req *subreq);
301 struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
302 struct event_context *ev, int fd)
304 struct async_req *result, *subreq;
305 struct resp_read_state *state;
307 result = async_req_new(mem_ctx, ev);
308 if (result == NULL) {
312 state = talloc(result, struct resp_read_state);
316 result->private_data = state;
320 state->wb_resp = talloc(state, struct winbindd_response);
321 if (state->wb_resp == NULL) {
325 subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length),
326 sizeof(state->wb_resp->length), 0);
327 if (subreq == NULL) {
331 subreq->async.fn = wb_resp_read_len;
332 subreq->async.priv = result;
340 static void wb_resp_read_len(struct async_req *subreq)
342 struct async_req *req = talloc_get_type_abort(
343 subreq->async.priv, struct async_req);
344 struct resp_read_state *state = talloc_get_type_abort(
345 req->private_data, struct resp_read_state);
348 status = recvall_recv(subreq);
350 if (!NT_STATUS_IS_OK(status)) {
351 async_req_error(req, status);
355 if (state->wb_resp->length < sizeof(struct winbindd_response)) {
356 DEBUG(0, ("wb_resp_read_len: Invalid response size received: "
357 "%d (expected at least%d)\n",
358 (int)state->wb_resp->length,
359 (int)sizeof(struct winbindd_response)));
360 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
364 subreq = recvall_send(
365 req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1,
366 sizeof(struct winbindd_response) - sizeof(uint32), 0);
367 if (async_req_nomem(subreq, req)) {
371 subreq->async.fn = wb_resp_read_main;
372 subreq->async.priv = req;
375 static void wb_resp_read_main(struct async_req *subreq)
377 struct async_req *req = talloc_get_type_abort(
378 subreq->async.priv, struct async_req);
379 struct resp_read_state *state = talloc_get_type_abort(
380 req->private_data, struct resp_read_state);
384 status = recvall_recv(subreq);
386 if (!NT_STATUS_IS_OK(status)) {
387 async_req_error(req, status);
391 extra_len = state->wb_resp->length - sizeof(struct winbindd_response);
392 if (extra_len == 0) {
397 state->wb_resp->extra_data.data = TALLOC_ARRAY(
398 state->wb_resp, char, extra_len+1);
399 if (async_req_nomem(state->wb_resp->extra_data.data, req)) {
402 ((char *)state->wb_resp->extra_data.data)[extra_len] = 0;
404 subreq = recvall_send(
405 req, state->ev, state->fd, state->wb_resp->extra_data.data,
407 if (async_req_nomem(subreq, req)) {
411 subreq->async.fn = wb_resp_read_extra;
412 subreq->async.priv = req;
415 static void wb_resp_read_extra(struct async_req *subreq)
417 struct async_req *req = talloc_get_type_abort(
418 subreq->async.priv, struct async_req);
421 status = recvall_recv(subreq);
423 if (!NT_STATUS_IS_OK(status)) {
424 async_req_error(req, status);
431 NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
432 struct winbindd_response **presp)
434 struct resp_read_state *state = talloc_get_type_abort(
435 req->private_data, struct resp_read_state);
438 if (async_req_is_error(req, &status)) {
441 *presp = talloc_move(mem_ctx, &state->wb_resp);
445 struct resp_write_state {
446 struct winbindd_response *wb_resp;
447 struct event_context *ev;
451 static void wb_resp_write_main(struct async_req *subreq);
452 static void wb_resp_write_extra(struct async_req *subreq);
454 struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
455 struct event_context *ev, int fd,
456 struct winbindd_response *wb_resp)
458 struct async_req *result, *subreq;
459 struct resp_write_state *state;
461 result = async_req_new(mem_ctx, ev);
462 if (result == NULL) {
466 state = talloc(result, struct resp_write_state);
470 result->private_data = state;
474 state->wb_resp = wb_resp;
476 subreq = sendall_send(state, state->ev, state->fd, state->wb_resp,
477 sizeof(struct winbindd_response), 0);
478 if (subreq == NULL) {
482 subreq->async.fn = wb_resp_write_main;
483 subreq->async.priv = result;
491 static void wb_resp_write_main(struct async_req *subreq)
493 struct async_req *req = talloc_get_type_abort(
494 subreq->async.priv, struct async_req);
495 struct resp_write_state *state = talloc_get_type_abort(
496 req->private_data, struct resp_write_state);
499 status = sendall_recv(subreq);
501 if (!NT_STATUS_IS_OK(status)) {
502 async_req_error(req, status);
506 if (state->wb_resp->length == sizeof(struct winbindd_response)) {
511 subreq = sendall_send(
512 state, state->ev, state->fd,
513 state->wb_resp->extra_data.data,
514 state->wb_resp->length - sizeof(struct winbindd_response), 0);
515 if (async_req_nomem(subreq, req)) {
519 subreq->async.fn = wb_resp_write_extra;
520 subreq->async.priv = req;
523 static void wb_resp_write_extra(struct async_req *subreq)
525 struct async_req *req = talloc_get_type_abort(
526 subreq->async.priv, struct async_req);
529 status = sendall_recv(subreq);
531 if (!NT_STATUS_IS_OK(status)) {
532 async_req_error(req, status);
539 NTSTATUS wb_resp_write_recv(struct async_req *req)
541 return async_req_simple_recv(req);
544 struct wb_trans_state {
545 struct event_context *ev;
546 struct timed_event *te;
548 struct winbindd_response *wb_resp;
549 size_t reply_max_extra_data;
552 static void wb_trans_timeout(struct event_context *ev, struct timed_event *te,
553 const struct timeval *now, void *priv);
554 static void wb_trans_sent(struct async_req *req);
555 static void wb_trans_received(struct async_req *req);
557 struct async_req *wb_trans_send(TALLOC_CTX *mem_ctx,
558 struct event_context *ev,
560 struct winbindd_request *wb_req,
561 struct timeval timeout,
562 size_t reply_max_extra_data)
564 struct async_req *result, *subreq;
565 struct wb_trans_state *state;
567 result = async_req_new(mem_ctx, ev);
568 if (result == NULL) {
572 state = talloc(result, struct wb_trans_state);
576 result->private_data = state;
580 state->reply_max_extra_data = reply_max_extra_data;
582 state->te = event_add_timed(
584 timeval_current_ofs(timeout.tv_sec, timeout.tv_usec),
585 "wb_trans_timeout", wb_trans_timeout, result);
586 if (state->te == NULL) {
590 subreq = wb_req_write_send(state, state->ev, state->fd, wb_req);
591 if (subreq == NULL) {
594 subreq->async.fn = wb_trans_sent;
595 subreq->async.priv = result;
604 static void wb_trans_timeout(struct event_context *ev, struct timed_event *te,
605 const struct timeval *now, void *priv)
607 struct async_req *req = talloc_get_type_abort(
608 priv, struct async_req);
609 struct wb_trans_state *state = talloc_get_type_abort(
610 req->private_data, struct wb_trans_state);
612 TALLOC_FREE(state->te);
613 async_req_error(req, NT_STATUS_IO_TIMEOUT);
616 static void wb_trans_sent(struct async_req *subreq)
618 struct async_req *req = talloc_get_type_abort(
619 subreq->async.priv, struct async_req);
620 struct wb_trans_state *state = talloc_get_type_abort(
621 req->private_data, struct wb_trans_state);
624 status = wb_req_write_recv(subreq);
626 if (!NT_STATUS_IS_OK(status)) {
627 async_req_error(req, status);
631 subreq = wb_resp_read_send(state, state->ev, state->fd);
632 if (async_req_nomem(subreq, req)) {
636 subreq->async.fn = wb_trans_received;
637 subreq->async.priv = req;
640 static void wb_trans_received(struct async_req *subreq)
642 struct async_req *req = talloc_get_type_abort(
643 subreq->async.priv, struct async_req);
644 struct wb_trans_state *state = talloc_get_type_abort(
645 req->private_data, struct wb_trans_state);
648 TALLOC_FREE(state->te);
650 status = wb_resp_read_recv(subreq, state, &state->wb_resp);
652 if (!NT_STATUS_IS_OK(status)) {
653 async_req_error(req, status);
660 NTSTATUS wb_trans_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
661 struct winbindd_response **presp)
663 struct wb_trans_state *state = talloc_get_type_abort(
664 req->private_data, struct wb_trans_state);
667 if (async_req_is_error(req, &status)) {
670 *presp = talloc_move(mem_ctx, &state->wb_resp);
674 struct wb_trans_queue_state {
675 struct wb_trans_queue_state *prev, *next;
676 struct wb_trans_queue *queue;
677 struct winbindd_request *req;
680 struct wb_trans_queue {
682 struct timeval timeout;
683 size_t max_resp_extra_data;
684 struct wb_trans_queue_state *queued_requests;