Adapt wb_reqtrans to "recent" coding conventions
[Samba.git] / source3 / lib / wb_reqtrans.c
blobb64efecef34802f8d1df50d5767e7d8cb4248b90
1 /*
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/>.
22 #include "includes.h"
23 #include "wbc_async.h"
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_WINBIND
28 wbcErr map_wbc_err_from_errno(int error)
30 switch(error) {
31 case EPERM:
32 case EACCES:
33 return WBC_ERR_AUTH_ERROR;
34 case ENOMEM:
35 return WBC_ERR_NO_MEMORY;
36 case EIO:
37 default:
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;
45 uint64_t error;
46 if (!tevent_req_is_error(req, &state, &error)) {
47 *pwbc_err = WBC_ERR_SUCCESS;
48 return false;
51 switch (state) {
52 case TEVENT_REQ_USER_ERROR:
53 *pwbc_err = error;
54 break;
55 case TEVENT_REQ_TIMED_OUT:
56 *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
57 break;
58 case TEVENT_REQ_NO_MEMORY:
59 *pwbc_err = WBC_ERR_NO_MEMORY;
60 break;
61 default:
62 *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
63 break;
65 return true;
68 wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req)
70 wbcErr wbc_err;
72 if (tevent_req_is_wbcerr(req, &wbc_err)) {
73 return 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);
95 if (req == NULL) {
96 return NULL;
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);
105 return 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;
114 if (buflen == 4) {
115 if (req->length != sizeof(struct winbindd_request)) {
116 DEBUG(0, ("wb_req_read_len: Invalid request size "
117 "received: %d (expected %d)\n",
118 (int)req->length,
119 (int)sizeof(struct winbindd_request)));
120 return -1;
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));
129 return -1;
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);
141 int err;
142 ssize_t ret;
143 uint8_t *buf;
145 ret = read_packet_recv(subreq, state, &buf, &err);
146 TALLOC_FREE(subreq);
147 if (ret == -1) {
148 tevent_req_error(req, map_wbc_err_from_errno(err));
149 return;
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);
157 } else {
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);
168 wbcErr wbc_err;
170 if (tevent_req_is_wbcerr(req, &wbc_err)) {
171 return wbc_err;
173 *preq = talloc_move(mem_ctx, &state->wb_req);
174 return WBC_ERR_SUCCESS;
177 struct req_write_state {
178 struct iovec iov[2];
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;
190 int count = 1;
192 req = tevent_req_create(mem_ctx, &state, struct req_write_state);
193 if (req == NULL) {
194 return NULL;
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;
203 count = 2;
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);
211 return 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);
218 int err;
219 ssize_t ret;
221 ret = writev_recv(subreq, &err);
222 TALLOC_FREE(subreq);
223 if (ret < 0) {
224 tevent_req_error(req, map_wbc_err_from_errno(err));
225 return;
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);
249 if (req == NULL) {
250 return NULL;
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);
258 return 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;
265 if (buflen == 4) {
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",
269 (int)resp->length,
270 (int)sizeof(struct winbindd_response)));
271 return -1;
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);
283 uint8_t *buf;
284 int err;
285 ssize_t ret;
287 ret = read_packet_recv(subreq, state, &buf, &err);
288 TALLOC_FREE(subreq);
289 if (ret == -1) {
290 tevent_req_error(req, map_wbc_err_from_errno(err));
291 return;
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);
299 } else {
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);
310 wbcErr wbc_err;
312 if (tevent_req_is_wbcerr(req, &wbc_err)) {
313 return wbc_err;
315 *presp = talloc_move(mem_ctx, &state->wb_resp);
316 return WBC_ERR_SUCCESS;
319 struct resp_write_state {
320 struct iovec iov[2];
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;
332 int count = 1;
334 req = tevent_req_create(mem_ctx, &state, struct resp_write_state);
335 if (req == NULL) {
336 return NULL;
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);
346 count = 2;
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);
354 return 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);
361 int err;
362 ssize_t ret;
364 ret = writev_recv(subreq, &err);
365 TALLOC_FREE(subreq);
366 if (ret < 0) {
367 tevent_req_error(req, map_wbc_err_from_errno(err));
368 return;
370 tevent_req_done(req);
373 wbcErr wb_resp_write_recv(struct tevent_req *req)
375 return tevent_req_simple_recv_wbcerr(req);