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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(req
, status
);
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
;
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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(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_nterror(req
, status
);
511 NTSTATUS
wb_resp_write_recv(struct async_req
*req
)
513 return async_req_simple_recv_ntstatus(req
);