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 "wbc_async.h"
26 #define DBGC_CLASS DBGC_WINBIND
28 wbcErr
map_wbc_err_from_errno(int error
)
33 return WBC_ERR_AUTH_ERROR
;
35 return WBC_ERR_NO_MEMORY
;
38 return WBC_ERR_UNKNOWN_FAILURE
;
42 bool tevent_req_is_wbcerr(struct tevent_req
*req
, wbcErr
*pwbc_err
)
44 enum tevent_req_state state
;
46 if (!tevent_req_is_error(req
, &state
, &error
)) {
47 *pwbc_err
= WBC_ERR_SUCCESS
;
52 case TEVENT_REQ_USER_ERROR
:
55 case TEVENT_REQ_TIMED_OUT
:
56 *pwbc_err
= WBC_ERR_UNKNOWN_FAILURE
;
58 case TEVENT_REQ_NO_MEMORY
:
59 *pwbc_err
= WBC_ERR_NO_MEMORY
;
62 *pwbc_err
= WBC_ERR_UNKNOWN_FAILURE
;
68 wbcErr
tevent_req_simple_recv_wbcerr(struct tevent_req
*req
)
72 if (tevent_req_is_wbcerr(req
, &wbc_err
)) {
76 return WBC_ERR_SUCCESS
;
79 struct req_read_state
{
80 struct winbindd_request
*wb_req
;
81 size_t max_extra_data
;
84 static ssize_t
wb_req_more(uint8_t *buf
, size_t buflen
, void *private_data
);
85 static void wb_req_read_done(struct tevent_req
*subreq
);
87 struct tevent_req
*wb_req_read_send(TALLOC_CTX
*mem_ctx
,
88 struct tevent_context
*ev
,
89 int fd
, size_t max_extra_data
)
91 struct tevent_req
*result
, *subreq
;
92 struct req_read_state
*state
;
94 result
= tevent_req_create(mem_ctx
, &state
, struct req_read_state
);
98 state
->max_extra_data
= max_extra_data
;
100 subreq
= read_packet_send(state
, ev
, fd
, 4, wb_req_more
, state
);
101 if (subreq
== NULL
) {
105 tevent_req_set_callback(subreq
, wb_req_read_done
, result
);
112 static ssize_t
wb_req_more(uint8_t *buf
, size_t buflen
, void *private_data
)
114 struct req_read_state
*state
= talloc_get_type_abort(
115 private_data
, struct req_read_state
);
116 struct winbindd_request
*req
= (struct winbindd_request
*)buf
;
119 if (req
->length
!= sizeof(struct winbindd_request
)) {
120 DEBUG(0, ("wb_req_read_len: Invalid request size "
121 "received: %d (expected %d)\n",
123 (int)sizeof(struct winbindd_request
)));
126 return sizeof(struct winbindd_request
) - 4;
129 if ((state
->max_extra_data
!= 0)
130 && (req
->extra_len
> state
->max_extra_data
)) {
131 DEBUG(3, ("Got request with %d bytes extra data on "
132 "unprivileged socket\n", (int)req
->extra_len
));
136 return req
->extra_len
;
139 static void wb_req_read_done(struct tevent_req
*subreq
)
141 struct tevent_req
*req
= tevent_req_callback_data(
142 subreq
, struct tevent_req
);
143 struct req_read_state
*state
= tevent_req_data(
144 req
, struct req_read_state
);
149 ret
= read_packet_recv(subreq
, state
, &buf
, &err
);
152 tevent_req_error(req
, map_wbc_err_from_errno(err
));
156 state
->wb_req
= (struct winbindd_request
*)buf
;
158 if (state
->wb_req
->extra_len
!= 0) {
159 state
->wb_req
->extra_data
.data
=
160 (char *)buf
+ sizeof(struct winbindd_request
);
162 state
->wb_req
->extra_data
.data
= NULL
;
164 tevent_req_done(req
);
167 wbcErr
wb_req_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
168 struct winbindd_request
**preq
)
170 struct req_read_state
*state
= tevent_req_data(
171 req
, struct req_read_state
);
174 if (tevent_req_is_wbcerr(req
, &wbc_err
)) {
177 *preq
= talloc_move(mem_ctx
, &state
->wb_req
);
178 return WBC_ERR_SUCCESS
;
181 struct req_write_state
{
185 static void wb_req_write_done(struct tevent_req
*subreq
);
187 struct tevent_req
*wb_req_write_send(TALLOC_CTX
*mem_ctx
,
188 struct tevent_context
*ev
,
189 struct tevent_queue
*queue
, int fd
,
190 struct winbindd_request
*wb_req
)
192 struct tevent_req
*result
, *subreq
;
193 struct req_write_state
*state
;
196 result
= tevent_req_create(mem_ctx
, &state
, struct req_write_state
);
197 if (result
== NULL
) {
201 state
->iov
[0].iov_base
= wb_req
;
202 state
->iov
[0].iov_len
= sizeof(struct winbindd_request
);
204 if (wb_req
->extra_len
!= 0) {
205 state
->iov
[1].iov_base
= wb_req
->extra_data
.data
;
206 state
->iov
[1].iov_len
= wb_req
->extra_len
;
210 subreq
= writev_send(state
, ev
, queue
, fd
, state
->iov
, count
);
211 if (subreq
== NULL
) {
214 tevent_req_set_callback(subreq
, wb_req_write_done
, result
);
222 static void wb_req_write_done(struct tevent_req
*subreq
)
224 struct tevent_req
*req
= tevent_req_callback_data(
225 subreq
, struct tevent_req
);
229 ret
= writev_recv(subreq
, &err
);
232 tevent_req_error(req
, map_wbc_err_from_errno(err
));
235 tevent_req_done(req
);
238 wbcErr
wb_req_write_recv(struct tevent_req
*req
)
240 return tevent_req_simple_recv_wbcerr(req
);
243 struct resp_read_state
{
244 struct winbindd_response
*wb_resp
;
247 static ssize_t
wb_resp_more(uint8_t *buf
, size_t buflen
, void *private_data
);
248 static void wb_resp_read_done(struct tevent_req
*subreq
);
250 struct tevent_req
*wb_resp_read_send(TALLOC_CTX
*mem_ctx
,
251 struct tevent_context
*ev
, int fd
)
253 struct tevent_req
*result
, *subreq
;
254 struct resp_read_state
*state
;
256 result
= tevent_req_create(mem_ctx
, &state
, struct resp_read_state
);
257 if (result
== NULL
) {
261 subreq
= read_packet_send(state
, ev
, fd
, 4, wb_resp_more
, state
);
262 if (subreq
== NULL
) {
265 tevent_req_set_callback(subreq
, wb_resp_read_done
, result
);
273 static ssize_t
wb_resp_more(uint8_t *buf
, size_t buflen
, void *private_data
)
275 struct winbindd_response
*resp
= (struct winbindd_response
*)buf
;
278 if (resp
->length
< sizeof(struct winbindd_response
)) {
279 DEBUG(0, ("wb_resp_read_len: Invalid response size "
280 "received: %d (expected at least%d)\n",
282 (int)sizeof(struct winbindd_response
)));
286 return resp
->length
- buflen
;
289 static void wb_resp_read_done(struct tevent_req
*subreq
)
291 struct tevent_req
*req
= tevent_req_callback_data(
292 subreq
, struct tevent_req
);
293 struct resp_read_state
*state
= tevent_req_data(
294 req
, struct resp_read_state
);
299 ret
= read_packet_recv(subreq
, state
, &buf
, &err
);
302 tevent_req_error(req
, map_wbc_err_from_errno(err
));
306 state
->wb_resp
= (struct winbindd_response
*)buf
;
308 if (state
->wb_resp
->length
> sizeof(struct winbindd_response
)) {
309 state
->wb_resp
->extra_data
.data
=
310 (char *)buf
+ sizeof(struct winbindd_response
);
312 state
->wb_resp
->extra_data
.data
= NULL
;
314 tevent_req_done(req
);
317 wbcErr
wb_resp_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
318 struct winbindd_response
**presp
)
320 struct resp_read_state
*state
= tevent_req_data(
321 req
, struct resp_read_state
);
324 if (tevent_req_is_wbcerr(req
, &wbc_err
)) {
327 *presp
= talloc_move(mem_ctx
, &state
->wb_resp
);
328 return WBC_ERR_SUCCESS
;
331 struct resp_write_state
{
335 static void wb_resp_write_done(struct tevent_req
*subreq
);
337 struct tevent_req
*wb_resp_write_send(TALLOC_CTX
*mem_ctx
,
338 struct tevent_context
*ev
,
339 struct tevent_queue
*queue
, int fd
,
340 struct winbindd_response
*wb_resp
)
342 struct tevent_req
*result
, *subreq
;
343 struct resp_write_state
*state
;
346 result
= tevent_req_create(mem_ctx
, &state
, struct resp_write_state
);
347 if (result
== NULL
) {
351 state
->iov
[0].iov_base
= wb_resp
;
352 state
->iov
[0].iov_len
= sizeof(struct winbindd_response
);
354 if (wb_resp
->length
> sizeof(struct winbindd_response
)) {
355 state
->iov
[1].iov_base
= wb_resp
->extra_data
.data
;
356 state
->iov
[1].iov_len
=
357 wb_resp
->length
- sizeof(struct winbindd_response
);
361 subreq
= writev_send(state
, ev
, queue
, fd
, state
->iov
, count
);
362 if (subreq
== NULL
) {
365 tevent_req_set_callback(subreq
, wb_resp_write_done
, result
);
373 static void wb_resp_write_done(struct tevent_req
*subreq
)
375 struct tevent_req
*req
= tevent_req_callback_data(
376 subreq
, struct tevent_req
);
380 ret
= writev_recv(subreq
, &err
);
383 tevent_req_error(req
, map_wbc_err_from_errno(err
));
386 tevent_req_done(req
);
389 wbcErr
wb_resp_write_recv(struct tevent_req
*req
)
391 return tevent_req_simple_recv_wbcerr(req
);