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 struct req_read_state {
29 struct winbindd_request *wb_req;
30 size_t max_extra_data;
33 bool async_req_is_wbcerr(struct async_req *req, wbcErr *pwbc_err)
35 enum async_req_state state;
37 if (!async_req_is_error(req, &state, &error)) {
38 *pwbc_err = WBC_ERR_SUCCESS;
43 case ASYNC_REQ_USER_ERROR:
46 case ASYNC_REQ_TIMED_OUT:
47 *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
49 case ASYNC_REQ_NO_MEMORY:
50 *pwbc_err = WBC_ERR_NO_MEMORY;
53 *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
59 wbcErr map_wbc_err_from_errno(int error)
64 return WBC_ERR_AUTH_ERROR;
66 return WBC_ERR_NO_MEMORY;
69 return WBC_ERR_UNKNOWN_FAILURE;
73 wbcErr async_req_simple_recv_wbcerr(struct async_req *req)
77 if (async_req_is_wbcerr(req, &wbc_err)) {
81 return WBC_ERR_SUCCESS;
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 async_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
88 struct tevent_context *ev,
89 int fd, size_t max_extra_data)
91 struct async_req *result;
92 struct tevent_req *subreq;
93 struct req_read_state *state;
95 if (!async_req_setup(mem_ctx, &result, &state,
96 struct req_read_state)) {
99 state->max_extra_data = max_extra_data;
101 subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
102 if (subreq == NULL) {
106 subreq->async.fn = wb_req_read_done;
107 subreq->async.private_data = result;
114 static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
116 struct req_read_state *state = talloc_get_type_abort(
117 private_data, struct req_read_state);
118 struct winbindd_request *req = (struct winbindd_request *)buf;
121 if (req->length != sizeof(struct winbindd_request)) {
122 DEBUG(0, ("wb_req_read_len: Invalid request size "
123 "received: %d (expected %d)\n",
125 (int)sizeof(struct winbindd_request)));
128 return sizeof(struct winbindd_request) - 4;
131 if ((state->max_extra_data != 0)
132 && (req->extra_len > state->max_extra_data)) {
133 DEBUG(3, ("Got request with %d bytes extra data on "
134 "unprivileged socket\n", (int)req->extra_len));
138 return req->extra_len;
141 static void wb_req_read_done(struct tevent_req *subreq)
143 struct async_req *req = talloc_get_type_abort(
144 subreq->async.private_data, struct async_req);
145 struct req_read_state *state = talloc_get_type_abort(
146 req->private_data, struct req_read_state);
151 ret = read_packet_recv(subreq, state, &buf, &err);
154 async_req_error(req, map_wbc_err_from_errno(err));
158 state->wb_req = (struct winbindd_request *)buf;
160 if (state->wb_req->extra_len != 0) {
161 state->wb_req->extra_data.data =
162 (char *)buf + sizeof(struct winbindd_request);
164 state->wb_req->extra_data.data = NULL;
169 wbcErr wb_req_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
170 struct winbindd_request **preq)
172 struct req_read_state *state = talloc_get_type_abort(
173 req->private_data, struct req_read_state);
176 if (async_req_is_wbcerr(req, &wbc_err)) {
179 *preq = talloc_move(mem_ctx, &state->wb_req);
180 return WBC_ERR_SUCCESS;
183 struct req_write_state {
187 static void wb_req_write_done(struct tevent_req *subreq);
189 struct async_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
190 struct tevent_context *ev, int fd,
191 struct winbindd_request *wb_req)
193 struct async_req *result;
194 struct tevent_req *subreq;
195 struct req_write_state *state;
198 if (!async_req_setup(mem_ctx, &result, &state,
199 struct req_write_state)) {
203 state->iov[0].iov_base = wb_req;
204 state->iov[0].iov_len = sizeof(struct winbindd_request);
206 if (wb_req->extra_len != 0) {
207 state->iov[1].iov_base = wb_req->extra_data.data;
208 state->iov[1].iov_len = wb_req->extra_len;
212 subreq = writev_send(state, ev, fd, state->iov, count);
213 if (subreq == NULL) {
216 subreq->async.fn = wb_req_write_done;
217 subreq->async.private_data = result;
225 static void wb_req_write_done(struct tevent_req *subreq)
227 struct async_req *req = talloc_get_type_abort(
228 subreq->async.private_data, struct async_req);
232 ret = writev_recv(subreq, &err);
235 async_req_error(req, map_wbc_err_from_errno(err));
241 wbcErr wb_req_write_recv(struct async_req *req)
243 return async_req_simple_recv_wbcerr(req);
246 struct resp_read_state {
247 struct winbindd_response *wb_resp;
250 static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
251 static void wb_resp_read_done(struct tevent_req *subreq);
253 struct async_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
254 struct tevent_context *ev, int fd)
256 struct async_req *result;
257 struct tevent_req *subreq;
258 struct resp_read_state *state;
260 if (!async_req_setup(mem_ctx, &result, &state,
261 struct resp_read_state)) {
265 subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
266 if (subreq == NULL) {
269 subreq->async.fn = wb_resp_read_done;
270 subreq->async.private_data = result;
278 static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
280 struct winbindd_response *resp = (struct winbindd_response *)buf;
283 if (resp->length < sizeof(struct winbindd_response)) {
284 DEBUG(0, ("wb_resp_read_len: Invalid response size "
285 "received: %d (expected at least%d)\n",
287 (int)sizeof(struct winbindd_response)));
291 return resp->length - buflen;
294 static void wb_resp_read_done(struct tevent_req *subreq)
296 struct async_req *req = talloc_get_type_abort(
297 subreq->async.private_data, struct async_req);
298 struct resp_read_state *state = talloc_get_type_abort(
299 req->private_data, struct resp_read_state);
304 ret = read_packet_recv(subreq, state, &buf, &err);
307 async_req_error(req, map_wbc_err_from_errno(err));
311 state->wb_resp = (struct winbindd_response *)buf;
313 if (state->wb_resp->length > sizeof(struct winbindd_response)) {
314 state->wb_resp->extra_data.data =
315 (char *)buf + sizeof(struct winbindd_response);
317 state->wb_resp->extra_data.data = NULL;
322 wbcErr wb_resp_read_recv(struct async_req *req, TALLOC_CTX *mem_ctx,
323 struct winbindd_response **presp)
325 struct resp_read_state *state = talloc_get_type_abort(
326 req->private_data, struct resp_read_state);
329 if (async_req_is_wbcerr(req, &wbc_err)) {
332 *presp = talloc_move(mem_ctx, &state->wb_resp);
333 return WBC_ERR_SUCCESS;
336 struct resp_write_state {
340 static void wb_resp_write_done(struct tevent_req *subreq);
342 struct async_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
343 struct tevent_context *ev, int fd,
344 struct winbindd_response *wb_resp)
346 struct async_req *result;
347 struct tevent_req *subreq;
348 struct resp_write_state *state;
351 if (!async_req_setup(mem_ctx, &result, &state,
352 struct resp_write_state)) {
356 state->iov[0].iov_base = wb_resp;
357 state->iov[0].iov_len = sizeof(struct winbindd_response);
359 if (wb_resp->length > sizeof(struct winbindd_response)) {
360 state->iov[1].iov_base = wb_resp->extra_data.data;
361 state->iov[1].iov_len =
362 wb_resp->length - sizeof(struct winbindd_response);
366 subreq = writev_send(state, ev, fd, state->iov, count);
367 if (subreq == NULL) {
370 subreq->async.fn = wb_resp_write_done;
371 subreq->async.private_data = result;
379 static void wb_resp_write_done(struct tevent_req *subreq)
381 struct async_req *req = talloc_get_type_abort(
382 subreq->async.private_data, struct async_req);
386 ret = writev_recv(subreq, &err);
389 async_req_error(req, map_wbc_err_from_errno(err));
395 wbcErr wb_resp_write_recv(struct async_req *req)
397 return async_req_simple_recv_wbcerr(req);