tsocket: add tstream_readv_pdu_queue_send/recv()
[ira/wip.git] / lib / tsocket / tsocket_bsd.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Stefan Metzmacher 2009
5
6      ** NOTE! The following LGPL license applies to the tevent
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 3 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "replace.h"
25 #include "system/filesys.h"
26 #include "system/network.h"
27 #include "tsocket.h"
28 #include "tsocket_internal.h"
29
30 static int tsocket_bsd_error_from_errno(int ret,
31                                         int sys_errno,
32                                         bool *retry)
33 {
34         *retry = false;
35
36         if (ret >= 0) {
37                 return 0;
38         }
39
40         if (ret != -1) {
41                 return EIO;
42         }
43
44         if (sys_errno == 0) {
45                 return EIO;
46         }
47
48         if (sys_errno == EINTR) {
49                 *retry = true;
50                 return sys_errno;
51         }
52
53         if (sys_errno == EINPROGRESS) {
54                 *retry = true;
55                 return sys_errno;
56         }
57
58         if (sys_errno == EAGAIN) {
59                 *retry = true;
60                 return sys_errno;
61         }
62
63 #ifdef EWOULDBLOCK
64         if (sys_errno == EWOULDBLOCK) {
65                 *retry = true;
66                 return sys_errno;
67         }
68 #endif
69
70         return sys_errno;
71 }
72
73 static int tsocket_bsd_common_prepare_fd(int fd, bool high_fd)
74 {
75         int i;
76         int sys_errno = 0;
77         int fds[3];
78         int num_fds = 0;
79
80         int result, flags;
81
82         if (fd == -1) {
83                 return -1;
84         }
85
86         /* first make a fd >= 3 */
87         if (high_fd) {
88                 while (fd < 3) {
89                         fds[num_fds++] = fd;
90                         fd = dup(fd);
91                         if (fd == -1) {
92                                 sys_errno = errno;
93                                 break;
94                         }
95                 }
96                 for (i=0; i<num_fds; i++) {
97                         close(fds[i]);
98                 }
99                 if (fd == -1) {
100                         errno = sys_errno;
101                         return fd;
102                 }
103         }
104
105         /* fd should be nonblocking. */
106
107 #ifdef O_NONBLOCK
108 #define FLAG_TO_SET O_NONBLOCK
109 #else
110 #ifdef SYSV
111 #define FLAG_TO_SET O_NDELAY
112 #else /* BSD */
113 #define FLAG_TO_SET FNDELAY
114 #endif
115 #endif
116
117         if ((flags = fcntl(fd, F_GETFL)) == -1) {
118                 goto fail;
119         }
120
121         flags |= FLAG_TO_SET;
122         if (fcntl(fd, F_SETFL, flags) == -1) {
123                 goto fail;
124         }
125
126 #undef FLAG_TO_SET
127
128         /* fd should be closed on exec() */
129 #ifdef FD_CLOEXEC
130         result = flags = fcntl(fd, F_GETFD, 0);
131         if (flags >= 0) {
132                 flags |= FD_CLOEXEC;
133                 result = fcntl(fd, F_SETFD, flags);
134         }
135         if (result < 0) {
136                 goto fail;
137         }
138 #endif
139         return fd;
140
141  fail:
142         if (fd != -1) {
143                 sys_errno = errno;
144                 close(fd);
145                 errno = sys_errno;
146         }
147         return -1;
148 }
149
150 static ssize_t tsocket_bsd_pending(int fd)
151 {
152         int ret;
153         int value = 0;
154
155         ret = ioctl(fd, FIONREAD, &value);
156         if (ret == -1) {
157                 return ret;
158         }
159
160         if (ret == 0) {
161                 if (value == 0) {
162                         int error=0;
163                         socklen_t len = sizeof(error);
164                         /*
165                          * if no data is available check if the socket
166                          * is in error state. For dgram sockets
167                          * it's the way to return ICMP error messages
168                          * of connected sockets to the caller.
169                          */
170                         ret = getsockopt(fd, SOL_SOCKET, SO_ERROR,
171                                          &error, &len);
172                         if (ret == -1) {
173                                 return ret;
174                         }
175                         if (error != 0) {
176                                 errno = error;
177                                 return -1;
178                         }
179                 }
180                 return value;
181         }
182
183         /* this should not be reached */
184         errno = EIO;
185         return -1;
186 }
187
188 static const struct tsocket_address_ops tsocket_address_bsd_ops;
189
190 struct tsocket_address_bsd {
191         union {
192                 struct sockaddr sa;
193                 struct sockaddr_in in;
194 #ifdef HAVE_IPV6
195                 struct sockaddr_in6 in6;
196 #endif
197                 struct sockaddr_un un;
198                 struct sockaddr_storage ss;
199         } u;
200 };
201
202 static int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
203                                               struct sockaddr *sa,
204                                               socklen_t sa_len,
205                                               struct tsocket_address **_addr,
206                                               const char *location)
207 {
208         struct tsocket_address *addr;
209         struct tsocket_address_bsd *bsda;
210
211         switch (sa->sa_family) {
212         case AF_UNIX:
213                 if (sa_len < sizeof(struct sockaddr_un)) {
214                         errno = EINVAL;
215                         return -1;
216                 }
217                 break;
218         case AF_INET:
219                 if (sa_len < sizeof(struct sockaddr_in)) {
220                         errno = EINVAL;
221                         return -1;
222                 }
223                 break;
224 #ifdef HAVE_IPV6
225         case AF_INET6:
226                 if (sa_len < sizeof(struct sockaddr_in6)) {
227                         errno = EINVAL;
228                         return -1;
229                 }
230                 break;
231 #endif
232         default:
233                 errno = EAFNOSUPPORT;
234                 return -1;
235         }
236
237         if (sa_len > sizeof(struct sockaddr_storage)) {
238                 errno = EINVAL;
239                 return -1;
240         }
241
242         addr = tsocket_address_create(mem_ctx,
243                                       &tsocket_address_bsd_ops,
244                                       &bsda,
245                                       struct tsocket_address_bsd,
246                                       location);
247         if (!addr) {
248                 errno = ENOMEM;
249                 return -1;
250         }
251
252         ZERO_STRUCTP(bsda);
253
254         memcpy(&bsda->u.ss, sa, sa_len);
255
256         *_addr = addr;
257         return 0;
258 }
259
260 int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
261                                        const char *fam,
262                                        const char *addr,
263                                        uint16_t port,
264                                        struct tsocket_address **_addr,
265                                        const char *location)
266 {
267         struct addrinfo hints;
268         struct addrinfo *result = NULL;
269         char port_str[6];
270         int ret;
271
272         ZERO_STRUCT(hints);
273         /*
274          * we use SOCKET_STREAM here to get just one result
275          * back from getaddrinfo().
276          */
277         hints.ai_socktype = SOCK_STREAM;
278         hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
279
280         if (strcasecmp(fam, "ip") == 0) {
281                 hints.ai_family = AF_UNSPEC;
282                 if (!addr) {
283 #ifdef HAVE_IPV6
284                         addr = "::";
285 #else
286                         addr = "0.0.0.0";
287 #endif
288                 }
289         } else if (strcasecmp(fam, "ipv4") == 0) {
290                 hints.ai_family = AF_INET;
291                 if (!addr) {
292                         addr = "0.0.0.0";
293                 }
294 #ifdef HAVE_IPV6
295         } else if (strcasecmp(fam, "ipv6") == 0) {
296                 hints.ai_family = AF_INET6;
297                 if (!addr) {
298                         addr = "::";
299                 }
300 #endif
301         } else {
302                 errno = EAFNOSUPPORT;
303                 return -1;
304         }
305
306         snprintf(port_str, sizeof(port_str) - 1, "%u", port);
307
308         ret = getaddrinfo(addr, port_str, &hints, &result);
309         if (ret != 0) {
310                 switch (ret) {
311                 case EAI_FAIL:
312                         errno = EINVAL;
313                         break;
314                 }
315                 ret = -1;
316                 goto done;
317         }
318
319         if (result->ai_socktype != SOCK_STREAM) {
320                 errno = EINVAL;
321                 ret = -1;
322                 goto done;
323         }
324
325         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
326                                                   result->ai_addr,
327                                                   result->ai_addrlen,
328                                                   _addr,
329                                                   location);
330
331 done:
332         if (result) {
333                 freeaddrinfo(result);
334         }
335         return ret;
336 }
337
338 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
339                                        TALLOC_CTX *mem_ctx)
340 {
341         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
342                                            struct tsocket_address_bsd);
343         char addr_str[INET6_ADDRSTRLEN+1];
344         const char *str;
345
346         if (!bsda) {
347                 errno = EINVAL;
348                 return NULL;
349         }
350
351         switch (bsda->u.sa.sa_family) {
352         case AF_INET:
353                 str = inet_ntop(bsda->u.in.sin_family,
354                                 &bsda->u.in.sin_addr,
355                                 addr_str, sizeof(addr_str));
356                 break;
357 #ifdef HAVE_IPV6
358         case AF_INET6:
359                 str = inet_ntop(bsda->u.in6.sin6_family,
360                                 &bsda->u.in6.sin6_addr,
361                                 addr_str, sizeof(addr_str));
362                 break;
363 #endif
364         default:
365                 errno = EINVAL;
366                 return NULL;
367         }
368
369         if (!str) {
370                 return NULL;
371         }
372
373         return talloc_strdup(mem_ctx, str);
374 }
375
376 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
377 {
378         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
379                                            struct tsocket_address_bsd);
380         uint16_t port = 0;
381
382         if (!bsda) {
383                 errno = EINVAL;
384                 return 0;
385         }
386
387         switch (bsda->u.sa.sa_family) {
388         case AF_INET:
389                 port = ntohs(bsda->u.in.sin_port);
390                 break;
391 #ifdef HAVE_IPV6
392         case AF_INET6:
393                 port = ntohs(bsda->u.in6.sin6_port);
394                 break;
395 #endif
396         default:
397                 errno = EINVAL;
398                 return 0;
399         }
400
401         return port;
402 }
403
404 int tsocket_address_inet_set_port(struct tsocket_address *addr,
405                                   uint16_t port)
406 {
407         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
408                                            struct tsocket_address_bsd);
409
410         if (!bsda) {
411                 errno = EINVAL;
412                 return -1;
413         }
414
415         switch (bsda->u.sa.sa_family) {
416         case AF_INET:
417                 bsda->u.in.sin_port = htons(port);
418                 break;
419 #ifdef HAVE_IPV6
420         case AF_INET6:
421                 bsda->u.in6.sin6_port = htons(port);
422                 break;
423 #endif
424         default:
425                 errno = EINVAL;
426                 return -1;
427         }
428
429         return 0;
430 }
431
432 int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
433                                     const char *path,
434                                     struct tsocket_address **_addr,
435                                     const char *location)
436 {
437         struct sockaddr_un un;
438         void *p = &un;
439         int ret;
440
441         if (!path) {
442                 path = "";
443         }
444
445         ZERO_STRUCT(un);
446         un.sun_family = AF_UNIX;
447         strncpy(un.sun_path, path, sizeof(un.sun_path));
448
449         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
450                                                  (struct sockaddr *)p,
451                                                  sizeof(un),
452                                                  _addr,
453                                                  location);
454
455         return ret;
456 }
457
458 char *tsocket_address_unix_path(const struct tsocket_address *addr,
459                                 TALLOC_CTX *mem_ctx)
460 {
461         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
462                                            struct tsocket_address_bsd);
463         const char *str;
464
465         if (!bsda) {
466                 errno = EINVAL;
467                 return NULL;
468         }
469
470         switch (bsda->u.sa.sa_family) {
471         case AF_UNIX:
472                 str = bsda->u.un.sun_path;
473                 break;
474         default:
475                 errno = EINVAL;
476                 return NULL;
477         }
478
479         return talloc_strdup(mem_ctx, str);
480 }
481
482 static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
483                                         TALLOC_CTX *mem_ctx)
484 {
485         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
486                                            struct tsocket_address_bsd);
487         char *str;
488         char *addr_str;
489         const char *prefix = NULL;
490         uint16_t port;
491
492         switch (bsda->u.sa.sa_family) {
493         case AF_UNIX:
494                 return talloc_asprintf(mem_ctx, "unix:%s",
495                                        bsda->u.un.sun_path);
496         case AF_INET:
497                 prefix = "ipv4";
498                 break;
499 #ifdef HAVE_IPV6
500         case AF_INET6:
501                 prefix = "ipv6";
502                 break;
503 #endif
504         default:
505                 errno = EINVAL;
506                 return NULL;
507         }
508
509         addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
510         if (!addr_str) {
511                 return NULL;
512         }
513
514         port = tsocket_address_inet_port(addr);
515
516         str = talloc_asprintf(mem_ctx, "%s:%s:%u",
517                               prefix, addr_str, port);
518         talloc_free(addr_str);
519
520         return str;
521 }
522
523 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
524                                                          TALLOC_CTX *mem_ctx,
525                                                          const char *location)
526 {
527         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
528                                            struct tsocket_address_bsd);
529         struct tsocket_address *copy;
530         int ret;
531
532         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
533                                                  &bsda->u.sa,
534                                                  sizeof(bsda->u.ss),
535                                                  &copy,
536                                                  location);
537         if (ret != 0) {
538                 return NULL;
539         }
540
541         return copy;
542 }
543
544 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
545         .name           = "bsd",
546         .string         = tsocket_address_bsd_string,
547         .copy           = tsocket_address_bsd_copy,
548 };
549
550 struct tdgram_bsd {
551         int fd;
552
553         void *event_ptr;
554         struct tevent_fd *fde;
555
556         void *readable_private;
557         void (*readable_handler)(void *private_data);
558         void *writeable_private;
559         void (*writeable_handler)(void *private_data);
560 };
561
562 static void tdgram_bsd_fde_handler(struct tevent_context *ev,
563                                    struct tevent_fd *fde,
564                                    uint16_t flags,
565                                    void *private_data)
566 {
567         struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
568                                   struct tdgram_bsd);
569
570         if (flags & TEVENT_FD_WRITE) {
571                 bsds->writeable_handler(bsds->writeable_private);
572                 return;
573         }
574         if (flags & TEVENT_FD_READ) {
575                 if (!bsds->readable_handler) {
576                         TEVENT_FD_NOT_READABLE(bsds->fde);
577                         return;
578                 }
579                 bsds->readable_handler(bsds->readable_private);
580                 return;
581         }
582 }
583
584 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
585                                            struct tevent_context *ev,
586                                            void (*handler)(void *private_data),
587                                            void *private_data)
588 {
589         if (ev == NULL) {
590                 if (handler) {
591                         errno = EINVAL;
592                         return -1;
593                 }
594                 if (!bsds->readable_handler) {
595                         return 0;
596                 }
597                 bsds->readable_handler = NULL;
598                 bsds->readable_private = NULL;
599
600                 return 0;
601         }
602
603         /* read and write must use the same tevent_context */
604         if (bsds->event_ptr != ev) {
605                 if (bsds->readable_handler || bsds->writeable_handler) {
606                         errno = EINVAL;
607                         return -1;
608                 }
609                 bsds->event_ptr = NULL;
610                 TALLOC_FREE(bsds->fde);
611         }
612
613         if (bsds->fde == NULL) {
614                 bsds->fde = tevent_add_fd(ev, bsds,
615                                           bsds->fd, TEVENT_FD_READ,
616                                           tdgram_bsd_fde_handler,
617                                           bsds);
618                 if (!bsds->fde) {
619                         return -1;
620                 }
621
622                 /* cache the event context we're running on */
623                 bsds->event_ptr = ev;
624         } else if (!bsds->readable_handler) {
625                 TEVENT_FD_READABLE(bsds->fde);
626         }
627
628         bsds->readable_handler = handler;
629         bsds->readable_private = private_data;
630
631         return 0;
632 }
633
634 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
635                                             struct tevent_context *ev,
636                                             void (*handler)(void *private_data),
637                                             void *private_data)
638 {
639         if (ev == NULL) {
640                 if (handler) {
641                         errno = EINVAL;
642                         return -1;
643                 }
644                 if (!bsds->writeable_handler) {
645                         return 0;
646                 }
647                 bsds->writeable_handler = NULL;
648                 bsds->writeable_private = NULL;
649                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
650
651                 return 0;
652         }
653
654         /* read and write must use the same tevent_context */
655         if (bsds->event_ptr != ev) {
656                 if (bsds->readable_handler || bsds->writeable_handler) {
657                         errno = EINVAL;
658                         return -1;
659                 }
660                 bsds->event_ptr = NULL;
661                 TALLOC_FREE(bsds->fde);
662         }
663
664         if (bsds->fde == NULL) {
665                 bsds->fde = tevent_add_fd(ev, bsds,
666                                           bsds->fd, TEVENT_FD_WRITE,
667                                           tdgram_bsd_fde_handler,
668                                           bsds);
669                 if (!bsds->fde) {
670                         return -1;
671                 }
672
673                 /* cache the event context we're running on */
674                 bsds->event_ptr = ev;
675         } else if (!bsds->writeable_handler) {
676                 TEVENT_FD_WRITEABLE(bsds->fde);
677         }
678
679         bsds->writeable_handler = handler;
680         bsds->writeable_private = private_data;
681
682         return 0;
683 }
684
685 struct tdgram_bsd_recvfrom_state {
686         struct tdgram_context *dgram;
687
688         uint8_t *buf;
689         size_t len;
690         struct tsocket_address *src;
691 };
692
693 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
694 {
695         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
696                                   struct tdgram_bsd);
697
698         tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
699
700         return 0;
701 }
702
703 static void tdgram_bsd_recvfrom_handler(void *private_data);
704
705 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
706                                         struct tevent_context *ev,
707                                         struct tdgram_context *dgram)
708 {
709         struct tevent_req *req;
710         struct tdgram_bsd_recvfrom_state *state;
711         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
712         int ret;
713
714         req = tevent_req_create(mem_ctx, &state,
715                                 struct tdgram_bsd_recvfrom_state);
716         if (!req) {
717                 return NULL;
718         }
719
720         state->dgram    = dgram;
721         state->buf      = NULL;
722         state->len      = 0;
723         state->src      = NULL;
724
725         talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
726
727         if (bsds->fd == -1) {
728                 tevent_req_error(req, ENOTCONN);
729                 goto post;
730         }
731
732         /*
733          * this is a fast path, not waiting for the
734          * socket to become explicit readable gains
735          * about 10%-20% performance in benchmark tests.
736          */
737         tdgram_bsd_recvfrom_handler(req);
738         if (!tevent_req_is_in_progress(req)) {
739                 goto post;
740         }
741
742         ret = tdgram_bsd_set_readable_handler(bsds, ev,
743                                               tdgram_bsd_recvfrom_handler,
744                                               req);
745         if (ret == -1) {
746                 tevent_req_error(req, errno);
747                 goto post;
748         }
749
750         return req;
751
752  post:
753         tevent_req_post(req, ev);
754         return req;
755 }
756
757 static void tdgram_bsd_recvfrom_handler(void *private_data)
758 {
759         struct tevent_req *req = talloc_get_type_abort(private_data,
760                                  struct tevent_req);
761         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
762                                         struct tdgram_bsd_recvfrom_state);
763         struct tdgram_context *dgram = state->dgram;
764         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
765         struct tsocket_address_bsd *bsda;
766         ssize_t ret;
767         struct sockaddr *sa = NULL;
768         socklen_t sa_len = 0;
769         int err;
770         bool retry;
771
772         ret = tsocket_bsd_pending(bsds->fd);
773         if (ret == 0) {
774                 /* retry later */
775                 return;
776         }
777         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
778         if (retry) {
779                 /* retry later */
780                 return;
781         }
782         if (tevent_req_error(req, err)) {
783                 return;
784         }
785
786         state->buf = talloc_array(state, uint8_t, ret);
787         if (tevent_req_nomem(state->buf, req)) {
788                 return;
789         }
790         state->len = ret;
791
792         state->src = tsocket_address_create(state,
793                                             &tsocket_address_bsd_ops,
794                                             &bsda,
795                                             struct tsocket_address_bsd,
796                                             __location__ "bsd_recvfrom");
797         if (tevent_req_nomem(state->src, req)) {
798                 return;
799         }
800
801         ZERO_STRUCTP(bsda);
802
803         sa = &bsda->u.sa;
804         sa_len = sizeof(bsda->u.ss);
805         /*
806          * for unix sockets we can't use the size of sockaddr_storage
807          * we would get EINVAL
808          */
809         if (bsda->u.sa.sa_family == AF_UNIX) {
810                 sa_len = sizeof(bsda->u.un);
811         }
812
813         ret = recvfrom(bsds->fd, state->buf, state->len, 0, sa, &sa_len);
814         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
815         if (retry) {
816                 /* retry later */
817                 return;
818         }
819         if (tevent_req_error(req, err)) {
820                 return;
821         }
822
823         if (ret != state->len) {
824                 tevent_req_error(req, EIO);
825                 return;
826         }
827
828         tevent_req_done(req);
829 }
830
831 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
832                                         int *perrno,
833                                         TALLOC_CTX *mem_ctx,
834                                         uint8_t **buf,
835                                         struct tsocket_address **src)
836 {
837         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
838                                         struct tdgram_bsd_recvfrom_state);
839         ssize_t ret;
840
841         ret = tsocket_simple_int_recv(req, perrno);
842         if (ret == 0) {
843                 *buf = talloc_move(mem_ctx, &state->buf);
844                 ret = state->len;
845                 if (src) {
846                         *src = talloc_move(mem_ctx, &state->src);
847                 }
848         }
849
850         tevent_req_received(req);
851         return ret;
852 }
853
854 struct tdgram_bsd_sendto_state {
855         struct tdgram_context *dgram;
856
857         const uint8_t *buf;
858         size_t len;
859         const struct tsocket_address *dst;
860
861         ssize_t ret;
862 };
863
864 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
865 {
866         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
867                                   struct tdgram_bsd);
868
869         tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
870
871         return 0;
872 }
873
874 static void tdgram_bsd_sendto_handler(void *private_data);
875
876 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
877                                                  struct tevent_context *ev,
878                                                  struct tdgram_context *dgram,
879                                                  const uint8_t *buf,
880                                                  size_t len,
881                                                  const struct tsocket_address *dst)
882 {
883         struct tevent_req *req;
884         struct tdgram_bsd_sendto_state *state;
885         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
886         int ret;
887
888         req = tevent_req_create(mem_ctx, &state,
889                                 struct tdgram_bsd_sendto_state);
890         if (!req) {
891                 return NULL;
892         }
893
894         state->dgram    = dgram;
895         state->buf      = buf;
896         state->len      = len;
897         state->dst      = dst;
898         state->ret      = -1;
899
900         talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
901
902         if (bsds->fd == -1) {
903                 tevent_req_error(req, ENOTCONN);
904                 goto post;
905         }
906
907         /*
908          * this is a fast path, not waiting for the
909          * socket to become explicit writeable gains
910          * about 10%-20% performance in benchmark tests.
911          */
912         tdgram_bsd_sendto_handler(req);
913         if (!tevent_req_is_in_progress(req)) {
914                 goto post;
915         }
916
917         ret = tdgram_bsd_set_writeable_handler(bsds, ev,
918                                                tdgram_bsd_sendto_handler,
919                                                req);
920         if (ret == -1) {
921                 tevent_req_error(req, errno);
922                 goto post;
923         }
924
925         return req;
926
927  post:
928         tevent_req_post(req, ev);
929         return req;
930 }
931
932 static void tdgram_bsd_sendto_handler(void *private_data)
933 {
934         struct tevent_req *req = talloc_get_type_abort(private_data,
935                                  struct tevent_req);
936         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
937                                         struct tdgram_bsd_sendto_state);
938         struct tdgram_context *dgram = state->dgram;
939         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
940         struct sockaddr *sa = NULL;
941         socklen_t sa_len = 0;
942         ssize_t ret;
943         int err;
944         bool retry;
945
946         if (state->dst) {
947                 struct tsocket_address_bsd *bsda =
948                         talloc_get_type(state->dst->private_data,
949                         struct tsocket_address_bsd);
950
951                 sa = &bsda->u.sa;
952                 sa_len = sizeof(bsda->u.ss);
953                 /*
954                  * for unix sockets we can't use the size of sockaddr_storage
955                  * we would get EINVAL
956                  */
957                 if (bsda->u.sa.sa_family == AF_UNIX) {
958                         sa_len = sizeof(bsda->u.un);
959                 }
960         }
961
962         ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_len);
963         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
964         if (retry) {
965                 /* retry later */
966                 return;
967         }
968         if (tevent_req_error(req, err)) {
969                 return;
970         }
971
972         state->ret = ret;
973
974         tevent_req_done(req);
975 }
976
977 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
978 {
979         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
980                                         struct tdgram_bsd_sendto_state);
981         ssize_t ret;
982
983         ret = tsocket_simple_int_recv(req, perrno);
984         if (ret == 0) {
985                 ret = state->ret;
986         }
987
988         tevent_req_received(req);
989         return ret;
990 }
991
992 struct tdgram_bsd_disconnect_state {
993         uint8_t __dummy;
994 };
995
996 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
997                                                      struct tevent_context *ev,
998                                                      struct tdgram_context *dgram)
999 {
1000         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1001         struct tevent_req *req;
1002         struct tdgram_bsd_disconnect_state *state;
1003         int ret;
1004         int err;
1005         bool dummy;
1006
1007         req = tevent_req_create(mem_ctx, &state,
1008                                 struct tdgram_bsd_disconnect_state);
1009         if (req == NULL) {
1010                 return NULL;
1011         }
1012
1013         if (bsds->fd == -1) {
1014                 tevent_req_error(req, ENOTCONN);
1015                 goto post;
1016         }
1017
1018         ret = close(bsds->fd);
1019         bsds->fd = -1;
1020         err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1021         if (tevent_req_error(req, err)) {
1022                 goto post;
1023         }
1024
1025         tevent_req_done(req);
1026 post:
1027         tevent_req_post(req, ev);
1028         return req;
1029 }
1030
1031 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1032                                       int *perrno)
1033 {
1034         int ret;
1035
1036         ret = tsocket_simple_int_recv(req, perrno);
1037
1038         tevent_req_received(req);
1039         return ret;
1040 }
1041
1042 static const struct tdgram_context_ops tdgram_bsd_ops = {
1043         .name                   = "bsd",
1044
1045         .recvfrom_send          = tdgram_bsd_recvfrom_send,
1046         .recvfrom_recv          = tdgram_bsd_recvfrom_recv,
1047
1048         .sendto_send            = tdgram_bsd_sendto_send,
1049         .sendto_recv            = tdgram_bsd_sendto_recv,
1050
1051         .disconnect_send        = tdgram_bsd_disconnect_send,
1052         .disconnect_recv        = tdgram_bsd_disconnect_recv,
1053 };
1054
1055 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1056 {
1057         TALLOC_FREE(bsds->fde);
1058         if (bsds->fd != -1) {
1059                 close(bsds->fd);
1060                 bsds->fd = -1;
1061         }
1062         return 0;
1063 }
1064
1065 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1066                                    const struct tsocket_address *remote,
1067                                    bool broadcast,
1068                                    TALLOC_CTX *mem_ctx,
1069                                    struct tdgram_context **_dgram,
1070                                    const char *location)
1071 {
1072         struct tsocket_address_bsd *lbsda =
1073                 talloc_get_type_abort(local->private_data,
1074                 struct tsocket_address_bsd);
1075         struct tsocket_address_bsd *rbsda = NULL;
1076         struct tdgram_context *dgram;
1077         struct tdgram_bsd *bsds;
1078         int fd;
1079         int ret;
1080         bool do_bind = false;
1081         bool do_reuseaddr = false;
1082         socklen_t sa_len = sizeof(lbsda->u.ss);
1083
1084         if (remote) {
1085                 rbsda = talloc_get_type_abort(remote->private_data,
1086                         struct tsocket_address_bsd);
1087         }
1088
1089         switch (lbsda->u.sa.sa_family) {
1090         case AF_UNIX:
1091                 if (broadcast) {
1092                         errno = EINVAL;
1093                         return -1;
1094                 }
1095                 if (lbsda->u.un.sun_path[0] != 0) {
1096                         do_reuseaddr = true;
1097                         do_bind = true;
1098                 }
1099                 /*
1100                  * for unix sockets we can't use the size of sockaddr_storage
1101                  * we would get EINVAL
1102                  */
1103                 sa_len = sizeof(lbsda->u.un);
1104                 break;
1105         case AF_INET:
1106                 if (lbsda->u.in.sin_port != 0) {
1107                         do_reuseaddr = true;
1108                         do_bind = true;
1109                 }
1110                 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1111                         do_bind = true;
1112                 }
1113                 break;
1114 #ifdef HAVE_IPV6
1115         case AF_INET6:
1116                 if (lbsda->u.in6.sin6_port != 0) {
1117                         do_reuseaddr = true;
1118                         do_bind = true;
1119                 }
1120                 if (memcmp(&in6addr_any,
1121                            &lbsda->u.in6.sin6_addr,
1122                            sizeof(in6addr_any)) != 0) {
1123                         do_bind = true;
1124                 }
1125                 break;
1126 #endif
1127         default:
1128                 errno = EINVAL;
1129                 return -1;
1130         }
1131
1132         fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
1133         if (fd < 0) {
1134                 return fd;
1135         }
1136
1137         fd = tsocket_bsd_common_prepare_fd(fd, true);
1138         if (fd < 0) {
1139                 return fd;
1140         }
1141
1142         dgram = tdgram_context_create(mem_ctx,
1143                                       &tdgram_bsd_ops,
1144                                       &bsds,
1145                                       struct tdgram_bsd,
1146                                       location);
1147         if (!dgram) {
1148                 int saved_errno = errno;
1149                 close(fd);
1150                 errno = saved_errno;
1151                 return -1;
1152         }
1153         ZERO_STRUCTP(bsds);
1154         bsds->fd = fd;
1155         talloc_set_destructor(bsds, tdgram_bsd_destructor);
1156
1157         if (broadcast) {
1158                 int val = 1;
1159
1160                 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1161                                  (const void *)&val, sizeof(val));
1162                 if (ret == -1) {
1163                         int saved_errno = errno;
1164                         talloc_free(dgram);
1165                         errno = saved_errno;
1166                         return ret;
1167                 }
1168         }
1169
1170         if (do_reuseaddr) {
1171                 int val = 1;
1172
1173                 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1174                                  (const void *)&val, sizeof(val));
1175                 if (ret == -1) {
1176                         int saved_errno = errno;
1177                         talloc_free(dgram);
1178                         errno = saved_errno;
1179                         return ret;
1180                 }
1181         }
1182
1183         if (do_bind) {
1184                 ret = bind(fd, &lbsda->u.sa, sa_len);
1185                 if (ret == -1) {
1186                         int saved_errno = errno;
1187                         talloc_free(dgram);
1188                         errno = saved_errno;
1189                         return ret;
1190                 }
1191         }
1192
1193         if (rbsda) {
1194                 ret = connect(fd, &rbsda->u.sa, sa_len);
1195                 if (ret == -1) {
1196                         int saved_errno = errno;
1197                         talloc_free(dgram);
1198                         errno = saved_errno;
1199                         return ret;
1200                 }
1201         }
1202
1203         *_dgram = dgram;
1204         return 0;
1205 }
1206
1207 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1208                             const struct tsocket_address *remote,
1209                             TALLOC_CTX *mem_ctx,
1210                             struct tdgram_context **dgram,
1211                             const char *location)
1212 {
1213         struct tsocket_address_bsd *lbsda =
1214                 talloc_get_type_abort(local->private_data,
1215                 struct tsocket_address_bsd);
1216         int ret;
1217
1218         switch (lbsda->u.sa.sa_family) {
1219         case AF_INET:
1220                 break;
1221 #ifdef HAVE_IPV6
1222         case AF_INET6:
1223                 break;
1224 #endif
1225         default:
1226                 errno = EINVAL;
1227                 return -1;
1228         }
1229
1230         ret = tdgram_bsd_dgram_socket(local, remote, false,
1231                                       mem_ctx, dgram, location);
1232
1233         return ret;
1234 }
1235
1236 int _tdgram_unix_socket(const struct tsocket_address *local,
1237                         const struct tsocket_address *remote,
1238                         TALLOC_CTX *mem_ctx,
1239                         struct tdgram_context **dgram,
1240                         const char *location)
1241 {
1242         struct tsocket_address_bsd *lbsda =
1243                 talloc_get_type_abort(local->private_data,
1244                 struct tsocket_address_bsd);
1245         int ret;
1246
1247         switch (lbsda->u.sa.sa_family) {
1248         case AF_UNIX:
1249                 break;
1250         default:
1251                 errno = EINVAL;
1252                 return -1;
1253         }
1254
1255         ret = tdgram_bsd_dgram_socket(local, remote, false,
1256                                       mem_ctx, dgram, location);
1257
1258         return ret;
1259 }
1260
1261 struct tstream_bsd {
1262         int fd;
1263
1264         void *event_ptr;
1265         struct tevent_fd *fde;
1266
1267         void *readable_private;
1268         void (*readable_handler)(void *private_data);
1269         void *writeable_private;
1270         void (*writeable_handler)(void *private_data);
1271 };
1272
1273 static void tstream_bsd_fde_handler(struct tevent_context *ev,
1274                                     struct tevent_fd *fde,
1275                                     uint16_t flags,
1276                                     void *private_data)
1277 {
1278         struct tstream_bsd *bsds = talloc_get_type_abort(private_data,
1279                                    struct tstream_bsd);
1280
1281         if (flags & TEVENT_FD_WRITE) {
1282                 bsds->writeable_handler(bsds->writeable_private);
1283                 return;
1284         }
1285         if (flags & TEVENT_FD_READ) {
1286                 if (!bsds->readable_handler) {
1287                         TEVENT_FD_NOT_READABLE(bsds->fde);
1288                         return;
1289                 }
1290                 bsds->readable_handler(bsds->readable_private);
1291                 return;
1292         }
1293 }
1294
1295 static int tstream_bsd_set_readable_handler(struct tstream_bsd *bsds,
1296                                             struct tevent_context *ev,
1297                                             void (*handler)(void *private_data),
1298                                             void *private_data)
1299 {
1300         if (ev == NULL) {
1301                 if (handler) {
1302                         errno = EINVAL;
1303                         return -1;
1304                 }
1305                 if (!bsds->readable_handler) {
1306                         return 0;
1307                 }
1308                 bsds->readable_handler = NULL;
1309                 bsds->readable_private = NULL;
1310
1311                 return 0;
1312         }
1313
1314         /* read and write must use the same tevent_context */
1315         if (bsds->event_ptr != ev) {
1316                 if (bsds->readable_handler || bsds->writeable_handler) {
1317                         errno = EINVAL;
1318                         return -1;
1319                 }
1320                 bsds->event_ptr = NULL;
1321                 TALLOC_FREE(bsds->fde);
1322         }
1323
1324         if (bsds->fde == NULL) {
1325                 bsds->fde = tevent_add_fd(ev, bsds,
1326                                           bsds->fd, TEVENT_FD_READ,
1327                                           tstream_bsd_fde_handler,
1328                                           bsds);
1329                 if (!bsds->fde) {
1330                         return -1;
1331                 }
1332
1333                 /* cache the event context we're running on */
1334                 bsds->event_ptr = ev;
1335         } else if (!bsds->readable_handler) {
1336                 TEVENT_FD_READABLE(bsds->fde);
1337         }
1338
1339         bsds->readable_handler = handler;
1340         bsds->readable_private = private_data;
1341
1342         return 0;
1343 }
1344
1345 static int tstream_bsd_set_writeable_handler(struct tstream_bsd *bsds,
1346                                              struct tevent_context *ev,
1347                                              void (*handler)(void *private_data),
1348                                              void *private_data)
1349 {
1350         if (ev == NULL) {
1351                 if (handler) {
1352                         errno = EINVAL;
1353                         return -1;
1354                 }
1355                 if (!bsds->writeable_handler) {
1356                         return 0;
1357                 }
1358                 bsds->writeable_handler = NULL;
1359                 bsds->writeable_private = NULL;
1360                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1361
1362                 return 0;
1363         }
1364
1365         /* read and write must use the same tevent_context */
1366         if (bsds->event_ptr != ev) {
1367                 if (bsds->readable_handler || bsds->writeable_handler) {
1368                         errno = EINVAL;
1369                         return -1;
1370                 }
1371                 bsds->event_ptr = NULL;
1372                 TALLOC_FREE(bsds->fde);
1373         }
1374
1375         if (bsds->fde == NULL) {
1376                 bsds->fde = tevent_add_fd(ev, bsds,
1377                                           bsds->fd, TEVENT_FD_WRITE,
1378                                           tstream_bsd_fde_handler,
1379                                           bsds);
1380                 if (!bsds->fde) {
1381                         return -1;
1382                 }
1383
1384                 /* cache the event context we're running on */
1385                 bsds->event_ptr = ev;
1386         } else if (!bsds->writeable_handler) {
1387                 TEVENT_FD_WRITEABLE(bsds->fde);
1388         }
1389
1390         bsds->writeable_handler = handler;
1391         bsds->writeable_private = private_data;
1392
1393         return 0;
1394 }
1395
1396 static ssize_t tstream_bsd_pending_bytes(struct tstream_context *stream)
1397 {
1398         struct tstream_bsd *bsds = tstream_context_data(stream,
1399                                    struct tstream_bsd);
1400         ssize_t ret;
1401
1402         if (bsds->fd == -1) {
1403                 errno = ENOTCONN;
1404                 return -1;
1405         }
1406
1407         ret = tsocket_bsd_pending(bsds->fd);
1408
1409         return ret;
1410 }
1411
1412 struct tstream_bsd_readv_state {
1413         struct tstream_context *stream;
1414
1415         struct iovec *vector;
1416         size_t count;
1417
1418         int ret;
1419 };
1420
1421 static int tstream_bsd_readv_destructor(struct tstream_bsd_readv_state *state)
1422 {
1423         struct tstream_bsd *bsds = tstream_context_data(state->stream,
1424                                    struct tstream_bsd);
1425
1426         tstream_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1427
1428         return 0;
1429 }
1430
1431 static void tstream_bsd_readv_handler(void *private_data);
1432
1433 static struct tevent_req *tstream_bsd_readv_send(TALLOC_CTX *mem_ctx,
1434                                         struct tevent_context *ev,
1435                                         struct tstream_context *stream,
1436                                         struct iovec *vector,
1437                                         size_t count)
1438 {
1439         struct tevent_req *req;
1440         struct tstream_bsd_readv_state *state;
1441         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1442         int ret;
1443
1444         req = tevent_req_create(mem_ctx, &state,
1445                                 struct tstream_bsd_readv_state);
1446         if (!req) {
1447                 return NULL;
1448         }
1449
1450         state->stream   = stream;
1451         /* we make a copy of the vector so that we can modify it */
1452         state->vector   = talloc_array(state, struct iovec, count);
1453         if (tevent_req_nomem(state->vector, req)) {
1454                 goto post;
1455         }
1456         memcpy(state->vector, vector, sizeof(struct iovec)*count);
1457         state->count    = count;
1458         state->ret      = 0;
1459
1460         talloc_set_destructor(state, tstream_bsd_readv_destructor);
1461
1462         if (bsds->fd == -1) {
1463                 tevent_req_error(req, ENOTCONN);
1464                 goto post;
1465         }
1466
1467         /*
1468          * this is a fast path, not waiting for the
1469          * socket to become explicit readable gains
1470          * about 10%-20% performance in benchmark tests.
1471          */
1472         tstream_bsd_readv_handler(req);
1473         if (!tevent_req_is_in_progress(req)) {
1474                 goto post;
1475         }
1476
1477         ret = tstream_bsd_set_readable_handler(bsds, ev,
1478                                               tstream_bsd_readv_handler,
1479                                               req);
1480         if (ret == -1) {
1481                 tevent_req_error(req, errno);
1482                 goto post;
1483         }
1484
1485         return req;
1486
1487  post:
1488         tevent_req_post(req, ev);
1489         return req;
1490 }
1491
1492 static void tstream_bsd_readv_handler(void *private_data)
1493 {
1494         struct tevent_req *req = talloc_get_type_abort(private_data,
1495                                  struct tevent_req);
1496         struct tstream_bsd_readv_state *state = tevent_req_data(req,
1497                                         struct tstream_bsd_readv_state);
1498         struct tstream_context *stream = state->stream;
1499         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1500         int ret;
1501         int err;
1502         bool retry;
1503
1504         ret = readv(bsds->fd, state->vector, state->count);
1505         if (ret == 0) {
1506                 /* propagate end of file */
1507                 tevent_req_error(req, EPIPE);
1508                 return;
1509         }
1510         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1511         if (retry) {
1512                 /* retry later */
1513                 return;
1514         }
1515         if (tevent_req_error(req, err)) {
1516                 return;
1517         }
1518
1519         state->ret += ret;
1520
1521         while (ret > 0) {
1522                 if (ret < state->vector[0].iov_len) {
1523                         uint8_t *base;
1524                         base = (uint8_t *)state->vector[0].iov_base;
1525                         base += ret;
1526                         state->vector[0].iov_base = base;
1527                         state->vector[0].iov_len -= ret;
1528                         break;
1529                 }
1530                 ret -= state->vector[0].iov_len;
1531                 state->vector += 1;
1532                 state->count -= 1;
1533         }
1534
1535         if (state->count > 0) {
1536                 /* we have more to read */
1537                 return;
1538         }
1539
1540         tevent_req_done(req);
1541 }
1542
1543 static int tstream_bsd_readv_recv(struct tevent_req *req,
1544                                   int *perrno)
1545 {
1546         struct tstream_bsd_readv_state *state = tevent_req_data(req,
1547                                         struct tstream_bsd_readv_state);
1548         int ret;
1549
1550         ret = tsocket_simple_int_recv(req, perrno);
1551         if (ret == 0) {
1552                 ret = state->ret;
1553         }
1554
1555         tevent_req_received(req);
1556         return ret;
1557 }
1558
1559 struct tstream_bsd_writev_state {
1560         struct tstream_context *stream;
1561
1562         struct iovec *vector;
1563         size_t count;
1564
1565         int ret;
1566 };
1567
1568 static int tstream_bsd_writev_destructor(struct tstream_bsd_writev_state *state)
1569 {
1570         struct tstream_bsd *bsds = tstream_context_data(state->stream,
1571                                   struct tstream_bsd);
1572
1573         tstream_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1574
1575         return 0;
1576 }
1577
1578 static void tstream_bsd_writev_handler(void *private_data);
1579
1580 static struct tevent_req *tstream_bsd_writev_send(TALLOC_CTX *mem_ctx,
1581                                                  struct tevent_context *ev,
1582                                                  struct tstream_context *stream,
1583                                                  const struct iovec *vector,
1584                                                  size_t count)
1585 {
1586         struct tevent_req *req;
1587         struct tstream_bsd_writev_state *state;
1588         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1589         int ret;
1590
1591         req = tevent_req_create(mem_ctx, &state,
1592                                 struct tstream_bsd_writev_state);
1593         if (!req) {
1594                 return NULL;
1595         }
1596
1597         state->stream   = stream;
1598         /* we make a copy of the vector so that we can modify it */
1599         state->vector   = talloc_array(state, struct iovec, count);
1600         if (tevent_req_nomem(state->vector, req)) {
1601                 goto post;
1602         }
1603         memcpy(state->vector, vector, sizeof(struct iovec)*count);
1604         state->count    = count;
1605         state->ret      = 0;
1606
1607         talloc_set_destructor(state, tstream_bsd_writev_destructor);
1608
1609         if (bsds->fd == -1) {
1610                 tevent_req_error(req, ENOTCONN);
1611                 goto post;
1612         }
1613
1614         /*
1615          * this is a fast path, not waiting for the
1616          * socket to become explicit writeable gains
1617          * about 10%-20% performance in benchmark tests.
1618          */
1619         tstream_bsd_writev_handler(req);
1620         if (!tevent_req_is_in_progress(req)) {
1621                 goto post;
1622         }
1623
1624         ret = tstream_bsd_set_writeable_handler(bsds, ev,
1625                                                tstream_bsd_writev_handler,
1626                                                req);
1627         if (ret == -1) {
1628                 tevent_req_error(req, errno);
1629                 goto post;
1630         }
1631
1632         return req;
1633
1634  post:
1635         tevent_req_post(req, ev);
1636         return req;
1637 }
1638
1639 static void tstream_bsd_writev_handler(void *private_data)
1640 {
1641         struct tevent_req *req = talloc_get_type_abort(private_data,
1642                                  struct tevent_req);
1643         struct tstream_bsd_writev_state *state = tevent_req_data(req,
1644                                         struct tstream_bsd_writev_state);
1645         struct tstream_context *stream = state->stream;
1646         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1647         ssize_t ret;
1648         int err;
1649         bool retry;
1650
1651         ret = writev(bsds->fd, state->vector, state->count);
1652         if (ret == 0) {
1653                 /* propagate end of file */
1654                 tevent_req_error(req, EPIPE);
1655                 return;
1656         }
1657         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1658         if (retry) {
1659                 /* retry later */
1660                 return;
1661         }
1662         if (tevent_req_error(req, err)) {
1663                 return;
1664         }
1665
1666         state->ret += ret;
1667
1668         while (ret > 0) {
1669                 if (ret < state->vector[0].iov_len) {
1670                         uint8_t *base;
1671                         base = (uint8_t *)state->vector[0].iov_base;
1672                         base += ret;
1673                         state->vector[0].iov_base = base;
1674                         state->vector[0].iov_len -= ret;
1675                         break;
1676                 }
1677                 ret -= state->vector[0].iov_len;
1678                 state->vector += 1;
1679                 state->count -= 1;
1680         }
1681
1682         if (state->count > 0) {
1683                 /* we have more to read */
1684                 return;
1685         }
1686
1687         tevent_req_done(req);
1688 }
1689
1690 static int tstream_bsd_writev_recv(struct tevent_req *req, int *perrno)
1691 {
1692         struct tstream_bsd_writev_state *state = tevent_req_data(req,
1693                                         struct tstream_bsd_writev_state);
1694         int ret;
1695
1696         ret = tsocket_simple_int_recv(req, perrno);
1697         if (ret == 0) {
1698                 ret = state->ret;
1699         }
1700
1701         tevent_req_received(req);
1702         return ret;
1703 }
1704
1705 struct tstream_bsd_disconnect_state {
1706         void *__dummy;
1707 };
1708
1709 static struct tevent_req *tstream_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1710                                                      struct tevent_context *ev,
1711                                                      struct tstream_context *stream)
1712 {
1713         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1714         struct tevent_req *req;
1715         struct tstream_bsd_disconnect_state *state;
1716         int ret;
1717         int err;
1718         bool dummy;
1719
1720         req = tevent_req_create(mem_ctx, &state,
1721                                 struct tstream_bsd_disconnect_state);
1722         if (req == NULL) {
1723                 return NULL;
1724         }
1725
1726         if (bsds->fd == -1) {
1727                 tevent_req_error(req, ENOTCONN);
1728                 goto post;
1729         }
1730
1731         ret = close(bsds->fd);
1732         bsds->fd = -1;
1733         err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1734         if (tevent_req_error(req, err)) {
1735                 goto post;
1736         }
1737
1738         tevent_req_done(req);
1739 post:
1740         tevent_req_post(req, ev);
1741         return req;
1742 }
1743
1744 static int tstream_bsd_disconnect_recv(struct tevent_req *req,
1745                                       int *perrno)
1746 {
1747         int ret;
1748
1749         ret = tsocket_simple_int_recv(req, perrno);
1750
1751         tevent_req_received(req);
1752         return ret;
1753 }
1754
1755 static const struct tstream_context_ops tstream_bsd_ops = {
1756         .name                   = "bsd",
1757
1758         .pending_bytes          = tstream_bsd_pending_bytes,
1759
1760         .readv_send             = tstream_bsd_readv_send,
1761         .readv_recv             = tstream_bsd_readv_recv,
1762
1763         .writev_send            = tstream_bsd_writev_send,
1764         .writev_recv            = tstream_bsd_writev_recv,
1765
1766         .disconnect_send        = tstream_bsd_disconnect_send,
1767         .disconnect_recv        = tstream_bsd_disconnect_recv,
1768 };
1769
1770 static int tstream_bsd_destructor(struct tstream_bsd *bsds)
1771 {
1772         TALLOC_FREE(bsds->fde);
1773         if (bsds->fd != -1) {
1774                 close(bsds->fd);
1775                 bsds->fd = -1;
1776         }
1777         return 0;
1778 }
1779
1780 int _tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
1781                                  int fd,
1782                                  struct tstream_context **_stream,
1783                                  const char *location)
1784 {
1785         struct tstream_context *stream;
1786         struct tstream_bsd *bsds;
1787
1788         stream = tstream_context_create(mem_ctx,
1789                                         &tstream_bsd_ops,
1790                                         &bsds,
1791                                         struct tstream_bsd,
1792                                         location);
1793         if (!stream) {
1794                 return -1;
1795         }
1796         ZERO_STRUCTP(bsds);
1797         bsds->fd = fd;
1798         talloc_set_destructor(bsds, tstream_bsd_destructor);
1799
1800         *_stream = stream;
1801         return 0;
1802 }
1803
1804 struct tstream_bsd_connect_state {
1805         int fd;
1806         struct tevent_fd *fde;
1807         struct tstream_conext *stream;
1808 };
1809
1810 static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state *state)
1811 {
1812         TALLOC_FREE(state->fde);
1813         if (state->fd != -1) {
1814                 close(state->fd);
1815                 state->fd = -1;
1816         }
1817
1818         return 0;
1819 }
1820
1821 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
1822                                             struct tevent_fd *fde,
1823                                             uint16_t flags,
1824                                             void *private_data);
1825
1826 static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
1827                                         struct tevent_context *ev,
1828                                         int sys_errno,
1829                                         const struct tsocket_address *local,
1830                                         const struct tsocket_address *remote)
1831 {
1832         struct tevent_req *req;
1833         struct tstream_bsd_connect_state *state;
1834         struct tsocket_address_bsd *lbsda =
1835                 talloc_get_type_abort(local->private_data,
1836                 struct tsocket_address_bsd);
1837         struct tsocket_address_bsd *rbsda =
1838                 talloc_get_type_abort(remote->private_data,
1839                 struct tsocket_address_bsd);
1840         int ret;
1841         int err;
1842         bool retry;
1843         bool do_bind = false;
1844         bool do_reuseaddr = false;
1845         socklen_t sa_len = sizeof(rbsda->u.ss);
1846
1847         req = tevent_req_create(mem_ctx, &state,
1848                                 struct tstream_bsd_connect_state);
1849         if (!req) {
1850                 return NULL;
1851         }
1852         state->fd = -1;
1853         state->fde = NULL;
1854
1855         talloc_set_destructor(state, tstream_bsd_connect_destructor);
1856
1857         /* give the wrappers a chance to report an error */
1858         if (sys_errno != 0) {
1859                 tevent_req_error(req, sys_errno);
1860                 goto post;
1861         }
1862
1863         switch (lbsda->u.sa.sa_family) {
1864         case AF_UNIX:
1865                 if (lbsda->u.un.sun_path[0] != 0) {
1866                         do_reuseaddr = true;
1867                         do_bind = true;
1868                 }
1869                 /*
1870                  * for unix sockets we can't use the size of sockaddr_storage
1871                  * we would get EINVAL
1872                  */
1873                 sa_len = sizeof(rbsda->u.un);
1874                 break;
1875         case AF_INET:
1876                 if (lbsda->u.in.sin_port != 0) {
1877                         do_reuseaddr = true;
1878                         do_bind = true;
1879                 }
1880                 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1881                         do_bind = true;
1882                 }
1883                 break;
1884 #ifdef HAVE_IPV6
1885         case AF_INET6:
1886                 if (lbsda->u.in6.sin6_port != 0) {
1887                         do_reuseaddr = true;
1888                         do_bind = true;
1889                 }
1890                 if (memcmp(&in6addr_any,
1891                            &lbsda->u.in6.sin6_addr,
1892                            sizeof(in6addr_any)) != 0) {
1893                         do_bind = true;
1894                 }
1895                 break;
1896 #endif
1897         default:
1898                 tevent_req_error(req, EINVAL);
1899                 goto post;
1900         }
1901
1902         state->fd = socket(lbsda->u.sa.sa_family, SOCK_STREAM, 0);
1903         if (state->fd == -1) {
1904                 tevent_req_error(req, errno);
1905                 goto post;
1906         }
1907
1908         state->fd = tsocket_bsd_common_prepare_fd(state->fd, true);
1909         if (state->fd == -1) {
1910                 tevent_req_error(req, errno);
1911                 goto post;
1912         }
1913
1914         if (do_reuseaddr) {
1915                 int val = 1;
1916
1917                 ret = setsockopt(state->fd, SOL_SOCKET, SO_REUSEADDR,
1918                                  (const void *)&val, sizeof(val));
1919                 if (ret == -1) {
1920                         tevent_req_error(req, errno);
1921                         goto post;
1922                 }
1923         }
1924
1925         if (do_bind) {
1926                 ret = bind(state->fd, &lbsda->u.sa, sizeof(lbsda->u.ss));
1927                 if (ret == -1) {
1928                         tevent_req_error(req, errno);
1929                         goto post;
1930                 }
1931         }
1932
1933         ret = connect(state->fd, &rbsda->u.sa, sa_len);
1934         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1935         if (retry) {
1936                 /* retry later */
1937                 goto async;
1938         }
1939         if (tevent_req_error(req, err)) {
1940                 goto post;
1941         }
1942
1943         tevent_req_done(req);
1944         goto post;
1945
1946  async:
1947         state->fde = tevent_add_fd(ev, state,
1948                                    state->fd,
1949                                    TEVENT_FD_READ | TEVENT_FD_WRITE,
1950                                    tstream_bsd_connect_fde_handler,
1951                                    req);
1952         if (tevent_req_nomem(state->fde, req)) {
1953                 goto post;
1954         }
1955
1956         return req;
1957
1958  post:
1959         tevent_req_post(req, ev);
1960         return req;
1961 }
1962
1963 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
1964                                             struct tevent_fd *fde,
1965                                             uint16_t flags,
1966                                             void *private_data)
1967 {
1968         struct tevent_req *req = talloc_get_type_abort(private_data,
1969                                  struct tevent_req);
1970         struct tstream_bsd_connect_state *state = tevent_req_data(req,
1971                                         struct tstream_bsd_connect_state);
1972         int ret;
1973         int error=0;
1974         socklen_t len = sizeof(error);
1975         int err;
1976         bool retry;
1977
1978         ret = getsockopt(state->fd, SOL_SOCKET, SO_ERROR, &error, &len);
1979         if (ret == 0) {
1980                 if (error != 0) {
1981                         errno = error;
1982                         ret = -1;
1983                 }
1984         }
1985         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1986         if (retry) {
1987                 /* retry later */
1988                 return;
1989         }
1990         if (tevent_req_error(req, err)) {
1991                 return;
1992         }
1993
1994         tevent_req_done(req);
1995 }
1996
1997 static int tstream_bsd_connect_recv(struct tevent_req *req,
1998                                     int *perrno,
1999                                     TALLOC_CTX *mem_ctx,
2000                                     struct tstream_context **stream,
2001                                     const char *location)
2002 {
2003         struct tstream_bsd_connect_state *state = tevent_req_data(req,
2004                                         struct tstream_bsd_connect_state);
2005         int ret;
2006
2007         ret = tsocket_simple_int_recv(req, perrno);
2008         if (ret == 0) {
2009                 ret = _tstream_bsd_existing_socket(mem_ctx,
2010                                                    state->fd,
2011                                                    stream,
2012                                                    location);
2013                 if (ret == -1) {
2014                         *perrno = errno;
2015                         goto done;
2016                 }
2017                 TALLOC_FREE(state->fde);
2018                 state->fd = -1;
2019         }
2020
2021 done:
2022         tevent_req_received(req);
2023         return ret;
2024 }
2025
2026 struct tevent_req * tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
2027                                         struct tevent_context *ev,
2028                                         const struct tsocket_address *local,
2029                                         const struct tsocket_address *remote)
2030 {
2031         struct tsocket_address_bsd *lbsda =
2032                 talloc_get_type_abort(local->private_data,
2033                 struct tsocket_address_bsd);
2034         struct tevent_req *req;
2035         int sys_errno = 0;
2036
2037         switch (lbsda->u.sa.sa_family) {
2038         case AF_INET:
2039                 break;
2040 #ifdef HAVE_IPV6
2041         case AF_INET6:
2042                 break;
2043 #endif
2044         default:
2045                 sys_errno = EINVAL;
2046                 break;
2047         }
2048
2049         req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2050
2051         return req;
2052 }
2053
2054 int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
2055                                    int *perrno,
2056                                    TALLOC_CTX *mem_ctx,
2057                                    struct tstream_context **stream,
2058                                    const char *location)
2059 {
2060         return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
2061 }
2062
2063 struct tevent_req * tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
2064                                         struct tevent_context *ev,
2065                                         const struct tsocket_address *local,
2066                                         const struct tsocket_address *remote)
2067 {
2068         struct tsocket_address_bsd *lbsda =
2069                 talloc_get_type_abort(local->private_data,
2070                 struct tsocket_address_bsd);
2071         struct tevent_req *req;
2072         int sys_errno = 0;
2073
2074         switch (lbsda->u.sa.sa_family) {
2075         case AF_UNIX:
2076                 break;
2077         default:
2078                 sys_errno = EINVAL;
2079                 break;
2080         }
2081
2082         req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2083
2084         return req;
2085 }
2086
2087 int _tstream_unix_connect_recv(struct tevent_req *req,
2088                                       int *perrno,
2089                                       TALLOC_CTX *mem_ctx,
2090                                       struct tstream_context **stream,
2091                                       const char *location)
2092 {
2093         return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
2094 }
2095
2096 int _tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
2097                              struct tstream_context **_stream1,
2098                              TALLOC_CTX *mem_ctx2,
2099                              struct tstream_context **_stream2,
2100                              const char *location)
2101 {
2102         int ret;
2103         int fds[2];
2104         int fd1;
2105         int fd2;
2106         struct tstream_context *stream1 = NULL;
2107         struct tstream_context *stream2 = NULL;
2108
2109         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
2110         if (ret == -1) {
2111                 return -1;
2112         }
2113         fd1 = fds[0];
2114         fd2 = fds[1];
2115
2116         fd1 = tsocket_bsd_common_prepare_fd(fd1, true);
2117         if (fd1 == -1) {
2118                 int sys_errno = errno;
2119                 close(fd2);
2120                 errno = sys_errno;
2121                 return -1;
2122         }
2123
2124         fd2 = tsocket_bsd_common_prepare_fd(fd2, true);
2125         if (fd2 == -1) {
2126                 int sys_errno = errno;
2127                 close(fd1);
2128                 errno = sys_errno;
2129                 return -1;
2130         }
2131
2132         ret = _tstream_bsd_existing_socket(mem_ctx1,
2133                                            fd1,
2134                                            &stream1,
2135                                            location);
2136         if (ret == -1) {
2137                 int sys_errno = errno;
2138                 close(fd1);
2139                 close(fd2);
2140                 errno = sys_errno;
2141                 return -1;
2142         }
2143
2144         ret = _tstream_bsd_existing_socket(mem_ctx2,
2145                                            fd2,
2146                                            &stream2,
2147                                            location);
2148         if (ret == -1) {
2149                 int sys_errno = errno;
2150                 talloc_free(stream1);
2151                 close(fd2);
2152                 errno = sys_errno;
2153                 return -1;
2154         }
2155
2156         *_stream1 = stream1;
2157         *_stream2 = stream2;
2158         return 0;
2159 }
2160