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
*req
, *subreq
;
92 struct req_read_state
*state
;
94 req
= 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 (tevent_req_nomem(subreq
, req
)) {
102 return tevent_req_post(req
, ev
);
104 tevent_req_set_callback(subreq
, wb_req_read_done
, req
);
108 static ssize_t
wb_req_more(uint8_t *buf
, size_t buflen
, void *private_data
)
110 struct req_read_state
*state
= talloc_get_type_abort(
111 private_data
, struct req_read_state
);
112 struct winbindd_request
*req
= (struct winbindd_request
*)buf
;
115 if (req
->length
!= sizeof(struct winbindd_request
)) {
116 DEBUG(0, ("wb_req_read_len: Invalid request size "
117 "received: %d (expected %d)\n",
119 (int)sizeof(struct winbindd_request
)));
122 return sizeof(struct winbindd_request
) - 4;
125 if ((state
->max_extra_data
!= 0)
126 && (req
->extra_len
> state
->max_extra_data
)) {
127 DEBUG(3, ("Got request with %d bytes extra data on "
128 "unprivileged socket\n", (int)req
->extra_len
));
132 return req
->extra_len
;
135 static void wb_req_read_done(struct tevent_req
*subreq
)
137 struct tevent_req
*req
= tevent_req_callback_data(
138 subreq
, struct tevent_req
);
139 struct req_read_state
*state
= tevent_req_data(
140 req
, struct req_read_state
);
145 ret
= read_packet_recv(subreq
, state
, &buf
, &err
);
148 tevent_req_error(req
, map_wbc_err_from_errno(err
));
152 state
->wb_req
= (struct winbindd_request
*)buf
;
154 if (state
->wb_req
->extra_len
!= 0) {
155 state
->wb_req
->extra_data
.data
=
156 (char *)buf
+ sizeof(struct winbindd_request
);
158 state
->wb_req
->extra_data
.data
= NULL
;
160 tevent_req_done(req
);
163 wbcErr
wb_req_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
164 struct winbindd_request
**preq
)
166 struct req_read_state
*state
= tevent_req_data(
167 req
, struct req_read_state
);
170 if (tevent_req_is_wbcerr(req
, &wbc_err
)) {
173 *preq
= talloc_move(mem_ctx
, &state
->wb_req
);
174 return WBC_ERR_SUCCESS
;
177 struct req_write_state
{
181 static void wb_req_write_done(struct tevent_req
*subreq
);
183 struct tevent_req
*wb_req_write_send(TALLOC_CTX
*mem_ctx
,
184 struct tevent_context
*ev
,
185 struct tevent_queue
*queue
, int fd
,
186 struct winbindd_request
*wb_req
)
188 struct tevent_req
*req
, *subreq
;
189 struct req_write_state
*state
;
192 req
= tevent_req_create(mem_ctx
, &state
, struct req_write_state
);
197 state
->iov
[0].iov_base
= wb_req
;
198 state
->iov
[0].iov_len
= sizeof(struct winbindd_request
);
200 if (wb_req
->extra_len
!= 0) {
201 state
->iov
[1].iov_base
= wb_req
->extra_data
.data
;
202 state
->iov
[1].iov_len
= wb_req
->extra_len
;
206 subreq
= writev_send(state
, ev
, queue
, fd
, state
->iov
, count
);
207 if (tevent_req_nomem(subreq
, req
)) {
208 return tevent_req_post(req
, ev
);
210 tevent_req_set_callback(subreq
, wb_req_write_done
, req
);
214 static void wb_req_write_done(struct tevent_req
*subreq
)
216 struct tevent_req
*req
= tevent_req_callback_data(
217 subreq
, struct tevent_req
);
221 ret
= writev_recv(subreq
, &err
);
224 tevent_req_error(req
, map_wbc_err_from_errno(err
));
227 tevent_req_done(req
);
230 wbcErr
wb_req_write_recv(struct tevent_req
*req
)
232 return tevent_req_simple_recv_wbcerr(req
);
235 struct resp_read_state
{
236 struct winbindd_response
*wb_resp
;
239 static ssize_t
wb_resp_more(uint8_t *buf
, size_t buflen
, void *private_data
);
240 static void wb_resp_read_done(struct tevent_req
*subreq
);
242 struct tevent_req
*wb_resp_read_send(TALLOC_CTX
*mem_ctx
,
243 struct tevent_context
*ev
, int fd
)
245 struct tevent_req
*req
, *subreq
;
246 struct resp_read_state
*state
;
248 req
= tevent_req_create(mem_ctx
, &state
, struct resp_read_state
);
253 subreq
= read_packet_send(state
, ev
, fd
, 4, wb_resp_more
, state
);
254 if (tevent_req_nomem(subreq
, req
)) {
255 return tevent_req_post(req
, ev
);
257 tevent_req_set_callback(subreq
, wb_resp_read_done
, req
);
261 static ssize_t
wb_resp_more(uint8_t *buf
, size_t buflen
, void *private_data
)
263 struct winbindd_response
*resp
= (struct winbindd_response
*)buf
;
266 if (resp
->length
< sizeof(struct winbindd_response
)) {
267 DEBUG(0, ("wb_resp_read_len: Invalid response size "
268 "received: %d (expected at least%d)\n",
270 (int)sizeof(struct winbindd_response
)));
274 return resp
->length
- buflen
;
277 static void wb_resp_read_done(struct tevent_req
*subreq
)
279 struct tevent_req
*req
= tevent_req_callback_data(
280 subreq
, struct tevent_req
);
281 struct resp_read_state
*state
= tevent_req_data(
282 req
, struct resp_read_state
);
287 ret
= read_packet_recv(subreq
, state
, &buf
, &err
);
290 tevent_req_error(req
, map_wbc_err_from_errno(err
));
294 state
->wb_resp
= (struct winbindd_response
*)buf
;
296 if (state
->wb_resp
->length
> sizeof(struct winbindd_response
)) {
297 state
->wb_resp
->extra_data
.data
=
298 (char *)buf
+ sizeof(struct winbindd_response
);
300 state
->wb_resp
->extra_data
.data
= NULL
;
302 tevent_req_done(req
);
305 wbcErr
wb_resp_read_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
306 struct winbindd_response
**presp
)
308 struct resp_read_state
*state
= tevent_req_data(
309 req
, struct resp_read_state
);
312 if (tevent_req_is_wbcerr(req
, &wbc_err
)) {
315 *presp
= talloc_move(mem_ctx
, &state
->wb_resp
);
316 return WBC_ERR_SUCCESS
;
319 struct resp_write_state
{
323 static void wb_resp_write_done(struct tevent_req
*subreq
);
325 struct tevent_req
*wb_resp_write_send(TALLOC_CTX
*mem_ctx
,
326 struct tevent_context
*ev
,
327 struct tevent_queue
*queue
, int fd
,
328 struct winbindd_response
*wb_resp
)
330 struct tevent_req
*req
, *subreq
;
331 struct resp_write_state
*state
;
334 req
= tevent_req_create(mem_ctx
, &state
, struct resp_write_state
);
339 state
->iov
[0].iov_base
= wb_resp
;
340 state
->iov
[0].iov_len
= sizeof(struct winbindd_response
);
342 if (wb_resp
->length
> sizeof(struct winbindd_response
)) {
343 state
->iov
[1].iov_base
= wb_resp
->extra_data
.data
;
344 state
->iov
[1].iov_len
=
345 wb_resp
->length
- sizeof(struct winbindd_response
);
349 subreq
= writev_send(state
, ev
, queue
, fd
, state
->iov
, count
);
350 if (tevent_req_nomem(subreq
, req
)) {
351 return tevent_req_post(req
, ev
);
353 tevent_req_set_callback(subreq
, wb_resp_write_done
, req
);
357 static void wb_resp_write_done(struct tevent_req
*subreq
)
359 struct tevent_req
*req
= tevent_req_callback_data(
360 subreq
, struct tevent_req
);
364 ret
= writev_recv(subreq
, &err
);
367 tevent_req_error(req
, map_wbc_err_from_errno(err
));
370 tevent_req_done(req
);
373 wbcErr
wb_resp_write_recv(struct tevent_req
*req
)
375 return tevent_req_simple_recv_wbcerr(req
);