2 Unix SMB/CIFS implementation.
4 Async transfer of winbindd_request and _response structs
6 Copyright (C) Volker Lendecke 2008
8 ** NOTE! The following LGPL license applies to the wbclient
9 ** library. This does NOT imply that all of Samba is released
12 This library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Lesser General Public
14 License as published by the Free Software Foundation; either
15 version 3 of the License, or (at your option) any later version.
17 This library is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 Library General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
28 #include "system/network.h"
33 #include "lib/async_req/async_sock.h"
34 #include "lib/util/tevent_unix.h"
35 #include "nsswitch/winbind_struct_protocol.h"
36 #include "nsswitch/libwbclient/wbclient.h"
37 #include "nsswitch/libwbclient/wbc_async.h"
41 #define DBGC_CLASS DBGC_WINBIND
44 struct req_read_state
{
45 struct winbindd_request
*wb_req
;
46 size_t max_extra_data
;
50 static ssize_t
wb_req_more(uint8_t *buf
, size_t buflen
, void *private_data
);
51 static void wb_req_read_done(struct tevent_req
*subreq
);
53 struct tevent_req
*wb_req_read_send(TALLOC_CTX
*mem_ctx
,
54 struct tevent_context
*ev
,
55 int fd
, size_t max_extra_data
)
57 struct tevent_req
*req
, *subreq
;
58 struct req_read_state
*state
;
60 req
= tevent_req_create(mem_ctx
, &state
, struct req_read_state
);
64 state
->max_extra_data
= max_extra_data
;
66 subreq
= read_packet_send(state
, ev
, fd
, 4, wb_req_more
, state
);
67 if (tevent_req_nomem(subreq
, req
)) {
68 return tevent_req_post(req
, ev
);
70 tevent_req_set_callback(subreq
, wb_req_read_done
, req
);
74 static ssize_t
wb_req_more(uint8_t *buf
, size_t buflen
, void *private_data
)
76 struct req_read_state
*state
= talloc_get_type_abort(
77 private_data
, struct req_read_state
);
78 struct winbindd_request
*req
= (struct winbindd_request
*)buf
;
81 if (req
->length
!= sizeof(struct winbindd_request
)) {
82 DEBUG(0, ("wb_req_read_len: Invalid request size "
83 "received: %d (expected %d)\n",
85 (int)sizeof(struct winbindd_request
)));
88 return sizeof(struct winbindd_request
) - 4;
91 if ((state
->max_extra_data
!= 0)
92 && (req
->extra_len
> state
->max_extra_data
)) {
93 DEBUG(3, ("Got request with %d bytes extra data on "
94 "unprivileged socket\n", (int)req
->extra_len
));
98 return req
->extra_len
;
101 static void wb_req_read_done(struct tevent_req
*subreq
)
103 struct tevent_req
*req
= tevent_req_callback_data(
104 subreq
, struct tevent_req
);
105 struct req_read_state
*state
= tevent_req_data(
106 req
, struct req_read_state
);
110 state
->ret
= read_packet_recv(subreq
, state
, &buf
, &err
);
112 if (state
->ret
== -1) {
113 tevent_req_error(req
, err
);
117 state
->wb_req
= (struct winbindd_request
*)buf
;
119 if (state
->wb_req
->extra_len
!= 0) {
120 state
->wb_req
->extra_data
.data
=
121 (char *)buf
+ sizeof(struct winbindd_request
);
123 state
->wb_req
->extra_data
.data
= NULL
;
125 tevent_req_done(req
);
128 ssize_t
wb_req_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
129 struct winbindd_request
**preq
, int *err
)
131 struct req_read_state
*state
= tevent_req_data(
132 req
, struct req_read_state
);
134 if (tevent_req_is_unix_error(req
, err
)) {
137 *preq
= talloc_move(mem_ctx
, &state
->wb_req
);
141 struct req_write_state
{
146 static void wb_req_write_done(struct tevent_req
*subreq
);
148 struct tevent_req
*wb_req_write_send(TALLOC_CTX
*mem_ctx
,
149 struct tevent_context
*ev
,
150 struct tevent_queue
*queue
, int fd
,
151 struct winbindd_request
*wb_req
)
153 struct tevent_req
*req
, *subreq
;
154 struct req_write_state
*state
;
157 req
= tevent_req_create(mem_ctx
, &state
, struct req_write_state
);
162 state
->iov
[0].iov_base
= (void *)wb_req
;
163 state
->iov
[0].iov_len
= sizeof(struct winbindd_request
);
165 if (wb_req
->extra_len
!= 0) {
166 state
->iov
[1].iov_base
= (void *)wb_req
->extra_data
.data
;
167 state
->iov
[1].iov_len
= wb_req
->extra_len
;
171 subreq
= writev_send(state
, ev
, queue
, fd
, true, state
->iov
, count
);
172 if (tevent_req_nomem(subreq
, req
)) {
173 return tevent_req_post(req
, ev
);
175 tevent_req_set_callback(subreq
, wb_req_write_done
, req
);
179 static void wb_req_write_done(struct tevent_req
*subreq
)
181 struct tevent_req
*req
= tevent_req_callback_data(
182 subreq
, struct tevent_req
);
183 struct req_write_state
*state
= tevent_req_data(
184 req
, struct req_write_state
);
187 state
->ret
= writev_recv(subreq
, &err
);
189 if (state
->ret
< 0) {
190 tevent_req_error(req
, err
);
193 tevent_req_done(req
);
196 ssize_t
wb_req_write_recv(struct tevent_req
*req
, int *err
)
198 struct req_write_state
*state
= tevent_req_data(
199 req
, struct req_write_state
);
201 if (tevent_req_is_unix_error(req
, err
)) {
207 struct resp_read_state
{
208 struct winbindd_response
*wb_resp
;
212 static ssize_t
wb_resp_more(uint8_t *buf
, size_t buflen
, void *private_data
);
213 static void wb_resp_read_done(struct tevent_req
*subreq
);
215 struct tevent_req
*wb_resp_read_send(TALLOC_CTX
*mem_ctx
,
216 struct tevent_context
*ev
, int fd
)
218 struct tevent_req
*req
, *subreq
;
219 struct resp_read_state
*state
;
221 req
= tevent_req_create(mem_ctx
, &state
, struct resp_read_state
);
226 subreq
= read_packet_send(state
, ev
, fd
, 4, wb_resp_more
, state
);
227 if (tevent_req_nomem(subreq
, req
)) {
228 return tevent_req_post(req
, ev
);
230 tevent_req_set_callback(subreq
, wb_resp_read_done
, req
);
234 static ssize_t
wb_resp_more(uint8_t *buf
, size_t buflen
, void *private_data
)
236 struct winbindd_response
*resp
= (struct winbindd_response
*)buf
;
239 if (resp
->length
< sizeof(struct winbindd_response
)) {
240 DEBUG(0, ("wb_resp_read_len: Invalid response size "
241 "received: %d (expected at least%d)\n",
243 (int)sizeof(struct winbindd_response
)));
247 return resp
->length
- buflen
;
250 static void wb_resp_read_done(struct tevent_req
*subreq
)
252 struct tevent_req
*req
= tevent_req_callback_data(
253 subreq
, struct tevent_req
);
254 struct resp_read_state
*state
= tevent_req_data(
255 req
, struct resp_read_state
);
259 state
->ret
= read_packet_recv(subreq
, state
, &buf
, &err
);
261 if (state
->ret
== -1) {
262 tevent_req_error(req
, err
);
266 state
->wb_resp
= (struct winbindd_response
*)buf
;
268 if (state
->wb_resp
->length
> sizeof(struct winbindd_response
)) {
269 state
->wb_resp
->extra_data
.data
=
270 (char *)buf
+ sizeof(struct winbindd_response
);
272 state
->wb_resp
->extra_data
.data
= NULL
;
274 tevent_req_done(req
);
277 ssize_t
wb_resp_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
278 struct winbindd_response
**presp
, int *err
)
280 struct resp_read_state
*state
= tevent_req_data(
281 req
, struct resp_read_state
);
283 if (tevent_req_is_unix_error(req
, err
)) {
286 *presp
= talloc_move(mem_ctx
, &state
->wb_resp
);
290 struct resp_write_state
{
295 static void wb_resp_write_done(struct tevent_req
*subreq
);
297 struct tevent_req
*wb_resp_write_send(TALLOC_CTX
*mem_ctx
,
298 struct tevent_context
*ev
,
299 struct tevent_queue
*queue
, int fd
,
300 struct winbindd_response
*wb_resp
)
302 struct tevent_req
*req
, *subreq
;
303 struct resp_write_state
*state
;
306 req
= tevent_req_create(mem_ctx
, &state
, struct resp_write_state
);
311 state
->iov
[0].iov_base
= (void *)wb_resp
;
312 state
->iov
[0].iov_len
= sizeof(struct winbindd_response
);
314 if (wb_resp
->length
> sizeof(struct winbindd_response
)) {
315 state
->iov
[1].iov_base
= (void *)wb_resp
->extra_data
.data
;
316 state
->iov
[1].iov_len
=
317 wb_resp
->length
- sizeof(struct winbindd_response
);
321 subreq
= writev_send(state
, ev
, queue
, fd
, true, state
->iov
, count
);
322 if (tevent_req_nomem(subreq
, req
)) {
323 return tevent_req_post(req
, ev
);
325 tevent_req_set_callback(subreq
, wb_resp_write_done
, req
);
329 static void wb_resp_write_done(struct tevent_req
*subreq
)
331 struct tevent_req
*req
= tevent_req_callback_data(
332 subreq
, struct tevent_req
);
333 struct resp_write_state
*state
= tevent_req_data(
334 req
, struct resp_write_state
);
337 state
->ret
= writev_recv(subreq
, &err
);
339 if (state
->ret
< 0) {
340 tevent_req_error(req
, err
);
343 tevent_req_done(req
);
346 ssize_t
wb_resp_write_recv(struct tevent_req
*req
, int *err
)
348 struct resp_write_state
*state
= tevent_req_data(
349 req
, struct resp_write_state
);
351 if (tevent_req_is_unix_error(req
, err
)) {
357 struct wb_simple_trans_state
{
358 struct tevent_context
*ev
;
360 struct winbindd_response
*wb_resp
;
363 static void wb_simple_trans_write_done(struct tevent_req
*subreq
);
364 static void wb_simple_trans_read_done(struct tevent_req
*subreq
);
366 struct tevent_req
*wb_simple_trans_send(TALLOC_CTX
*mem_ctx
,
367 struct tevent_context
*ev
,
368 struct tevent_queue
*queue
, int fd
,
369 struct winbindd_request
*wb_req
)
371 struct tevent_req
*req
, *subreq
;
372 struct wb_simple_trans_state
*state
;
374 req
= tevent_req_create(mem_ctx
, &state
, struct wb_simple_trans_state
);
379 wb_req
->length
= sizeof(struct winbindd_request
);
384 subreq
= wb_req_write_send(state
, ev
, queue
, fd
, wb_req
);
385 if (tevent_req_nomem(subreq
, req
)) {
386 return tevent_req_post(req
, ev
);
388 tevent_req_set_callback(subreq
, wb_simple_trans_write_done
, req
);
393 static void wb_simple_trans_write_done(struct tevent_req
*subreq
)
395 struct tevent_req
*req
= tevent_req_callback_data(
396 subreq
, struct tevent_req
);
397 struct wb_simple_trans_state
*state
= tevent_req_data(
398 req
, struct wb_simple_trans_state
);
402 ret
= wb_req_write_recv(subreq
, &err
);
405 tevent_req_error(req
, err
);
408 subreq
= wb_resp_read_send(state
, state
->ev
, state
->fd
);
409 if (tevent_req_nomem(subreq
, req
)) {
412 tevent_req_set_callback(subreq
, wb_simple_trans_read_done
, req
);
415 static void wb_simple_trans_read_done(struct tevent_req
*subreq
)
417 struct tevent_req
*req
= tevent_req_callback_data(
418 subreq
, struct tevent_req
);
419 struct wb_simple_trans_state
*state
= tevent_req_data(
420 req
, struct wb_simple_trans_state
);
424 ret
= wb_resp_read_recv(subreq
, state
, &state
->wb_resp
, &err
);
427 tevent_req_error(req
, err
);
431 tevent_req_done(req
);
434 int wb_simple_trans_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
435 struct winbindd_response
**presponse
, int *err
)
437 struct wb_simple_trans_state
*state
= tevent_req_data(
438 req
, struct wb_simple_trans_state
);
440 if (tevent_req_is_unix_error(req
, err
)) {
443 *presponse
= talloc_move(mem_ctx
, &state
->wb_resp
);