Next step disentangling async_req from NTSTATUS
[Samba.git] / source3 / lib / wb_reqtrans.c
blobe779e47d2827733b63af1df14251462ab5359887
1 /*
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/>.
22 #include "includes.h"
23 #include "winbindd/winbindd.h"
25 #undef DBGC_CLASS
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;
32 int fd;
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)) {
48 return NULL;
50 state->fd = fd;
51 state->ev = ev;
52 state->max_extra_data = max_extra_data;
53 state->wb_req = talloc(state, struct winbindd_request);
54 if (state->wb_req == NULL) {
55 goto nomem;
58 subreq = recvall_send(state, ev, state->fd, &(state->wb_req->length),
59 sizeof(state->wb_req->length), 0);
60 if (subreq == NULL) {
61 goto nomem;
64 subreq->async.fn = wb_req_read_len;
65 subreq->async.priv = result;
66 return result;
68 nomem:
69 TALLOC_FREE(result);
70 return NULL;
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);
79 NTSTATUS status;
81 status = recvall_recv(subreq);
82 TALLOC_FREE(subreq);
83 if (!NT_STATUS_IS_OK(status)) {
84 async_req_nterror(req, status);
85 return;
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_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE);
93 return;
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)) {
100 return;
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);
113 NTSTATUS status;
115 status = recvall_recv(subreq);
116 TALLOC_FREE(subreq);
117 if (!NT_STATUS_IS_OK(status)) {
118 async_req_nterror(req, status);
119 return;
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_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE);
128 return;
131 if (state->wb_req->extra_len == 0) {
132 async_req_done(req);
133 return;
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)) {
139 return;
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)) {
148 return;
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);
159 NTSTATUS status;
161 status = recvall_recv(subreq);
162 TALLOC_FREE(subreq);
163 if (!NT_STATUS_IS_OK(status)) {
164 async_req_nterror(req, status);
165 return;
167 async_req_done(req);
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);
176 NTSTATUS status;
178 if (async_req_is_nterror(req, &status)) {
179 return status;
181 *preq = talloc_move(mem_ctx, &state->wb_req);
182 return NT_STATUS_OK;
185 struct req_write_state {
186 struct winbindd_request *wb_req;
187 struct event_context *ev;
188 int fd;
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)) {
203 return NULL;
205 state->fd = fd;
206 state->ev = ev;
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) {
212 goto nomem;
215 subreq->async.fn = wb_req_write_main;
216 subreq->async.priv = result;
217 return result;
219 nomem:
220 TALLOC_FREE(result);
221 return NULL;
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);
230 NTSTATUS status;
232 status = sendall_recv(subreq);
233 TALLOC_FREE(subreq);
234 if (!NT_STATUS_IS_OK(status)) {
235 async_req_nterror(req, status);
236 return;
239 if (state->wb_req->extra_len == 0) {
240 async_req_done(req);
241 return;
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)) {
248 return;
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);
259 NTSTATUS status;
261 status = sendall_recv(subreq);
262 TALLOC_FREE(subreq);
263 if (!NT_STATUS_IS_OK(status)) {
264 async_req_nterror(req, status);
265 return;
268 async_req_done(req);
271 NTSTATUS wb_req_write_recv(struct async_req *req)
273 return async_req_simple_recv_ntstatus(req);
276 struct resp_read_state {
277 struct winbindd_response *wb_resp;
278 struct event_context *ev;
279 size_t max_extra_data;
280 int fd;
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)) {
295 return NULL;
297 state->fd = fd;
298 state->ev = ev;
299 state->wb_resp = talloc(state, struct winbindd_response);
300 if (state->wb_resp == NULL) {
301 goto nomem;
304 subreq = recvall_send(state, ev, state->fd, &(state->wb_resp->length),
305 sizeof(state->wb_resp->length), 0);
306 if (subreq == NULL) {
307 goto nomem;
310 subreq->async.fn = wb_resp_read_len;
311 subreq->async.priv = result;
312 return result;
314 nomem:
315 TALLOC_FREE(result);
316 return NULL;
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);
325 NTSTATUS status;
327 status = recvall_recv(subreq);
328 TALLOC_FREE(subreq);
329 if (!NT_STATUS_IS_OK(status)) {
330 async_req_nterror(req, status);
331 return;
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_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE);
340 return;
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)) {
347 return;
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);
360 NTSTATUS status;
361 size_t extra_len;
363 status = recvall_recv(subreq);
364 TALLOC_FREE(subreq);
365 if (!NT_STATUS_IS_OK(status)) {
366 async_req_nterror(req, status);
367 return;
370 extra_len = state->wb_resp->length - sizeof(struct winbindd_response);
371 if (extra_len == 0) {
372 async_req_done(req);
373 return;
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)) {
379 return;
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,
385 extra_len, 0);
386 if (async_req_nomem(subreq, req)) {
387 return;
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);
398 NTSTATUS status;
400 status = recvall_recv(subreq);
401 TALLOC_FREE(subreq);
402 if (!NT_STATUS_IS_OK(status)) {
403 async_req_nterror(req, status);
404 return;
406 async_req_done(req);
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);
415 NTSTATUS status;
417 if (async_req_is_nterror(req, &status)) {
418 return status;
420 *presp = talloc_move(mem_ctx, &state->wb_resp);
421 return NT_STATUS_OK;
424 struct resp_write_state {
425 struct winbindd_response *wb_resp;
426 struct event_context *ev;
427 int fd;
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)) {
442 return NULL;
444 state->fd = fd;
445 state->ev = ev;
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) {
451 goto nomem;
454 subreq->async.fn = wb_resp_write_main;
455 subreq->async.priv = result;
456 return result;
458 nomem:
459 TALLOC_FREE(result);
460 return NULL;
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);
469 NTSTATUS status;
471 status = sendall_recv(subreq);
472 TALLOC_FREE(subreq);
473 if (!NT_STATUS_IS_OK(status)) {
474 async_req_nterror(req, status);
475 return;
478 if (state->wb_resp->length == sizeof(struct winbindd_response)) {
479 async_req_done(req);
480 return;
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)) {
488 return;
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);
499 NTSTATUS status;
501 status = sendall_recv(subreq);
502 TALLOC_FREE(subreq);
503 if (!NT_STATUS_IS_OK(status)) {
504 async_req_nterror(req, status);
505 return;
508 async_req_done(req);
511 NTSTATUS wb_resp_write_recv(struct async_req *req)
513 return async_req_simple_recv_ntstatus(req);