Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ab/samba.git/.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 Create a new async syscall req
99  * @param[in] mem_ctx   The memory context to hang the result off
100  * @param[in] ev        The event context to work from
101  * @param[in] type      Which syscall will this be
102  * @param[in] pstate    Where to put the newly created private_data state
103  * @retval The new request
104  *
105  * This is a helper function to prepare a new struct async_req with an
106  * associated struct async_syscall_state. The async_syscall_state will be put
107  * into the async_req as private_data.
108  */
109
110 static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
111                                            struct tevent_context *ev,
112                                            enum async_syscall_type type,
113                                            struct async_syscall_state **pstate)
114 {
115         struct async_req *result;
116         struct async_syscall_state *state;
117
118         if (!async_req_setup(mem_ctx, &result, &state,
119                              struct async_syscall_state)) {
120                 return NULL;
121         }
122         state->syscall_type = type;
123
124         result->private_data = state;
125
126         *pstate = state;
127
128         return result;
129 }
130
131 /**
132  * @brief Create a new async syscall req based on a fd
133  * @param[in] mem_ctx   The memory context to hang the result off
134  * @param[in] ev        The event context to work from
135  * @param[in] type      Which syscall will this be
136  * @param[in] fd        The file descriptor we work on
137  * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in?
138  * @param[in] fde_cb    The callback function for the file descriptor event
139  * @param[in] pstate    Where to put the newly created private_data state
140  * @retval The new request
141  *
142  * This is a helper function to prepare a new struct async_req with an
143  * associated struct async_syscall_state and an associated file descriptor
144  * event.
145  */
146
147 static struct async_req *async_fde_syscall_new(
148         TALLOC_CTX *mem_ctx,
149         struct tevent_context *ev,
150         enum async_syscall_type type,
151         int fd,
152         uint16_t fde_flags,
153         void (*fde_cb)(struct tevent_context *ev,
154                        struct tevent_fd *fde, uint16_t flags,
155                        void *priv),
156         struct async_syscall_state **pstate)
157 {
158         struct async_req *result;
159         struct async_syscall_state *state;
160
161         result = async_syscall_new(mem_ctx, ev, type, &state);
162         if (result == NULL) {
163                 return NULL;
164         }
165
166         state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result);
167         if (state->fde == NULL) {
168                 TALLOC_FREE(result);
169                 return NULL;
170         }
171         *pstate = state;
172         return result;
173 }
174
175 /**
176  * Retrieve a ssize_t typed result from an async syscall
177  * @param[in] req       The syscall that has just finished
178  * @param[out] perrno   Where to put the syscall's errno
179  * @retval The return value from the asynchronously called syscall
180  */
181
182 ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
183 {
184         struct async_syscall_state *state = talloc_get_type_abort(
185                 req->private_data, struct async_syscall_state);
186
187         *perrno = state->sys_errno;
188         return state->result.result_ssize_t;
189 }
190
191 /**
192  * Retrieve a size_t typed result from an async syscall
193  * @param[in] req       The syscall that has just finished
194  * @param[out] perrno   Where to put the syscall's errno
195  * @retval The return value from the asynchronously called syscall
196  */
197
198 size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
199 {
200         struct async_syscall_state *state = talloc_get_type_abort(
201                 req->private_data, struct async_syscall_state);
202
203         *perrno = state->sys_errno;
204         return state->result.result_size_t;
205 }
206
207 /**
208  * Retrieve a int typed result from an async syscall
209  * @param[in] req       The syscall that has just finished
210  * @param[out] perrno   Where to put the syscall's errno
211  * @retval The return value from the asynchronously called syscall
212  */
213
214 int async_syscall_result_int(struct async_req *req, int *perrno)
215 {
216         struct async_syscall_state *state = talloc_get_type_abort(
217                 req->private_data, struct async_syscall_state);
218
219         *perrno = state->sys_errno;
220         return state->result.result_int;
221 }
222
223 /**
224  * fde event handler for the "send" syscall
225  * @param[in] ev        The event context that sent us here
226  * @param[in] fde       The file descriptor event associated with the send
227  * @param[in] flags     Can only be TEVENT_FD_WRITE here
228  * @param[in] priv      private data, "struct async_req *" in this case
229  */
230
231 static void async_send_callback(struct tevent_context *ev,
232                                 struct tevent_fd *fde, uint16_t flags,
233                                 void *priv)
234 {
235         struct async_req *req = talloc_get_type_abort(
236                 priv, struct async_req);
237         struct async_syscall_state *state = talloc_get_type_abort(
238                 req->private_data, struct async_syscall_state);
239         struct param_send *p = &state->param.param_send;
240
241         if (state->syscall_type != ASYNC_SYSCALL_SEND) {
242                 async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
243                 return;
244         }
245
246         state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
247                                             p->flags);
248         state->sys_errno = errno;
249
250         TALLOC_FREE(state->fde);
251
252         async_req_done(req);
253 }
254
255 /**
256  * Async version of send(2)
257  * @param[in] mem_ctx   The memory context to hang the result off
258  * @param[in] ev        The event context to work from
259  * @param[in] fd        The socket to send to
260  * @param[in] buffer    The buffer to send
261  * @param[in] length    How many bytes to send
262  * @param[in] flags     flags passed to send(2)
263  *
264  * This function is a direct counterpart of send(2)
265  */
266
267 struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
268                              int fd, const void *buffer, size_t length,
269                              int flags)
270 {
271         struct async_req *result;
272         struct async_syscall_state *state;
273
274         result = async_fde_syscall_new(
275                 mem_ctx, ev, ASYNC_SYSCALL_SEND,
276                 fd, TEVENT_FD_WRITE, async_send_callback,
277                 &state);
278         if (result == NULL) {
279                 return NULL;
280         }
281
282         state->param.param_send.fd = fd;
283         state->param.param_send.buffer = buffer;
284         state->param.param_send.length = length;
285         state->param.param_send.flags = flags;
286
287         return result;
288 }
289
290 /**
291  * fde event handler for the "sendall" syscall group
292  * @param[in] ev        The event context that sent us here
293  * @param[in] fde       The file descriptor event associated with the send
294  * @param[in] flags     Can only be TEVENT_FD_WRITE here
295  * @param[in] priv      private data, "struct async_req *" in this case
296  */
297
298 static void async_sendall_callback(struct tevent_context *ev,
299                                    struct tevent_fd *fde, uint16_t flags,
300                                    void *priv)
301 {
302         struct async_req *req = talloc_get_type_abort(
303                 priv, struct async_req);
304         struct async_syscall_state *state = talloc_get_type_abort(
305                 req->private_data, struct async_syscall_state);
306         struct param_sendall *p = &state->param.param_sendall;
307
308         if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
309                 async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
310                 return;
311         }
312
313         state->result.result_ssize_t = send(p->fd,
314                                             (const char *)p->buffer + p->sent,
315                                             p->length - p->sent, p->flags);
316         state->sys_errno = errno;
317
318         if (state->result.result_ssize_t == -1) {
319                 async_req_nterror(req, map_nt_error_from_unix(state->sys_errno));
320                 return;
321         }
322
323         if (state->result.result_ssize_t == 0) {
324                 async_req_nterror(req, NT_STATUS_END_OF_FILE);
325                 return;
326         }
327
328         p->sent += state->result.result_ssize_t;
329         if (p->sent > p->length) {
330                 async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
331                 return;
332         }
333
334         if (p->sent == p->length) {
335                 TALLOC_FREE(state->fde);
336                 async_req_done(req);
337         }
338 }
339
340 /**
341  * @brief Send all bytes to a socket
342  * @param[in] mem_ctx   The memory context to hang the result off
343  * @param[in] ev        The event context to work from
344  * @param[in] fd        The socket to send to
345  * @param[in] buffer    The buffer to send
346  * @param[in] length    How many bytes to send
347  * @param[in] flags     flags passed to send(2)
348  *
349  * async_sendall calls send(2) as long as it is necessary to send all of the
350  * "length" bytes
351  */
352
353 struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
354                                int fd, const void *buffer, size_t length,
355                                int flags)
356 {
357         struct async_req *result;
358         struct async_syscall_state *state;
359
360         result = async_fde_syscall_new(
361                 mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
362                 fd, TEVENT_FD_WRITE, async_sendall_callback,
363                 &state);
364         if (result == NULL) {
365                 return NULL;
366         }
367
368         state->param.param_sendall.fd = fd;
369         state->param.param_sendall.buffer = buffer;
370         state->param.param_sendall.length = length;
371         state->param.param_sendall.flags = flags;
372         state->param.param_sendall.sent = 0;
373
374         return result;
375 }
376
377 NTSTATUS sendall_recv(struct async_req *req)
378 {
379         return async_req_simple_recv_ntstatus(req);
380 }
381
382 /**
383  * fde event handler for the "recv" syscall
384  * @param[in] ev        The event context that sent us here
385  * @param[in] fde       The file descriptor event associated with the recv
386  * @param[in] flags     Can only be TEVENT_FD_READ here
387  * @param[in] priv      private data, "struct async_req *" in this case
388  */
389
390 static void async_recv_callback(struct tevent_context *ev,
391                                 struct tevent_fd *fde, uint16_t flags,
392                                 void *priv)
393 {
394         struct async_req *req = talloc_get_type_abort(
395                 priv, struct async_req);
396         struct async_syscall_state *state = talloc_get_type_abort(
397                 req->private_data, struct async_syscall_state);
398         struct param_recv *p = &state->param.param_recv;
399
400         if (state->syscall_type != ASYNC_SYSCALL_RECV) {
401                 async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
402                 return;
403         }
404
405         state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
406                                             p->flags);
407         state->sys_errno = errno;
408
409         TALLOC_FREE(state->fde);
410
411         async_req_done(req);
412 }
413
414 /**
415  * Async version of recv(2)
416  * @param[in] mem_ctx   The memory context to hang the result off
417  * @param[in] ev        The event context to work from
418  * @param[in] fd        The socket to recv from
419  * @param[in] buffer    The buffer to recv into
420  * @param[in] length    How many bytes to recv
421  * @param[in] flags     flags passed to recv(2)
422  *
423  * This function is a direct counterpart of recv(2)
424  */
425
426 struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
427                              int fd, void *buffer, size_t length,
428                              int flags)
429 {
430         struct async_req *result;
431         struct async_syscall_state *state;
432
433         result = async_fde_syscall_new(
434                 mem_ctx, ev, ASYNC_SYSCALL_RECV,
435                 fd, TEVENT_FD_READ, async_recv_callback,
436                 &state);
437
438         if (result == NULL) {
439                 return NULL;
440         }
441
442         state->param.param_recv.fd = fd;
443         state->param.param_recv.buffer = buffer;
444         state->param.param_recv.length = length;
445         state->param.param_recv.flags = flags;
446
447         return result;
448 }
449
450 /**
451  * fde event handler for the "recvall" syscall group
452  * @param[in] ev        The event context that sent us here
453  * @param[in] fde       The file descriptor event associated with the recv
454  * @param[in] flags     Can only be TEVENT_FD_READ here
455  * @param[in] priv      private data, "struct async_req *" in this case
456  */
457
458 static void async_recvall_callback(struct tevent_context *ev,
459                                    struct tevent_fd *fde, uint16_t flags,
460                                    void *priv)
461 {
462         struct async_req *req = talloc_get_type_abort(
463                 priv, struct async_req);
464         struct async_syscall_state *state = talloc_get_type_abort(
465                 req->private_data, struct async_syscall_state);
466         struct param_recvall *p = &state->param.param_recvall;
467
468         if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
469                 async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
470                 return;
471         }
472
473         state->result.result_ssize_t = recv(p->fd,
474                                             (char *)p->buffer + p->received,
475                                             p->length - p->received, p->flags);
476         state->sys_errno = errno;
477
478         if (state->result.result_ssize_t == -1) {
479                 async_req_nterror(req, map_nt_error_from_unix(state->sys_errno));
480                 return;
481         }
482
483         if (state->result.result_ssize_t == 0) {
484                 async_req_nterror(req, NT_STATUS_END_OF_FILE);
485                 return;
486         }
487
488         p->received += state->result.result_ssize_t;
489         if (p->received > p->length) {
490                 async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
491                 return;
492         }
493
494         if (p->received == p->length) {
495                 TALLOC_FREE(state->fde);
496                 async_req_done(req);
497         }
498 }
499
500 /**
501  * Receive a specified number of bytes from a socket
502  * @param[in] mem_ctx   The memory context to hang the result off
503  * @param[in] ev        The event context to work from
504  * @param[in] fd        The socket to recv from
505  * @param[in] buffer    The buffer to recv into
506  * @param[in] length    How many bytes to recv
507  * @param[in] flags     flags passed to recv(2)
508  *
509  * async_recvall will call recv(2) until "length" bytes are received
510  */
511
512 struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
513                                int fd, void *buffer, size_t length,
514                                int flags)
515 {
516         struct async_req *result;
517         struct async_syscall_state *state;
518
519         result = async_fde_syscall_new(
520                 mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
521                 fd, TEVENT_FD_READ, async_recvall_callback,
522                 &state);
523         if (result == NULL) {
524                 return NULL;
525         }
526
527         state->param.param_recvall.fd = fd;
528         state->param.param_recvall.buffer = buffer;
529         state->param.param_recvall.length = length;
530         state->param.param_recvall.flags = flags;
531         state->param.param_recvall.received = 0;
532
533         return result;
534 }
535
536 NTSTATUS recvall_recv(struct async_req *req)
537 {
538         return async_req_simple_recv_ntstatus(req);
539 }
540
541 struct async_connect_state {
542         int fd;
543         int result;
544         int sys_errno;
545         long old_sockflags;
546 };
547
548 static void async_connect_connected(struct tevent_context *ev,
549                                     struct tevent_fd *fde, uint16_t flags,
550                                     void *priv);
551
552 /**
553  * @brief async version of connect(2)
554  * @param[in] mem_ctx   The memory context to hang the result off
555  * @param[in] ev        The event context to work from
556  * @param[in] fd        The socket to recv from
557  * @param[in] address   Where to connect?
558  * @param[in] address_len Length of *address
559  * @retval The async request
560  *
561  * This function sets the socket into non-blocking state to be able to call
562  * connect in an async state. This will be reset when the request is finished.
563  */
564
565 struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
566                                      struct tevent_context *ev,
567                                      int fd, const struct sockaddr *address,
568                                      socklen_t address_len)
569 {
570         struct async_req *result;
571         struct async_connect_state *state;
572         struct tevent_fd *fde;
573         NTSTATUS status;
574
575         if (!async_req_setup(mem_ctx, &result, &state,
576                              struct async_connect_state)) {
577                 return NULL;
578         }
579
580         /**
581          * We have to set the socket to nonblocking for async connect(2). Keep
582          * the old sockflags around.
583          */
584
585         state->fd = fd;
586         state->sys_errno = 0;
587
588         state->old_sockflags = fcntl(fd, F_GETFL, 0);
589         if (state->old_sockflags == -1) {
590                 goto post_errno;
591         }
592
593         set_blocking(fd, false);
594
595         state->result = connect(fd, address, address_len);
596         if (state->result == 0) {
597                 state->sys_errno = 0;
598                 status = NT_STATUS_OK;
599                 goto post_status;
600         }
601
602         /**
603          * A number of error messages show that something good is progressing
604          * and that we have to wait for readability.
605          *
606          * If none of them are present, bail out.
607          */
608
609         if (!(errno == EINPROGRESS || errno == EALREADY ||
610 #ifdef EISCONN
611               errno == EISCONN ||
612 #endif
613               errno == EAGAIN || errno == EINTR)) {
614                 goto post_errno;
615         }
616
617         fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ | TEVENT_FD_WRITE,
618                            async_connect_connected, result);
619         if (fde == NULL) {
620                 status = NT_STATUS_NO_MEMORY;
621                 goto post_status;
622         }
623         return result;
624
625  post_errno:
626         state->sys_errno = errno;
627         status = map_nt_error_from_unix(state->sys_errno);
628  post_status:
629         fcntl(fd, F_SETFL, state->old_sockflags);
630         if (!async_post_ntstatus(result, ev, status)) {
631                 goto fail;
632         }
633         return result;
634  fail:
635         TALLOC_FREE(result);
636         return NULL;
637 }
638
639 /**
640  * fde event handler for connect(2)
641  * @param[in] ev        The event context that sent us here
642  * @param[in] fde       The file descriptor event associated with the connect
643  * @param[in] flags     Indicate read/writeability of the socket
644  * @param[in] priv      private data, "struct async_req *" in this case
645  */
646
647 static void async_connect_connected(struct tevent_context *ev,
648                                     struct tevent_fd *fde, uint16_t flags,
649                                     void *priv)
650 {
651         struct async_req *req = talloc_get_type_abort(
652                 priv, struct async_req);
653         struct async_connect_state *state = talloc_get_type_abort(
654                 req->private_data, struct async_connect_state);
655
656         TALLOC_FREE(fde);
657
658         /*
659          * Stevens, Network Programming says that if there's a
660          * successful connect, the socket is only writable. Upon an
661          * error, it's both readable and writable.
662          */
663         if ((flags & (TEVENT_FD_READ|TEVENT_FD_WRITE))
664             == (TEVENT_FD_READ|TEVENT_FD_WRITE)) {
665                 int sockerr;
666                 socklen_t err_len = sizeof(sockerr);
667
668                 if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
669                                (void *)&sockerr, &err_len) == 0) {
670                         errno = sockerr;
671                 }
672
673                 state->sys_errno = errno;
674
675                 DEBUG(10, ("connect returned %s\n", strerror(errno)));
676
677                 fcntl(state->fd, F_SETFL, state->old_sockflags);
678                 async_req_nterror(req, map_nt_error_from_unix(state->sys_errno));
679                 return;
680         }
681
682         state->sys_errno = 0;
683         async_req_done(req);
684 }
685
686 NTSTATUS async_connect_recv(struct async_req *req, int *perrno)
687 {
688         struct async_connect_state *state = talloc_get_type_abort(
689                 req->private_data, struct async_connect_state);
690         NTSTATUS status;
691
692         fcntl(state->fd, F_SETFL, state->old_sockflags);
693
694         *perrno = state->sys_errno;
695
696         if (async_req_is_nterror(req, &status)) {
697                 return status;
698         }
699         if (state->sys_errno == 0) {
700                 return NT_STATUS_OK;
701         }
702         return map_nt_error_from_unix(state->sys_errno);
703 }