async_sock: Use unix errnos instead of NTSTATUS
[ira/wip.git] / lib / async_req / async_sock.c
1 /*
2    Unix SMB/CIFS implementation.
3    async socket syscalls
4    Copyright (C) Volker Lendecke 2008
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "lib/talloc/talloc.h"
22 #include "lib/tevent/tevent.h"
23 #include "lib/async_req/async_req.h"
24 #include "lib/async_req/async_sock.h"
25 #include <fcntl.h>
26
27 #ifndef TALLOC_FREE
28 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
29 #endif
30
31 /**
32  * Discriminator for async_syscall_state
33  */
34 enum async_syscall_type {
35         ASYNC_SYSCALL_SEND,
36         ASYNC_SYSCALL_SENDALL,
37         ASYNC_SYSCALL_RECV,
38         ASYNC_SYSCALL_RECVALL,
39         ASYNC_SYSCALL_CONNECT
40 };
41
42 /**
43  * Holder for syscall arguments and the result
44  */
45
46 struct async_syscall_state {
47         enum async_syscall_type syscall_type;
48         struct tevent_fd *fde;
49
50         union {
51                 struct param_send {
52                         int fd;
53                         const void *buffer;
54                         size_t length;
55                         int flags;
56                 } param_send;
57                 struct param_sendall {
58                         int fd;
59                         const void *buffer;
60                         size_t length;
61                         int flags;
62                         size_t sent;
63                 } param_sendall;
64                 struct param_recv {
65                         int fd;
66                         void *buffer;
67                         size_t length;
68                         int flags;
69                 } param_recv;
70                 struct param_recvall {
71                         int fd;
72                         void *buffer;
73                         size_t length;
74                         int flags;
75                         size_t received;
76                 } param_recvall;
77                 struct param_connect {
78                         /**
79                          * connect needs to be done on a nonblocking
80                          * socket. Keep the old flags around
81                          */
82                         long old_sockflags;
83                         int fd;
84                         const struct sockaddr *address;
85                         socklen_t address_len;
86                 } param_connect;
87         } param;
88
89         union {
90                 ssize_t result_ssize_t;
91                 size_t result_size_t;
92                 int result_int;
93         } result;
94         int sys_errno;
95 };
96
97 /**
98  * @brief Map async_req states to unix-style errnos
99  * @param[in]  req      The async req to get the state from
100  * @param[out] err      Pointer to take the unix-style errno
101  *
102  * @return true if the async_req is in an error state, false otherwise
103  */
104
105 bool async_req_is_errno(struct async_req *req, int *err)
106 {
107         enum async_req_state state;
108         uint64_t error;
109
110         if (!async_req_is_error(req, &state, &error)) {
111                 return false;
112         }
113
114         switch (state) {
115         case ASYNC_REQ_USER_ERROR:
116                 *err = (int)error;
117                 break;
118         case ASYNC_REQ_TIMED_OUT:
119                 *err = ETIME;
120                 break;
121         case ASYNC_REQ_NO_MEMORY:
122                 *err = ENOMEM;
123                 break;
124         default:
125                 *err = EIO;
126                 break;
127         }
128         return true;
129 }
130
131 int async_req_simple_recv_errno(struct async_req *req)
132 {
133         int err;
134
135         if (async_req_is_errno(req, &err)) {
136                 return err;
137         }
138
139         return 0;
140 }
141
142 /**
143  * @brief Create a new async syscall req
144  * @param[in] mem_ctx   The memory context to hang the result off
145  * @param[in] ev        The event context to work from
146  * @param[in] type      Which syscall will this be
147  * @param[in] pstate    Where to put the newly created private_data state
148  * @retval The new request
149  *
150  * This is a helper function to prepare a new struct async_req with an
151  * associated struct async_syscall_state. The async_syscall_state will be put
152  * into the async_req as private_data.
153  */
154
155 static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
156                                            struct tevent_context *ev,
157                                            enum async_syscall_type type,
158                                            struct async_syscall_state **pstate)
159 {
160         struct async_req *result;
161         struct async_syscall_state *state;
162
163         if (!async_req_setup(mem_ctx, &result, &state,
164                              struct async_syscall_state)) {
165                 return NULL;
166         }
167         state->syscall_type = type;
168
169         result->private_data = state;
170
171         *pstate = state;
172
173         return result;
174 }
175
176 /**
177  * @brief Create a new async syscall req based on a fd
178  * @param[in] mem_ctx   The memory context to hang the result off
179  * @param[in] ev        The event context to work from
180  * @param[in] type      Which syscall will this be
181  * @param[in] fd        The file descriptor we work on
182  * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in?
183  * @param[in] fde_cb    The callback function for the file descriptor event
184  * @param[in] pstate    Where to put the newly created private_data state
185  * @retval The new request
186  *
187  * This is a helper function to prepare a new struct async_req with an
188  * associated struct async_syscall_state and an associated file descriptor
189  * event.
190  */
191
192 static struct async_req *async_fde_syscall_new(
193         TALLOC_CTX *mem_ctx,
194         struct tevent_context *ev,
195         enum async_syscall_type type,
196         int fd,
197         uint16_t fde_flags,
198         void (*fde_cb)(struct tevent_context *ev,
199                        struct tevent_fd *fde, uint16_t flags,
200                        void *priv),
201         struct async_syscall_state **pstate)
202 {
203         struct async_req *result;
204         struct async_syscall_state *state;
205
206         result = async_syscall_new(mem_ctx, ev, type, &state);
207         if (result == NULL) {
208                 return NULL;
209         }
210
211         state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result);
212         if (state->fde == NULL) {
213                 TALLOC_FREE(result);
214                 return NULL;
215         }
216         *pstate = state;
217         return result;
218 }
219
220 /**
221  * Retrieve a ssize_t typed result from an async syscall
222  * @param[in] req       The syscall that has just finished
223  * @param[out] perrno   Where to put the syscall's errno
224  * @retval The return value from the asynchronously called syscall
225  */
226
227 ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
228 {
229         struct async_syscall_state *state = talloc_get_type_abort(
230                 req->private_data, struct async_syscall_state);
231
232         *perrno = state->sys_errno;
233         return state->result.result_ssize_t;
234 }
235
236 /**
237  * Retrieve a size_t typed result from an async syscall
238  * @param[in] req       The syscall that has just finished
239  * @param[out] perrno   Where to put the syscall's errno
240  * @retval The return value from the asynchronously called syscall
241  */
242
243 size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
244 {
245         struct async_syscall_state *state = talloc_get_type_abort(
246                 req->private_data, struct async_syscall_state);
247
248         *perrno = state->sys_errno;
249         return state->result.result_size_t;
250 }
251
252 /**
253  * Retrieve a int typed result from an async syscall
254  * @param[in] req       The syscall that has just finished
255  * @param[out] perrno   Where to put the syscall's errno
256  * @retval The return value from the asynchronously called syscall
257  */
258
259 int async_syscall_result_int(struct async_req *req, int *perrno)
260 {
261         struct async_syscall_state *state = talloc_get_type_abort(
262                 req->private_data, struct async_syscall_state);
263
264         *perrno = state->sys_errno;
265         return state->result.result_int;
266 }
267
268 /**
269  * fde event handler for the "send" syscall
270  * @param[in] ev        The event context that sent us here
271  * @param[in] fde       The file descriptor event associated with the send
272  * @param[in] flags     Can only be TEVENT_FD_WRITE here
273  * @param[in] priv      private data, "struct async_req *" in this case
274  */
275
276 static void async_send_callback(struct tevent_context *ev,
277                                 struct tevent_fd *fde, uint16_t flags,
278                                 void *priv)
279 {
280         struct async_req *req = talloc_get_type_abort(
281                 priv, struct async_req);
282         struct async_syscall_state *state = talloc_get_type_abort(
283                 req->private_data, struct async_syscall_state);
284         struct param_send *p = &state->param.param_send;
285
286         if (state->syscall_type != ASYNC_SYSCALL_SEND) {
287                 async_req_error(req, EIO);
288                 return;
289         }
290
291         state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
292                                             p->flags);
293         state->sys_errno = errno;
294
295         TALLOC_FREE(state->fde);
296
297         async_req_done(req);
298 }
299
300 /**
301  * Async version of send(2)
302  * @param[in] mem_ctx   The memory context to hang the result off
303  * @param[in] ev        The event context to work from
304  * @param[in] fd        The socket to send to
305  * @param[in] buffer    The buffer to send
306  * @param[in] length    How many bytes to send
307  * @param[in] flags     flags passed to send(2)
308  *
309  * This function is a direct counterpart of send(2)
310  */
311
312 struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
313                              int fd, const void *buffer, size_t length,
314                              int flags)
315 {
316         struct async_req *result;
317         struct async_syscall_state *state;
318
319         result = async_fde_syscall_new(
320                 mem_ctx, ev, ASYNC_SYSCALL_SEND,
321                 fd, TEVENT_FD_WRITE, async_send_callback,
322                 &state);
323         if (result == NULL) {
324                 return NULL;
325         }
326
327         state->param.param_send.fd = fd;
328         state->param.param_send.buffer = buffer;
329         state->param.param_send.length = length;
330         state->param.param_send.flags = flags;
331
332         return result;
333 }
334
335 /**
336  * fde event handler for the "sendall" syscall group
337  * @param[in] ev        The event context that sent us here
338  * @param[in] fde       The file descriptor event associated with the send
339  * @param[in] flags     Can only be TEVENT_FD_WRITE here
340  * @param[in] priv      private data, "struct async_req *" in this case
341  */
342
343 static void async_sendall_callback(struct tevent_context *ev,
344                                    struct tevent_fd *fde, uint16_t flags,
345                                    void *priv)
346 {
347         struct async_req *req = talloc_get_type_abort(
348                 priv, struct async_req);
349         struct async_syscall_state *state = talloc_get_type_abort(
350                 req->private_data, struct async_syscall_state);
351         struct param_sendall *p = &state->param.param_sendall;
352
353         if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
354                 async_req_error(req, EIO);
355                 return;
356         }
357
358         state->result.result_ssize_t = send(p->fd,
359                                             (const char *)p->buffer + p->sent,
360                                             p->length - p->sent, p->flags);
361         state->sys_errno = errno;
362
363         if (state->result.result_ssize_t == -1) {
364                 async_req_error(req, state->sys_errno);
365                 return;
366         }
367
368         if (state->result.result_ssize_t == 0) {
369                 async_req_error(req, EOF);
370                 return;
371         }
372
373         p->sent += state->result.result_ssize_t;
374         if (p->sent > p->length) {
375                 async_req_error(req, EIO);
376                 return;
377         }
378
379         if (p->sent == p->length) {
380                 TALLOC_FREE(state->fde);
381                 async_req_done(req);
382         }
383 }
384
385 /**
386  * @brief Send all bytes to a socket
387  * @param[in] mem_ctx   The memory context to hang the result off
388  * @param[in] ev        The event context to work from
389  * @param[in] fd        The socket to send to
390  * @param[in] buffer    The buffer to send
391  * @param[in] length    How many bytes to send
392  * @param[in] flags     flags passed to send(2)
393  *
394  * async_sendall calls send(2) as long as it is necessary to send all of the
395  * "length" bytes
396  */
397
398 struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
399                                int fd, const void *buffer, size_t length,
400                                int flags)
401 {
402         struct async_req *result;
403         struct async_syscall_state *state;
404
405         result = async_fde_syscall_new(
406                 mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
407                 fd, TEVENT_FD_WRITE, async_sendall_callback,
408                 &state);
409         if (result == NULL) {
410                 return NULL;
411         }
412
413         state->param.param_sendall.fd = fd;
414         state->param.param_sendall.buffer = buffer;
415         state->param.param_sendall.length = length;
416         state->param.param_sendall.flags = flags;
417         state->param.param_sendall.sent = 0;
418
419         return result;
420 }
421
422 ssize_t sendall_recv(struct async_req *req, int *perr)
423 {
424         struct async_syscall_state *state = talloc_get_type_abort(
425                 req->private_data, struct async_syscall_state);
426         int err;
427
428         err = async_req_simple_recv_errno(req);
429
430         if (err != 0) {
431                 *perr = err;
432                 return -1;
433         }
434
435         return state->result.result_ssize_t;
436 }
437
438 /**
439  * fde event handler for the "recv" syscall
440  * @param[in] ev        The event context that sent us here
441  * @param[in] fde       The file descriptor event associated with the recv
442  * @param[in] flags     Can only be TEVENT_FD_READ here
443  * @param[in] priv      private data, "struct async_req *" in this case
444  */
445
446 static void async_recv_callback(struct tevent_context *ev,
447                                 struct tevent_fd *fde, uint16_t flags,
448                                 void *priv)
449 {
450         struct async_req *req = talloc_get_type_abort(
451                 priv, struct async_req);
452         struct async_syscall_state *state = talloc_get_type_abort(
453                 req->private_data, struct async_syscall_state);
454         struct param_recv *p = &state->param.param_recv;
455
456         if (state->syscall_type != ASYNC_SYSCALL_RECV) {
457                 async_req_error(req, EIO);
458                 return;
459         }
460
461         state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
462                                             p->flags);
463         state->sys_errno = errno;
464
465         TALLOC_FREE(state->fde);
466
467         async_req_done(req);
468 }
469
470 /**
471  * Async version of recv(2)
472  * @param[in] mem_ctx   The memory context to hang the result off
473  * @param[in] ev        The event context to work from
474  * @param[in] fd        The socket to recv from
475  * @param[in] buffer    The buffer to recv into
476  * @param[in] length    How many bytes to recv
477  * @param[in] flags     flags passed to recv(2)
478  *
479  * This function is a direct counterpart of recv(2)
480  */
481
482 struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
483                              int fd, void *buffer, size_t length,
484                              int flags)
485 {
486         struct async_req *result;
487         struct async_syscall_state *state;
488
489         result = async_fde_syscall_new(
490                 mem_ctx, ev, ASYNC_SYSCALL_RECV,
491                 fd, TEVENT_FD_READ, async_recv_callback,
492                 &state);
493
494         if (result == NULL) {
495                 return NULL;
496         }
497
498         state->param.param_recv.fd = fd;
499         state->param.param_recv.buffer = buffer;
500         state->param.param_recv.length = length;
501         state->param.param_recv.flags = flags;
502
503         return result;
504 }
505
506 /**
507  * fde event handler for the "recvall" syscall group
508  * @param[in] ev        The event context that sent us here
509  * @param[in] fde       The file descriptor event associated with the recv
510  * @param[in] flags     Can only be TEVENT_FD_READ here
511  * @param[in] priv      private data, "struct async_req *" in this case
512  */
513
514 static void async_recvall_callback(struct tevent_context *ev,
515                                    struct tevent_fd *fde, uint16_t flags,
516                                    void *priv)
517 {
518         struct async_req *req = talloc_get_type_abort(
519                 priv, struct async_req);
520         struct async_syscall_state *state = talloc_get_type_abort(
521                 req->private_data, struct async_syscall_state);
522         struct param_recvall *p = &state->param.param_recvall;
523
524         if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
525                 async_req_error(req, EIO);
526                 return;
527         }
528
529         state->result.result_ssize_t = recv(p->fd,
530                                             (char *)p->buffer + p->received,
531                                             p->length - p->received, p->flags);
532         state->sys_errno = errno;
533
534         if (state->result.result_ssize_t == -1) {
535                 async_req_error(req, state->sys_errno);
536                 return;
537         }
538
539         if (state->result.result_ssize_t == 0) {
540                 async_req_error(req, EIO);
541                 return;
542         }
543
544         p->received += state->result.result_ssize_t;
545         if (p->received > p->length) {
546                 async_req_error(req, EIO);
547                 return;
548         }
549
550         if (p->received == p->length) {
551                 TALLOC_FREE(state->fde);
552                 async_req_done(req);
553         }
554 }
555
556 /**
557  * Receive a specified number of bytes from a socket
558  * @param[in] mem_ctx   The memory context to hang the result off
559  * @param[in] ev        The event context to work from
560  * @param[in] fd        The socket to recv from
561  * @param[in] buffer    The buffer to recv into
562  * @param[in] length    How many bytes to recv
563  * @param[in] flags     flags passed to recv(2)
564  *
565  * async_recvall will call recv(2) until "length" bytes are received
566  */
567
568 struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
569                                int fd, void *buffer, size_t length,
570                                int flags)
571 {
572         struct async_req *result;
573         struct async_syscall_state *state;
574
575         result = async_fde_syscall_new(
576                 mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
577                 fd, TEVENT_FD_READ, async_recvall_callback,
578                 &state);
579         if (result == NULL) {
580                 return NULL;
581         }
582
583         state->param.param_recvall.fd = fd;
584         state->param.param_recvall.buffer = buffer;
585         state->param.param_recvall.length = length;
586         state->param.param_recvall.flags = flags;
587         state->param.param_recvall.received = 0;
588
589         return result;
590 }
591
592 ssize_t recvall_recv(struct async_req *req, int *perr)
593 {
594         struct async_syscall_state *state = talloc_get_type_abort(
595                 req->private_data, struct async_syscall_state);
596         int err;
597
598         err = async_req_simple_recv_errno(req);
599
600         if (err != 0) {
601                 *perr = err;
602                 return -1;
603         }
604
605         return state->result.result_ssize_t;
606 }
607
608 struct async_connect_state {
609         int fd;
610         int result;
611         int sys_errno;
612         long old_sockflags;
613 };
614
615 static void async_connect_connected(struct tevent_context *ev,
616                                     struct tevent_fd *fde, uint16_t flags,
617                                     void *priv);
618
619 /**
620  * @brief async version of connect(2)
621  * @param[in] mem_ctx   The memory context to hang the result off
622  * @param[in] ev        The event context to work from
623  * @param[in] fd        The socket to recv from
624  * @param[in] address   Where to connect?
625  * @param[in] address_len Length of *address
626  * @retval The async request
627  *
628  * This function sets the socket into non-blocking state to be able to call
629  * connect in an async state. This will be reset when the request is finished.
630  */
631
632 struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
633                                      struct tevent_context *ev,
634                                      int fd, const struct sockaddr *address,
635                                      socklen_t address_len)
636 {
637         struct async_req *result;
638         struct async_connect_state *state;
639         struct tevent_fd *fde;
640
641         if (!async_req_setup(mem_ctx, &result, &state,
642                              struct async_connect_state)) {
643                 return NULL;
644         }
645
646         /**
647          * We have to set the socket to nonblocking for async connect(2). Keep
648          * the old sockflags around.
649          */
650
651         state->fd = fd;
652         state->sys_errno = 0;
653
654         state->old_sockflags = fcntl(fd, F_GETFL, 0);
655         if (state->old_sockflags == -1) {
656                 goto post_errno;
657         }
658
659         set_blocking(fd, false);
660
661         state->result = connect(fd, address, address_len);
662         if (state->result == 0) {
663                 state->sys_errno = 0;
664                 goto post_status;
665         }
666
667         /**
668          * A number of error messages show that something good is progressing
669          * and that we have to wait for readability.
670          *
671          * If none of them are present, bail out.
672          */
673
674         if (!(errno == EINPROGRESS || errno == EALREADY ||
675 #ifdef EISCONN
676               errno == EISCONN ||
677 #endif
678               errno == EAGAIN || errno == EINTR)) {
679                 goto post_errno;
680         }
681
682         fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ | TEVENT_FD_WRITE,
683                            async_connect_connected, result);
684         if (fde == NULL) {
685                 state->sys_errno = ENOMEM;
686                 goto post_status;
687         }
688         return result;
689
690  post_errno:
691         state->sys_errno = errno;
692  post_status:
693         fcntl(fd, F_SETFL, state->old_sockflags);
694         if (!async_post_error(result, ev, state->sys_errno)) {
695                 goto fail;
696         }
697         return result;
698  fail:
699         TALLOC_FREE(result);
700         return NULL;
701 }
702
703 /**
704  * fde event handler for connect(2)
705  * @param[in] ev        The event context that sent us here
706  * @param[in] fde       The file descriptor event associated with the connect
707  * @param[in] flags     Indicate read/writeability of the socket
708  * @param[in] priv      private data, "struct async_req *" in this case
709  */
710
711 static void async_connect_connected(struct tevent_context *ev,
712                                     struct tevent_fd *fde, uint16_t flags,
713                                     void *priv)
714 {
715         struct async_req *req = talloc_get_type_abort(
716                 priv, struct async_req);
717         struct async_connect_state *state = talloc_get_type_abort(
718                 req->private_data, struct async_connect_state);
719
720         TALLOC_FREE(fde);
721
722         /*
723          * Stevens, Network Programming says that if there's a
724          * successful connect, the socket is only writable. Upon an
725          * error, it's both readable and writable.
726          */
727         if ((flags & (TEVENT_FD_READ|TEVENT_FD_WRITE))
728             == (TEVENT_FD_READ|TEVENT_FD_WRITE)) {
729                 int sockerr;
730                 socklen_t err_len = sizeof(sockerr);
731
732                 if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
733                                (void *)&sockerr, &err_len) == 0) {
734                         errno = sockerr;
735                 }
736
737                 state->sys_errno = errno;
738
739                 DEBUG(10, ("connect returned %s\n", strerror(errno)));
740
741                 fcntl(state->fd, F_SETFL, state->old_sockflags);
742                 async_req_error(req, state->sys_errno);
743                 return;
744         }
745
746         state->sys_errno = 0;
747         async_req_done(req);
748 }
749
750 int async_connect_recv(struct async_req *req, int *perrno)
751 {
752         struct async_connect_state *state = talloc_get_type_abort(
753                 req->private_data, struct async_connect_state);
754         int err;
755
756         fcntl(state->fd, F_SETFL, state->old_sockflags);
757
758
759         if (async_req_is_errno(req, &err)) {
760                 *perrno = err;
761                 return -1;
762         }
763         if (state->sys_errno == 0) {
764                 return 0;
765         }
766
767         *perrno = state->sys_errno;
768         return -1;
769 }