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/>.
23 #include "winbindd/winbindd.h"
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 if (!async_req_setup(mem_ctx, &result, &state,
47 struct req_read_state)) {
52 state->max_extra_data = max_extra_data;
53 state->wb_req = talloc(state, struct winbindd_request);
54 if (state->wb_req == NULL) {
58 subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length),
59 sizeof(state->wb_req->length), 0);
64 subreq->async.fn = wb_req_read_len;
65 subreq->async.priv = result;
73 static void wb_req_read_len(struct async_req *subreq)
75 struct async_req *req = talloc_get_type_abort(
76 subreq->async.priv, struct async_req);
77 struct req_read_state *state = talloc_get_type_abort(
78 req->private_data, struct req_read_state);
81 status = recvall_recv(subreq);
83 if (!NT_STATUS_IS_OK(status)) {
84 async_req_error(req, status);
88 if (state->wb_req->length != sizeof(struct winbindd_request)) {
89 DEBUG(0, ("wb_req_read_len: Invalid request size received: "
90 "%d (expected %d)\n", (int)state->wb_req->length,
91 (int)sizeof(struct winbindd_request)));
92 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
96 subreq = recvall_send(
97 req, state->ev, state->fd, (uint32 *)(state->wb_req)+1,
98 sizeof(struct winbindd_request) - sizeof(uint32), 0);
99 if (async_req_nomem(subreq, req)) {
103 subreq->async.fn = wb_req_read_main;
104 subreq->async.priv = req;
107 static void wb_req_read_main(struct async_req *subreq)
109 struct async_req *req = talloc_get_type_abort(
110 subreq->async.priv, struct async_req);
111 struct req_read_state *state = talloc_get_type_abort(
112 req->private_data, struct req_read_state);
115 status = recvall_recv(subreq);
117 if (!NT_STATUS_IS_OK(status)) {
118 async_req_error(req, status);
122 if ((state->max_extra_data != 0)
123 && (state->wb_req->extra_len > state->max_extra_data)) {
124 DEBUG(3, ("Got request with %d bytes extra data on "
125 "unprivileged socket\n",
126 (int)state->wb_req->extra_len));
127 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
131 if (state->wb_req->extra_len == 0) {
136 state->wb_req->extra_data.data = TALLOC_ARRAY(
137 state->wb_req, char, state->wb_req->extra_len + 1);
138 if (async_req_nomem(state->wb_req->extra_data.data, req)) {
142 state->wb_req->extra_data.data[state->wb_req->extra_len] = 0;
144 subreq = recvall_send(
145 req, state->ev, state->fd, state->wb_req->extra_data.data,
146 state->wb_req->extra_len, 0);
147 if (async_req_nomem(subreq, req)) {
151 subreq->async.fn = wb_req_read_extra;
152 subreq->async.priv = req;
155 static void wb_req_read_extra(struct async_req *subreq)
157 struct async_req *req = talloc_get_type_abort(
158 subreq->async.priv, struct async_req);
161 status = recvall_recv(subreq);
163 if (!NT_STATUS_IS_OK(status)) {
164 async_req_error(req, status);
171 NTSTATUS wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
172 struct winbindd_request **preq)
174 struct req_read_state *state = talloc_get_type_abort(
175 req->private_data, struct req_read_state);
178 if (async_req_is_error(req, &status)) {
181 *preq = talloc_move(mem_ctx, &state->wb_req);
185 struct req_write_state {
186 struct winbindd_request *wb_req;
187 struct event_context *ev;
191 static void wb_req_write_main(struct async_req *subreq);
192 static void wb_req_write_extra(struct async_req *subreq);
194 struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
195 struct event_context *ev, int fd,
196 struct winbindd_request *wb_req)
198 struct async_req *result, *subreq;
199 struct req_write_state *state;
201 if (!async_req_setup(mem_ctx, &result, &state,
202 struct req_write_state)) {
207 state->wb_req = wb_req;
209 subreq = sendall_send(state, state->ev, state->fd, state->wb_req,
210 sizeof(struct winbindd_request), 0);
211 if (subreq == NULL) {
215 subreq->async.fn = wb_req_write_main;
216 subreq->async.priv = result;
224 static void wb_req_write_main(struct async_req *subreq)
226 struct async_req *req = talloc_get_type_abort(
227 subreq->async.priv, struct async_req);
228 struct req_write_state *state = talloc_get_type_abort(
229 req->private_data, struct req_write_state);
232 status = sendall_recv(subreq);
234 if (!NT_STATUS_IS_OK(status)) {
235 async_req_error(req, status);
239 if (state->wb_req->extra_len == 0) {
244 subreq = sendall_send(state, state->ev, state->fd,
245 state->wb_req->extra_data.data,
246 state->wb_req->extra_len, 0);
247 if (async_req_nomem(subreq, req)) {
251 subreq->async.fn = wb_req_write_extra;
252 subreq->async.priv = req;
255 static void wb_req_write_extra(struct async_req *subreq)
257 struct async_req *req = talloc_get_type_abort(
258 subreq->async.priv, struct async_req);
261 status = sendall_recv(subreq);
263 if (!NT_STATUS_IS_OK(status)) {
264 async_req_error(req, status);
271 NTSTATUS wb_req_write_recv(struct async_req *req)
273 return async_req_simple_recv(req);
276 struct resp_read_state {
277 struct winbindd_response *wb_resp;
278 struct event_context *ev;
279 size_t max_extra_data;
283 static void wb_resp_read_len(struct async_req *subreq);
284 static void wb_resp_read_main(struct async_req *subreq);
285 static void wb_resp_read_extra(struct async_req *subreq);
287 struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
288 struct event_context *ev, int fd)
290 struct async_req *result, *subreq;
291 struct resp_read_state *state;
293 if (!async_req_setup(mem_ctx, &result, &state,
294 struct resp_read_state)) {
299 state->wb_resp = talloc(state, struct winbindd_response);
300 if (state->wb_resp == NULL) {
304 subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length),
305 sizeof(state->wb_resp->length), 0);
306 if (subreq == NULL) {
310 subreq->async.fn = wb_resp_read_len;
311 subreq->async.priv = result;
319 static void wb_resp_read_len(struct async_req *subreq)
321 struct async_req *req = talloc_get_type_abort(
322 subreq->async.priv, struct async_req);
323 struct resp_read_state *state = talloc_get_type_abort(
324 req->private_data, struct resp_read_state);
327 status = recvall_recv(subreq);
329 if (!NT_STATUS_IS_OK(status)) {
330 async_req_error(req, status);
334 if (state->wb_resp->length < sizeof(struct winbindd_response)) {
335 DEBUG(0, ("wb_resp_read_len: Invalid response size received: "
336 "%d (expected at least%d)\n",
337 (int)state->wb_resp->length,
338 (int)sizeof(struct winbindd_response)));
339 async_req_error(req, NT_STATUS_INVALID_BUFFER_SIZE);
343 subreq = recvall_send(
344 req, state->ev, state->fd, (uint32 *)(state->wb_resp)+1,
345 sizeof(struct winbindd_response) - sizeof(uint32), 0);
346 if (async_req_nomem(subreq, req)) {
350 subreq->async.fn = wb_resp_read_main;
351 subreq->async.priv = req;
354 static void wb_resp_read_main(struct async_req *subreq)
356 struct async_req *req = talloc_get_type_abort(
357 subreq->async.priv, struct async_req);
358 struct resp_read_state *state = talloc_get_type_abort(
359 req->private_data, struct resp_read_state);
363 status = recvall_recv(subreq);
365 if (!NT_STATUS_IS_OK(status)) {
366 async_req_error(req, status);
370 extra_len = state->wb_resp->length - sizeof(struct winbindd_response);
371 if (extra_len == 0) {
376 state->wb_resp->extra_data.data = TALLOC_ARRAY(
377 state->wb_resp, char, extra_len+1);
378 if (async_req_nomem(state->wb_resp->extra_data.data, req)) {
381 ((char *)state->wb_resp->extra_data.data)[extra_len] = 0;
383 subreq = recvall_send(
384 req, state->ev, state->fd, state->wb_resp->extra_data.data,
386 if (async_req_nomem(subreq, req)) {
390 subreq->async.fn = wb_resp_read_extra;
391 subreq->async.priv = req;
394 static void wb_resp_read_extra(struct async_req *subreq)
396 struct async_req *req = talloc_get_type_abort(
397 subreq->async.priv, struct async_req);
400 status = recvall_recv(subreq);
402 if (!NT_STATUS_IS_OK(status)) {
403 async_req_error(req, status);
410 NTSTATUS wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
411 struct winbindd_response **presp)
413 struct resp_read_state *state = talloc_get_type_abort(
414 req->private_data, struct resp_read_state);
417 if (async_req_is_error(req, &status)) {
420 *presp = talloc_move(mem_ctx, &state->wb_resp);
424 struct resp_write_state {
425 struct winbindd_response *wb_resp;
426 struct event_context *ev;
430 static void wb_resp_write_main(struct async_req *subreq);
431 static void wb_resp_write_extra(struct async_req *subreq);
433 struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
434 struct event_context *ev, int fd,
435 struct winbindd_response *wb_resp)
437 struct async_req *result, *subreq;
438 struct resp_write_state *state;
440 if (!async_req_setup(mem_ctx, &result, &state,
441 struct resp_write_state)) {
446 state->wb_resp = wb_resp;
448 subreq = sendall_send(state, state->ev, state->fd, state->wb_resp,
449 sizeof(struct winbindd_response), 0);
450 if (subreq == NULL) {
454 subreq->async.fn = wb_resp_write_main;
455 subreq->async.priv = result;
463 static void wb_resp_write_main(struct async_req *subreq)
465 struct async_req *req = talloc_get_type_abort(
466 subreq->async.priv, struct async_req);
467 struct resp_write_state *state = talloc_get_type_abort(
468 req->private_data, struct resp_write_state);
471 status = sendall_recv(subreq);
473 if (!NT_STATUS_IS_OK(status)) {
474 async_req_error(req, status);
478 if (state->wb_resp->length == sizeof(struct winbindd_response)) {
483 subreq = sendall_send(
484 state, state->ev, state->fd,
485 state->wb_resp->extra_data.data,
486 state->wb_resp->length - sizeof(struct winbindd_response), 0);
487 if (async_req_nomem(subreq, req)) {
491 subreq->async.fn = wb_resp_write_extra;
492 subreq->async.priv = req;
495 static void wb_resp_write_extra(struct async_req *subreq)
497 struct async_req *req = talloc_get_type_abort(
498 subreq->async.priv, struct async_req);
501 status = sendall_recv(subreq);
503 if (!NT_STATUS_IS_OK(status)) {
504 async_req_error(req, status);
511 NTSTATUS wb_resp_write_recv(struct async_req *req)
513 return async_req_simple_recv(req);