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 (subreq == NULL) {
107 async_req_error(req, NT_STATUS_NO_MEMORY);
111 subreq->async.fn = wb_req_read_main;
112 subreq->async.priv = req;
115 static void wb_req_read_main(struct async_req *subreq)
117 struct async_req *req = talloc_get_type_abort(
118 subreq->async.priv, struct async_req);
119 struct req_read_state *state = talloc_get_type_abort(
120 req->private_data, struct req_read_state);
123 status = recvall_recv(subreq);
125 if (!NT_STATUS_IS_OK(status)) {
126 async_req_error(req, status);
130 if ((state->max_extra_data != 0)
131 && (state->wb_req->extra_len > state->max_extra_data)) {
132 DEBUG(3, ("Got request with %d bytes extra data on "
133 "unprivileged socket\n",
134 (int)state->wb_req->extra_len));
135 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
139 if (state->wb_req->extra_len == 0) {
144 state->wb_req->extra_data.data = TALLOC_ARRAY(
145 state->wb_req, char, state->wb_req->extra_len + 1);
146 if (state->wb_req->extra_data.data == NULL) {
147 async_req_error(req, NT_STATUS_NO_MEMORY);
150 state->wb_req->extra_data.data[state->wb_req->extra_len] = 0;
152 subreq = recvall_send(
153 req, state->ev, state->fd, state->wb_req->extra_data.data,
154 state->wb_req->extra_len, 0);
155 if (subreq == NULL) {
156 async_req_error(req, NT_STATUS_NO_MEMORY);
160 subreq->async.fn = wb_req_read_extra;
161 subreq->async.priv = req;
164 static void wb_req_read_extra(struct async_req *subreq)
166 struct async_req *req = talloc_get_type_abort(
167 subreq->async.priv, struct async_req);
170 status = recvall_recv(subreq);
172 if (!NT_STATUS_IS_OK(status)) {
173 async_req_error(req, status);
180 NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
181 struct winbindd_request **preq)
183 struct req_read_state *state = talloc_get_type_abort(
184 req->private_data, struct req_read_state);
186 SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
187 if (req->state == ASYNC_REQ_ERROR) {
191 *preq = talloc_move(mem_ctx, &state->wb_req);
195 struct req_write_state {
196 struct winbindd_request *wb_req;
197 struct event_context *ev;
201 static void wb_req_write_main(struct async_req *subreq);
202 static void wb_req_write_extra(struct async_req *subreq);
204 struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
205 struct event_context *ev, int fd,
206 struct winbindd_request *wb_req)
208 struct async_req *result, *subreq;
209 struct req_write_state *state;
211 result = async_req_new(mem_ctx, ev);
212 if (result == NULL) {
216 state = talloc(result, struct req_write_state);
220 result->private_data = state;
224 state->wb_req = wb_req;
226 subreq = sendall_send(state, state->ev, state->fd, state->wb_req,
227 sizeof(struct winbindd_request), 0);
228 if (subreq == NULL) {
232 subreq->async.fn = wb_req_write_main;
233 subreq->async.priv = result;
241 static void wb_req_write_main(struct async_req *subreq)
243 struct async_req *req = talloc_get_type_abort(
244 subreq->async.priv, struct async_req);
245 struct req_write_state *state = talloc_get_type_abort(
246 req->private_data, struct req_write_state);
249 status = sendall_recv(subreq);
251 if (!NT_STATUS_IS_OK(status)) {
252 async_req_error(req, status);
256 if (state->wb_req->extra_len == 0) {
261 subreq = sendall_send(state, state->ev, state->fd,
262 state->wb_req->extra_data.data,
263 state->wb_req->extra_len, 0);
264 if (subreq == NULL) {
265 async_req_error(req, NT_STATUS_NO_MEMORY);
269 subreq->async.fn = wb_req_write_extra;
270 subreq->async.priv = req;
273 static void wb_req_write_extra(struct async_req *subreq)
275 struct async_req *req = talloc_get_type_abort(
276 subreq->async.priv, struct async_req);
279 status = sendall_recv(subreq);
281 if (!NT_STATUS_IS_OK(status)) {
282 async_req_error(req, status);
289 NTSTATUS wb_req_write_recv(struct async_req *req)
291 SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
292 if (req->state == ASYNC_REQ_ERROR) {
299 struct resp_read_state {
300 struct winbindd_response *wb_resp;
301 struct event_context *ev;
302 size_t max_extra_data;
306 static void wb_resp_read_len(struct async_req *subreq);
307 static void wb_resp_read_main(struct async_req *subreq);
308 static void wb_resp_read_extra(struct async_req *subreq);
310 struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
311 struct event_context *ev, int fd)
313 struct async_req *result, *subreq;
314 struct resp_read_state *state;
316 result = async_req_new(mem_ctx, ev);
317 if (result == NULL) {
321 state = talloc(result, struct resp_read_state);
325 result->private_data = state;
329 state->wb_resp = talloc(state, struct winbindd_response);
330 if (state->wb_resp == NULL) {
334 subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length),
335 sizeof(state->wb_resp->length), 0);
336 if (subreq == NULL) {
340 subreq->async.fn = wb_resp_read_len;
341 subreq->async.priv = result;
349 static void wb_resp_read_len(struct async_req *subreq)
351 struct async_req *req = talloc_get_type_abort(
352 subreq->async.priv, struct async_req);
353 struct resp_read_state *state = talloc_get_type_abort(
354 req->private_data, struct resp_read_state);
357 status = recvall_recv(subreq);
359 if (!NT_STATUS_IS_OK(status)) {
360 async_req_error(req, status);
364 if (state->wb_resp->length < sizeof(struct winbindd_response)) {
365 DEBUG(0, ("wb_resp_read_len: Invalid response size received: "
366 "%d (expected at least%d)\n",
367 (int)state->wb_resp->length,
368 (int)sizeof(struct winbindd_response)));
369 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
373 subreq = recvall_send(
374 req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1,
375 sizeof(struct winbindd_response) - sizeof(uint32), 0);
376 if (subreq == NULL) {
377 async_req_error(req, NT_STATUS_NO_MEMORY);
381 subreq->async.fn = wb_resp_read_main;
382 subreq->async.priv = req;
385 static void wb_resp_read_main(struct async_req *subreq)
387 struct async_req *req = talloc_get_type_abort(
388 subreq->async.priv, struct async_req);
389 struct resp_read_state *state = talloc_get_type_abort(
390 req->private_data, struct resp_read_state);
394 status = recvall_recv(subreq);
396 if (!NT_STATUS_IS_OK(status)) {
397 async_req_error(req, status);
401 extra_len = state->wb_resp->length - sizeof(struct winbindd_response);
402 if (extra_len == 0) {
407 state->wb_resp->extra_data.data = TALLOC_ARRAY(
408 state->wb_resp, char, extra_len+1);
409 if (state->wb_resp->extra_data.data == NULL) {
410 async_req_error(req, NT_STATUS_NO_MEMORY);
413 ((char *)state->wb_resp->extra_data.data)[extra_len] = 0;
415 subreq = recvall_send(
416 req, state->ev, state->fd, state->wb_resp->extra_data.data,
418 if (subreq == NULL) {
419 async_req_error(req, NT_STATUS_NO_MEMORY);
423 subreq->async.fn = wb_resp_read_extra;
424 subreq->async.priv = req;
427 static void wb_resp_read_extra(struct async_req *subreq)
429 struct async_req *req = talloc_get_type_abort(
430 subreq->async.priv, struct async_req);
433 status = recvall_recv(subreq);
435 if (!NT_STATUS_IS_OK(status)) {
436 async_req_error(req, status);
443 NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
444 struct winbindd_response **presp)
446 struct resp_read_state *state = talloc_get_type_abort(
447 req->private_data, struct resp_read_state);
449 SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
450 if (req->state == ASYNC_REQ_ERROR) {
454 *presp = talloc_move(mem_ctx, &state->wb_resp);
458 struct resp_write_state {
459 struct winbindd_response *wb_resp;
460 struct event_context *ev;
464 static void wb_resp_write_main(struct async_req *subreq);
465 static void wb_resp_write_extra(struct async_req *subreq);
467 struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
468 struct event_context *ev, int fd,
469 struct winbindd_response *wb_resp)
471 struct async_req *result, *subreq;
472 struct resp_write_state *state;
474 result = async_req_new(mem_ctx, ev);
475 if (result == NULL) {
479 state = talloc(result, struct resp_write_state);
483 result->private_data = state;
487 state->wb_resp = wb_resp;
489 subreq = sendall_send(state, state->ev, state->fd, state->wb_resp,
490 sizeof(struct winbindd_response), 0);
491 if (subreq == NULL) {
495 subreq->async.fn = wb_resp_write_main;
496 subreq->async.priv = result;
504 static void wb_resp_write_main(struct async_req *subreq)
506 struct async_req *req = talloc_get_type_abort(
507 subreq->async.priv, struct async_req);
508 struct resp_write_state *state = talloc_get_type_abort(
509 req->private_data, struct resp_write_state);
512 status = sendall_recv(subreq);
514 if (!NT_STATUS_IS_OK(status)) {
515 async_req_error(req, status);
519 if (state->wb_resp->length == sizeof(struct winbindd_response)) {
524 subreq = sendall_send(
525 state, state->ev, state->fd,
526 state->wb_resp->extra_data.data,
527 state->wb_resp->length - sizeof(struct winbindd_response), 0);
529 async_req_error(req, NT_STATUS_NO_MEMORY);
533 subreq->async.fn = wb_resp_write_extra;
534 subreq->async.priv = req;
537 static void wb_resp_write_extra(struct async_req *subreq)
539 struct async_req *req = talloc_get_type_abort(
540 subreq->async.priv, struct async_req);
543 status = sendall_recv(subreq);
545 if (!NT_STATUS_IS_OK(status)) {
546 async_req_error(req, status);
553 NTSTATUS wb_resp_write_recv(struct async_req *req)
555 SMB_ASSERT(req->state >= ASYNC_REQ_DONE);
556 if (req->state == ASYNC_REQ_ERROR) {