root/source3/lib/wb_reqtrans.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. map_wbc_err_from_errno
  2. tevent_req_is_wbcerr
  3. tevent_req_simple_recv_wbcerr
  4. wb_req_read_send
  5. wb_req_more
  6. wb_req_read_done
  7. wb_req_read_recv
  8. wb_req_write_send
  9. wb_req_write_done
  10. wb_req_write_recv
  11. wb_resp_read_send
  12. wb_resp_more
  13. wb_resp_read_done
  14. wb_resp_read_recv
  15. wb_resp_write_send
  16. wb_resp_write_done
  17. wb_resp_write_recv

   1 /*
   2    Unix SMB/CIFS implementation.
   3 
   4    Async transfer of winbindd_request and _response structs
   5 
   6    Copyright (C) Volker Lendecke 2008
   7 
   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.
  12 
  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.
  17 
  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/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "wbc_async.h"
  24 
  25 #undef DBGC_CLASS
  26 #define DBGC_CLASS DBGC_WINBIND
  27 
  28 wbcErr map_wbc_err_from_errno(int error)
     /* [<][>][^][v][top][bottom][index][help] */
  29 {
  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;
  39         }
  40 }
  41 
  42 bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err)
     /* [<][>][^][v][top][bottom][index][help] */
  43 {
  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;
  49         }
  50 
  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;
  64         }
  65         return true;
  66 }
  67 
  68 wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
  69 {
  70         wbcErr wbc_err;
  71 
  72         if (tevent_req_is_wbcerr(req, &wbc_err)) {
  73                 return wbc_err;
  74         }
  75 
  76         return WBC_ERR_SUCCESS;
  77 }
  78 
  79 struct req_read_state {
  80         struct winbindd_request *wb_req;
  81         size_t max_extra_data;
  82 };
  83 
  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);
  86 
  87 struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  88                                     struct tevent_context *ev,
  89                                     int fd, size_t max_extra_data)
  90 {
  91         struct tevent_req *result, *subreq;
  92         struct req_read_state *state;
  93 
  94         result = tevent_req_create(mem_ctx, &state, struct req_read_state);
  95         if (result == NULL) {
  96                 return NULL;
  97         }
  98         state->max_extra_data = max_extra_data;
  99 
 100         subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
 101         if (subreq == NULL) {
 102                 goto nomem;
 103         }
 104 
 105         tevent_req_set_callback(subreq, wb_req_read_done, result);
 106         return result;
 107  nomem:
 108         TALLOC_FREE(result);
 109         return NULL;
 110 }
 111 
 112 static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
 113 {
 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;
 117 
 118         if (buflen == 4) {
 119                 if (req->length != sizeof(struct winbindd_request)) {
 120                         DEBUG(0, ("wb_req_read_len: Invalid request size "
 121                                   "received: %d (expected %d)\n",
 122                                   (int)req->length,
 123                                   (int)sizeof(struct winbindd_request)));
 124                         return -1;
 125                 }
 126                 return sizeof(struct winbindd_request) - 4;
 127         }
 128 
 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));
 133                 return -1;
 134         }
 135 
 136         return req->extra_len;
 137 }
 138 
 139 static void wb_req_read_done(struct tevent_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 140 {
 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);
 145         int err;
 146         ssize_t ret;
 147         uint8_t *buf;
 148 
 149         ret = read_packet_recv(subreq, state, &buf, &err);
 150         TALLOC_FREE(subreq);
 151         if (ret == -1) {
 152                 tevent_req_error(req, map_wbc_err_from_errno(err));
 153                 return;
 154         }
 155 
 156         state->wb_req = (struct winbindd_request *)buf;
 157 
 158         if (state->wb_req->extra_len != 0) {
 159                 state->wb_req->extra_data.data =
 160                         (char *)buf + sizeof(struct winbindd_request);
 161         } else {
 162                 state->wb_req->extra_data.data = NULL;
 163         }
 164         tevent_req_done(req);
 165 }
 166 
 167 wbcErr wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 168                         struct winbindd_request **preq)
 169 {
 170         struct req_read_state *state = tevent_req_data(
 171                 req, struct req_read_state);
 172         wbcErr wbc_err;
 173 
 174         if (tevent_req_is_wbcerr(req, &wbc_err)) {
 175                 return wbc_err;
 176         }
 177         *preq = talloc_move(mem_ctx, &state->wb_req);
 178         return WBC_ERR_SUCCESS;
 179 }
 180 
 181 struct req_write_state {
 182         struct iovec iov[2];
 183 };
 184 
 185 static void wb_req_write_done(struct tevent_req *subreq);
 186 
 187 struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 188                                      struct tevent_context *ev,
 189                                      struct tevent_queue *queue, int fd,
 190                                      struct winbindd_request *wb_req)
 191 {
 192         struct tevent_req *result, *subreq;
 193         struct req_write_state *state;
 194         int count = 1;
 195 
 196         result = tevent_req_create(mem_ctx, &state, struct req_write_state);
 197         if (result == NULL) {
 198                 return NULL;
 199         }
 200 
 201         state->iov[0].iov_base = wb_req;
 202         state->iov[0].iov_len = sizeof(struct winbindd_request);
 203 
 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;
 207                 count = 2;
 208         }
 209 
 210         subreq = writev_send(state, ev, queue, fd, state->iov, count);
 211         if (subreq == NULL) {
 212                 goto fail;
 213         }
 214         tevent_req_set_callback(subreq, wb_req_write_done, result);
 215         return result;
 216 
 217  fail:
 218         TALLOC_FREE(result);
 219         return NULL;
 220 }
 221 
 222 static void wb_req_write_done(struct tevent_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 223 {
 224         struct tevent_req *req = tevent_req_callback_data(
 225                 subreq, struct tevent_req);
 226         int err;
 227         ssize_t ret;
 228 
 229         ret = writev_recv(subreq, &err);
 230         TALLOC_FREE(subreq);
 231         if (ret < 0) {
 232                 tevent_req_error(req, map_wbc_err_from_errno(err));
 233                 return;
 234         }
 235         tevent_req_done(req);
 236 }
 237 
 238 wbcErr wb_req_write_recv(struct tevent_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
 239 {
 240         return tevent_req_simple_recv_wbcerr(req);
 241 }
 242 
 243 struct resp_read_state {
 244         struct winbindd_response *wb_resp;
 245 };
 246 
 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);
 249 
 250 struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 251                                      struct tevent_context *ev, int fd)
 252 {
 253         struct tevent_req *result, *subreq;
 254         struct resp_read_state *state;
 255 
 256         result = tevent_req_create(mem_ctx, &state, struct resp_read_state);
 257         if (result == NULL) {
 258                 return NULL;
 259         }
 260 
 261         subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
 262         if (subreq == NULL) {
 263                 goto nomem;
 264         }
 265         tevent_req_set_callback(subreq, wb_resp_read_done, result);
 266         return result;
 267 
 268  nomem:
 269         TALLOC_FREE(result);
 270         return NULL;
 271 }
 272 
 273 static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
     /* [<][>][^][v][top][bottom][index][help] */
 274 {
 275         struct winbindd_response *resp = (struct winbindd_response *)buf;
 276 
 277         if (buflen == 4) {
 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",
 281                                   (int)resp->length,
 282                                   (int)sizeof(struct winbindd_response)));
 283                         return -1;
 284                 }
 285         }
 286         return resp->length - buflen;
 287 }
 288 
 289 static void wb_resp_read_done(struct tevent_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 290 {
 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);
 295         uint8_t *buf;
 296         int err;
 297         ssize_t ret;
 298 
 299         ret = read_packet_recv(subreq, state, &buf, &err);
 300         TALLOC_FREE(subreq);
 301         if (ret == -1) {
 302                 tevent_req_error(req, map_wbc_err_from_errno(err));
 303                 return;
 304         }
 305 
 306         state->wb_resp = (struct winbindd_response *)buf;
 307 
 308         if (state->wb_resp->length > sizeof(struct winbindd_response)) {
 309                 state->wb_resp->extra_data.data =
 310                         (char *)buf + sizeof(struct winbindd_response);
 311         } else {
 312                 state->wb_resp->extra_data.data = NULL;
 313         }
 314         tevent_req_done(req);
 315 }
 316 
 317 wbcErr wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 318                          struct winbindd_response **presp)
 319 {
 320         struct resp_read_state *state = tevent_req_data(
 321                 req, struct resp_read_state);
 322         wbcErr wbc_err;
 323 
 324         if (tevent_req_is_wbcerr(req, &wbc_err)) {
 325                 return wbc_err;
 326         }
 327         *presp = talloc_move(mem_ctx, &state->wb_resp);
 328         return WBC_ERR_SUCCESS;
 329 }
 330 
 331 struct resp_write_state {
 332         struct iovec iov[2];
 333 };
 334 
 335 static void wb_resp_write_done(struct tevent_req *subreq);
 336 
 337 struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 338                                       struct tevent_context *ev,
 339                                       struct tevent_queue *queue, int fd,
 340                                       struct winbindd_response *wb_resp)
 341 {
 342         struct tevent_req *result, *subreq;
 343         struct resp_write_state *state;
 344         int count = 1;
 345 
 346         result = tevent_req_create(mem_ctx, &state, struct resp_write_state);
 347         if (result == NULL) {
 348                 return NULL;
 349         }
 350 
 351         state->iov[0].iov_base = wb_resp;
 352         state->iov[0].iov_len = sizeof(struct winbindd_response);
 353 
 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);
 358                 count = 2;
 359         }
 360 
 361         subreq = writev_send(state, ev, queue, fd, state->iov, count);
 362         if (subreq == NULL) {
 363                 goto fail;
 364         }
 365         tevent_req_set_callback(subreq, wb_resp_write_done, result);
 366         return result;
 367 
 368  fail:
 369         TALLOC_FREE(result);
 370         return NULL;
 371 }
 372 
 373 static void wb_resp_write_done(struct tevent_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 374 {
 375         struct tevent_req *req = tevent_req_callback_data(
 376                 subreq, struct tevent_req);
 377         int err;
 378         ssize_t ret;
 379 
 380         ret = writev_recv(subreq, &err);
 381         TALLOC_FREE(subreq);
 382         if (ret < 0) {
 383                 tevent_req_error(req, map_wbc_err_from_errno(err));
 384                 return;
 385         }
 386         tevent_req_done(req);
 387 }
 388 
 389 wbcErr wb_resp_write_recv(struct tevent_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
 390 {
 391         return tevent_req_simple_recv_wbcerr(req);
 392 }

/* [<][>][^][v][top][bottom][index][help] */