Revert "tsocket_bsd use sendmsg/recvmsg"
[metze/samba/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 tsocket
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 #include "lib/util/iov_buf.h"
30 #include "lib/util/blocking.h"
31
32 static int tsocket_bsd_error_from_errno(int ret,
33                                         int sys_errno,
34                                         bool *retry)
35 {
36         *retry = false;
37
38         if (ret >= 0) {
39                 return 0;
40         }
41
42         if (ret != -1) {
43                 return EIO;
44         }
45
46         if (sys_errno == 0) {
47                 return EIO;
48         }
49
50         if (sys_errno == EINTR) {
51                 *retry = true;
52                 return sys_errno;
53         }
54
55         if (sys_errno == EINPROGRESS) {
56                 *retry = true;
57                 return sys_errno;
58         }
59
60         if (sys_errno == EAGAIN) {
61                 *retry = true;
62                 return sys_errno;
63         }
64
65         /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
66         if (sys_errno == ENOMEM) {
67                 *retry = true;
68                 return sys_errno;
69         }
70
71 #ifdef EWOULDBLOCK
72         if (sys_errno == EWOULDBLOCK) {
73                 *retry = true;
74                 return sys_errno;
75         }
76 #endif
77
78         return sys_errno;
79 }
80
81 static int tsocket_bsd_common_prepare_fd(int fd, bool high_fd)
82 {
83         int i;
84         int sys_errno = 0;
85         int fds[3];
86         int num_fds = 0;
87
88         int result;
89         bool ok;
90
91         if (fd == -1) {
92                 return -1;
93         }
94
95         /* first make a fd >= 3 */
96         if (high_fd) {
97                 while (fd < 3) {
98                         fds[num_fds++] = fd;
99                         fd = dup(fd);
100                         if (fd == -1) {
101                                 sys_errno = errno;
102                                 break;
103                         }
104                 }
105                 for (i=0; i<num_fds; i++) {
106                         close(fds[i]);
107                 }
108                 if (fd == -1) {
109                         errno = sys_errno;
110                         return fd;
111                 }
112         }
113
114         result = set_blocking(fd, false);
115         if (result == -1) {
116                 goto fail;
117         }
118
119         ok = smb_set_close_on_exec(fd);
120         if (!ok) {
121                 goto fail;
122         }
123
124         return fd;
125
126  fail:
127         if (fd != -1) {
128                 sys_errno = errno;
129                 close(fd);
130                 errno = sys_errno;
131         }
132         return -1;
133 }
134
135 #ifdef HAVE_LINUX_RTNETLINK_H
136 /**
137  * Get the amount of pending bytes from a netlink socket
138  *
139  * For some reason netlink sockets don't support querying the amount of pending
140  * data via ioctl with FIONREAD, which is what we use in tsocket_bsd_pending()
141  * below.
142  *
143  * We know we are on Linux as we're using netlink, which means we have a working
144  * MSG_TRUNC flag to recvmsg() as well, so we use that together with MSG_PEEK.
145  **/
146 static ssize_t tsocket_bsd_netlink_pending(int fd)
147 {
148         struct iovec iov;
149         struct msghdr msg;
150         char buf[1];
151
152         iov = (struct iovec) {
153                 .iov_base = buf,
154                 .iov_len = sizeof(buf)
155         };
156
157         msg = (struct msghdr) {
158                 .msg_iov = &iov,
159                 .msg_iovlen = 1
160         };
161
162         return recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
163 }
164 #else
165 static ssize_t tsocket_bsd_netlink_pending(int fd)
166 {
167         errno = ENOSYS;
168         return -1;
169 }
170 #endif
171
172 static ssize_t tsocket_bsd_pending(int fd)
173 {
174         int ret, error;
175         int value = 0;
176         socklen_t len;
177
178         ret = ioctl(fd, FIONREAD, &value);
179         if (ret == -1) {
180                 return ret;
181         }
182
183         if (ret != 0) {
184                 /* this should not be reached */
185                 errno = EIO;
186                 return -1;
187         }
188
189         if (value != 0) {
190                 return value;
191         }
192
193         error = 0;
194         len = sizeof(error);
195
196         /*
197          * if no data is available check if the socket is in error state. For
198          * dgram sockets it's the way to return ICMP error messages of
199          * connected sockets to the caller.
200          */
201         ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
202         if (ret == -1) {
203                 return ret;
204         }
205         if (error != 0) {
206                 errno = error;
207                 return -1;
208         }
209         return 0;
210 }
211
212 static const struct tsocket_address_ops tsocket_address_bsd_ops;
213
214 struct tsocket_address_bsd {
215         socklen_t sa_socklen;
216         union {
217                 struct sockaddr sa;
218                 struct sockaddr_in in;
219 #ifdef HAVE_IPV6
220                 struct sockaddr_in6 in6;
221 #endif
222                 struct sockaddr_un un;
223                 struct sockaddr_storage ss;
224         } u;
225 };
226
227 int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
228                                        const struct sockaddr *sa,
229                                        size_t sa_socklen,
230                                        struct tsocket_address **_addr,
231                                        const char *location)
232 {
233         struct tsocket_address *addr;
234         struct tsocket_address_bsd *bsda;
235
236         if (sa_socklen < sizeof(sa->sa_family)) {
237                 errno = EINVAL;
238                 return -1;
239         }
240
241         switch (sa->sa_family) {
242         case AF_UNIX:
243                 if (sa_socklen > sizeof(struct sockaddr_un)) {
244                         sa_socklen = sizeof(struct sockaddr_un);
245                 }
246                 break;
247         case AF_INET:
248                 if (sa_socklen < sizeof(struct sockaddr_in)) {
249                         errno = EINVAL;
250                         return -1;
251                 }
252                 sa_socklen = sizeof(struct sockaddr_in);
253                 break;
254 #ifdef HAVE_IPV6
255         case AF_INET6:
256                 if (sa_socklen < sizeof(struct sockaddr_in6)) {
257                         errno = EINVAL;
258                         return -1;
259                 }
260                 sa_socklen = sizeof(struct sockaddr_in6);
261                 break;
262 #endif
263         default:
264                 errno = EAFNOSUPPORT;
265                 return -1;
266         }
267
268         if (sa_socklen > sizeof(struct sockaddr_storage)) {
269                 errno = EINVAL;
270                 return -1;
271         }
272
273         addr = tsocket_address_create(mem_ctx,
274                                       &tsocket_address_bsd_ops,
275                                       &bsda,
276                                       struct tsocket_address_bsd,
277                                       location);
278         if (!addr) {
279                 errno = ENOMEM;
280                 return -1;
281         }
282
283         ZERO_STRUCTP(bsda);
284
285         memcpy(&bsda->u.ss, sa, sa_socklen);
286
287         bsda->sa_socklen = sa_socklen;
288 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
289         bsda->u.sa.sa_len = bsda->sa_socklen;
290 #endif
291
292         *_addr = addr;
293         return 0;
294 }
295
296 ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
297                                      struct sockaddr *sa,
298                                      size_t sa_socklen)
299 {
300         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
301                                            struct tsocket_address_bsd);
302
303         if (!bsda) {
304                 errno = EINVAL;
305                 return -1;
306         }
307
308         if (sa_socklen < bsda->sa_socklen) {
309                 errno = EINVAL;
310                 return -1;
311         }
312
313         if (sa_socklen > bsda->sa_socklen) {
314                 memset(sa, 0, sa_socklen);
315                 sa_socklen = bsda->sa_socklen;
316         }
317
318         memcpy(sa, &bsda->u.ss, sa_socklen);
319 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
320         sa->sa_len = sa_socklen;
321 #endif
322         return sa_socklen;
323 }
324
325 bool tsocket_address_is_inet(const struct tsocket_address *addr, const char *fam)
326 {
327         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
328                                            struct tsocket_address_bsd);
329
330         if (!bsda) {
331                 return false;
332         }
333
334         switch (bsda->u.sa.sa_family) {
335         case AF_INET:
336                 if (strcasecmp(fam, "ip") == 0) {
337                         return true;
338                 }
339
340                 if (strcasecmp(fam, "ipv4") == 0) {
341                         return true;
342                 }
343
344                 return false;
345 #ifdef HAVE_IPV6
346         case AF_INET6:
347                 if (strcasecmp(fam, "ip") == 0) {
348                         return true;
349                 }
350
351                 if (strcasecmp(fam, "ipv6") == 0) {
352                         return true;
353                 }
354
355                 return false;
356 #endif
357         }
358
359         return false;
360 }
361
362 int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
363                                        const char *fam,
364                                        const char *addr,
365                                        uint16_t port,
366                                        struct tsocket_address **_addr,
367                                        const char *location)
368 {
369         struct addrinfo hints;
370         struct addrinfo *result = NULL;
371         char port_str[6];
372         int ret;
373
374         ZERO_STRUCT(hints);
375         /*
376          * we use SOCKET_STREAM here to get just one result
377          * back from getaddrinfo().
378          */
379         hints.ai_socktype = SOCK_STREAM;
380         hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
381
382         if (strcasecmp(fam, "ip") == 0) {
383                 hints.ai_family = AF_UNSPEC;
384                 if (!addr) {
385 #ifdef HAVE_IPV6
386                         addr = "::";
387 #else
388                         addr = "0.0.0.0";
389 #endif
390                 }
391         } else if (strcasecmp(fam, "ipv4") == 0) {
392                 hints.ai_family = AF_INET;
393                 if (!addr) {
394                         addr = "0.0.0.0";
395                 }
396 #ifdef HAVE_IPV6
397         } else if (strcasecmp(fam, "ipv6") == 0) {
398                 hints.ai_family = AF_INET6;
399                 if (!addr) {
400                         addr = "::";
401                 }
402 #endif
403         } else {
404                 errno = EAFNOSUPPORT;
405                 return -1;
406         }
407
408         snprintf(port_str, sizeof(port_str), "%u", port);
409
410         ret = getaddrinfo(addr, port_str, &hints, &result);
411         if (ret != 0) {
412                 switch (ret) {
413                 case EAI_FAIL:
414                         errno = EINVAL;
415                         break;
416                 }
417                 ret = -1;
418                 goto done;
419         }
420
421         if (result->ai_socktype != SOCK_STREAM) {
422                 errno = EINVAL;
423                 ret = -1;
424                 goto done;
425         }
426
427         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
428                                                   result->ai_addr,
429                                                   result->ai_addrlen,
430                                                   _addr,
431                                                   location);
432
433 done:
434         if (result) {
435                 freeaddrinfo(result);
436         }
437         return ret;
438 }
439
440 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
441                                        TALLOC_CTX *mem_ctx)
442 {
443         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
444                                            struct tsocket_address_bsd);
445         char addr_str[INET6_ADDRSTRLEN+1];
446         const char *str;
447
448         if (!bsda) {
449                 errno = EINVAL;
450                 return NULL;
451         }
452
453         switch (bsda->u.sa.sa_family) {
454         case AF_INET:
455                 str = inet_ntop(bsda->u.in.sin_family,
456                                 &bsda->u.in.sin_addr,
457                                 addr_str, sizeof(addr_str));
458                 break;
459 #ifdef HAVE_IPV6
460         case AF_INET6:
461                 str = inet_ntop(bsda->u.in6.sin6_family,
462                                 &bsda->u.in6.sin6_addr,
463                                 addr_str, sizeof(addr_str));
464                 break;
465 #endif
466         default:
467                 errno = EINVAL;
468                 return NULL;
469         }
470
471         if (!str) {
472                 return NULL;
473         }
474
475         return talloc_strdup(mem_ctx, str);
476 }
477
478 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
479 {
480         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
481                                            struct tsocket_address_bsd);
482         uint16_t port = 0;
483
484         if (!bsda) {
485                 errno = EINVAL;
486                 return 0;
487         }
488
489         switch (bsda->u.sa.sa_family) {
490         case AF_INET:
491                 port = ntohs(bsda->u.in.sin_port);
492                 break;
493 #ifdef HAVE_IPV6
494         case AF_INET6:
495                 port = ntohs(bsda->u.in6.sin6_port);
496                 break;
497 #endif
498         default:
499                 errno = EINVAL;
500                 return 0;
501         }
502
503         return port;
504 }
505
506 int tsocket_address_inet_set_port(struct tsocket_address *addr,
507                                   uint16_t port)
508 {
509         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
510                                            struct tsocket_address_bsd);
511
512         if (!bsda) {
513                 errno = EINVAL;
514                 return -1;
515         }
516
517         switch (bsda->u.sa.sa_family) {
518         case AF_INET:
519                 bsda->u.in.sin_port = htons(port);
520                 break;
521 #ifdef HAVE_IPV6
522         case AF_INET6:
523                 bsda->u.in6.sin6_port = htons(port);
524                 break;
525 #endif
526         default:
527                 errno = EINVAL;
528                 return -1;
529         }
530
531         return 0;
532 }
533
534 bool tsocket_address_is_unix(const struct tsocket_address *addr)
535 {
536         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
537                                            struct tsocket_address_bsd);
538
539         if (!bsda) {
540                 return false;
541         }
542
543         switch (bsda->u.sa.sa_family) {
544         case AF_UNIX:
545                 return true;
546         }
547
548         return false;
549 }
550
551 int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
552                                     const char *path,
553                                     struct tsocket_address **_addr,
554                                     const char *location)
555 {
556         struct sockaddr_un un;
557         void *p = &un;
558         int ret;
559
560         if (!path) {
561                 path = "";
562         }
563
564         if (strlen(path) > sizeof(un.sun_path)-1) {
565                 errno = ENAMETOOLONG;
566                 return -1;
567         }
568
569         ZERO_STRUCT(un);
570         un.sun_family = AF_UNIX;
571         strncpy(un.sun_path, path, sizeof(un.sun_path)-1);
572
573         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
574                                                  (struct sockaddr *)p,
575                                                  sizeof(un),
576                                                  _addr,
577                                                  location);
578
579         return ret;
580 }
581
582 char *tsocket_address_unix_path(const struct tsocket_address *addr,
583                                 TALLOC_CTX *mem_ctx)
584 {
585         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
586                                            struct tsocket_address_bsd);
587         const char *str;
588
589         if (!bsda) {
590                 errno = EINVAL;
591                 return NULL;
592         }
593
594         switch (bsda->u.sa.sa_family) {
595         case AF_UNIX:
596                 str = bsda->u.un.sun_path;
597                 break;
598         default:
599                 errno = EINVAL;
600                 return NULL;
601         }
602
603         return talloc_strdup(mem_ctx, str);
604 }
605
606 static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
607                                         TALLOC_CTX *mem_ctx)
608 {
609         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
610                                            struct tsocket_address_bsd);
611         char *str;
612         char *addr_str;
613         const char *prefix = NULL;
614         uint16_t port;
615
616         switch (bsda->u.sa.sa_family) {
617         case AF_UNIX:
618                 return talloc_asprintf(mem_ctx, "unix:%s",
619                                        bsda->u.un.sun_path);
620         case AF_INET:
621                 prefix = "ipv4";
622                 break;
623 #ifdef HAVE_IPV6
624         case AF_INET6:
625                 prefix = "ipv6";
626                 break;
627 #endif
628         default:
629                 errno = EINVAL;
630                 return NULL;
631         }
632
633         addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
634         if (!addr_str) {
635                 return NULL;
636         }
637
638         port = tsocket_address_inet_port(addr);
639
640         str = talloc_asprintf(mem_ctx, "%s:%s:%u",
641                               prefix, addr_str, port);
642         talloc_free(addr_str);
643
644         return str;
645 }
646
647 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
648                                                          TALLOC_CTX *mem_ctx,
649                                                          const char *location)
650 {
651         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
652                                            struct tsocket_address_bsd);
653         struct tsocket_address *copy;
654         int ret;
655
656         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
657                                                  &bsda->u.sa,
658                                                  bsda->sa_socklen,
659                                                  &copy,
660                                                  location);
661         if (ret != 0) {
662                 return NULL;
663         }
664
665         return copy;
666 }
667
668 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
669         .name           = "bsd",
670         .string         = tsocket_address_bsd_string,
671         .copy           = tsocket_address_bsd_copy,
672 };
673
674 struct tdgram_bsd {
675         int fd;
676
677         void *event_ptr;
678         struct tevent_fd *fde;
679         bool optimize_recvfrom;
680         bool netlink;
681
682         void *readable_private;
683         void (*readable_handler)(void *private_data);
684         void *writeable_private;
685         void (*writeable_handler)(void *private_data);
686 };
687
688 bool tdgram_bsd_optimize_recvfrom(struct tdgram_context *dgram,
689                                   bool on)
690 {
691         struct tdgram_bsd *bsds =
692                 talloc_get_type(_tdgram_context_data(dgram),
693                 struct tdgram_bsd);
694         bool old;
695
696         if (bsds == NULL) {
697                 /* not a bsd socket */
698                 return false;
699         }
700
701         old = bsds->optimize_recvfrom;
702         bsds->optimize_recvfrom = on;
703
704         return old;
705 }
706
707 static void tdgram_bsd_fde_handler(struct tevent_context *ev,
708                                    struct tevent_fd *fde,
709                                    uint16_t flags,
710                                    void *private_data)
711 {
712         struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
713                                   struct tdgram_bsd);
714
715         if (flags & TEVENT_FD_WRITE) {
716                 bsds->writeable_handler(bsds->writeable_private);
717                 return;
718         }
719         if (flags & TEVENT_FD_READ) {
720                 if (!bsds->readable_handler) {
721                         TEVENT_FD_NOT_READABLE(bsds->fde);
722                         return;
723                 }
724                 bsds->readable_handler(bsds->readable_private);
725                 return;
726         }
727 }
728
729 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
730                                            struct tevent_context *ev,
731                                            void (*handler)(void *private_data),
732                                            void *private_data)
733 {
734         if (ev == NULL) {
735                 if (handler) {
736                         errno = EINVAL;
737                         return -1;
738                 }
739                 if (!bsds->readable_handler) {
740                         return 0;
741                 }
742                 bsds->readable_handler = NULL;
743                 bsds->readable_private = NULL;
744
745                 return 0;
746         }
747
748         /* read and write must use the same tevent_context */
749         if (bsds->event_ptr != ev) {
750                 if (bsds->readable_handler || bsds->writeable_handler) {
751                         errno = EINVAL;
752                         return -1;
753                 }
754                 bsds->event_ptr = NULL;
755                 TALLOC_FREE(bsds->fde);
756         }
757
758         if (tevent_fd_get_flags(bsds->fde) == 0) {
759                 TALLOC_FREE(bsds->fde);
760
761                 bsds->fde = tevent_add_fd(ev, bsds,
762                                           bsds->fd, TEVENT_FD_READ,
763                                           tdgram_bsd_fde_handler,
764                                           bsds);
765                 if (!bsds->fde) {
766                         errno = ENOMEM;
767                         return -1;
768                 }
769
770                 /* cache the event context we're running on */
771                 bsds->event_ptr = ev;
772         } else if (!bsds->readable_handler) {
773                 TEVENT_FD_READABLE(bsds->fde);
774         }
775
776         bsds->readable_handler = handler;
777         bsds->readable_private = private_data;
778
779         return 0;
780 }
781
782 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
783                                             struct tevent_context *ev,
784                                             void (*handler)(void *private_data),
785                                             void *private_data)
786 {
787         if (ev == NULL) {
788                 if (handler) {
789                         errno = EINVAL;
790                         return -1;
791                 }
792                 if (!bsds->writeable_handler) {
793                         return 0;
794                 }
795                 bsds->writeable_handler = NULL;
796                 bsds->writeable_private = NULL;
797                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
798
799                 return 0;
800         }
801
802         /* read and write must use the same tevent_context */
803         if (bsds->event_ptr != ev) {
804                 if (bsds->readable_handler || bsds->writeable_handler) {
805                         errno = EINVAL;
806                         return -1;
807                 }
808                 bsds->event_ptr = NULL;
809                 TALLOC_FREE(bsds->fde);
810         }
811
812         if (tevent_fd_get_flags(bsds->fde) == 0) {
813                 TALLOC_FREE(bsds->fde);
814
815                 bsds->fde = tevent_add_fd(ev, bsds,
816                                           bsds->fd, TEVENT_FD_WRITE,
817                                           tdgram_bsd_fde_handler,
818                                           bsds);
819                 if (!bsds->fde) {
820                         errno = ENOMEM;
821                         return -1;
822                 }
823
824                 /* cache the event context we're running on */
825                 bsds->event_ptr = ev;
826         } else if (!bsds->writeable_handler) {
827                 TEVENT_FD_WRITEABLE(bsds->fde);
828         }
829
830         bsds->writeable_handler = handler;
831         bsds->writeable_private = private_data;
832
833         return 0;
834 }
835
836 struct tdgram_bsd_recvfrom_state {
837         struct tdgram_context *dgram;
838         bool first_try;
839         uint8_t *buf;
840         size_t len;
841         struct tsocket_address *src;
842 };
843
844 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
845 {
846         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
847                                   struct tdgram_bsd);
848
849         tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
850
851         return 0;
852 }
853
854 static void tdgram_bsd_recvfrom_handler(void *private_data);
855
856 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
857                                         struct tevent_context *ev,
858                                         struct tdgram_context *dgram)
859 {
860         struct tevent_req *req;
861         struct tdgram_bsd_recvfrom_state *state;
862         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
863         int ret;
864
865         req = tevent_req_create(mem_ctx, &state,
866                                 struct tdgram_bsd_recvfrom_state);
867         if (!req) {
868                 return NULL;
869         }
870
871         state->dgram    = dgram;
872         state->first_try= true;
873         state->buf      = NULL;
874         state->len      = 0;
875         state->src      = NULL;
876
877         talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
878
879         if (bsds->fd == -1) {
880                 tevent_req_error(req, ENOTCONN);
881                 goto post;
882         }
883
884
885         /*
886          * this is a fast path, not waiting for the
887          * socket to become explicit readable gains
888          * about 10%-20% performance in benchmark tests.
889          */
890         if (bsds->optimize_recvfrom) {
891                 /*
892                  * We only do the optimization on
893                  * recvfrom if the caller asked for it.
894                  *
895                  * This is needed because in most cases
896                  * we prefer to flush send buffers before
897                  * receiving incoming requests.
898                  */
899                 tdgram_bsd_recvfrom_handler(req);
900                 if (!tevent_req_is_in_progress(req)) {
901                         goto post;
902                 }
903         }
904
905         ret = tdgram_bsd_set_readable_handler(bsds, ev,
906                                               tdgram_bsd_recvfrom_handler,
907                                               req);
908         if (ret == -1) {
909                 tevent_req_error(req, errno);
910                 goto post;
911         }
912
913         return req;
914
915  post:
916         tevent_req_post(req, ev);
917         return req;
918 }
919
920 static void tdgram_bsd_recvfrom_handler(void *private_data)
921 {
922         struct tevent_req *req = talloc_get_type_abort(private_data,
923                                  struct tevent_req);
924         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
925                                         struct tdgram_bsd_recvfrom_state);
926         struct tdgram_context *dgram = state->dgram;
927         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
928         struct tsocket_address_bsd *bsda;
929         ssize_t ret;
930         int err;
931         bool retry;
932
933         if (bsds->netlink) {
934                 ret = tsocket_bsd_netlink_pending(bsds->fd);
935         } else {
936                 ret = tsocket_bsd_pending(bsds->fd);
937         }
938
939         if (state->first_try && ret == 0) {
940                 state->first_try = false;
941                 /* retry later */
942                 return;
943         }
944         state->first_try = false;
945
946         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
947         if (retry) {
948                 /* retry later */
949                 return;
950         }
951         if (tevent_req_error(req, err)) {
952                 return;
953         }
954
955         /* note that 'ret' can be 0 here */
956         state->buf = talloc_array(state, uint8_t, ret);
957         if (tevent_req_nomem(state->buf, req)) {
958                 return;
959         }
960         state->len = ret;
961
962         state->src = tsocket_address_create(state,
963                                             &tsocket_address_bsd_ops,
964                                             &bsda,
965                                             struct tsocket_address_bsd,
966                                             __location__ "bsd_recvfrom");
967         if (tevent_req_nomem(state->src, req)) {
968                 return;
969         }
970
971         ZERO_STRUCTP(bsda);
972         bsda->sa_socklen = sizeof(bsda->u.ss);
973 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
974         bsda->u.sa.sa_len = bsda->sa_socklen;
975 #endif
976
977         ret = recvfrom(bsds->fd, state->buf, state->len, 0,
978                        &bsda->u.sa, &bsda->sa_socklen);
979         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
980         if (retry) {
981                 /* retry later */
982                 return;
983         }
984         if (tevent_req_error(req, err)) {
985                 return;
986         }
987
988         /*
989          * Some systems (FreeBSD, see bug #7115) return too much
990          * bytes in tsocket_bsd_pending()/ioctl(fd, FIONREAD, ...),
991          * the return value includes some IP/UDP header bytes,
992          * while recvfrom() just returns the payload.
993          */
994         state->buf = talloc_realloc(state, state->buf, uint8_t, ret);
995         if (tevent_req_nomem(state->buf, req)) {
996                 return;
997         }
998         state->len = ret;
999
1000         tevent_req_done(req);
1001 }
1002
1003 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
1004                                         int *perrno,
1005                                         TALLOC_CTX *mem_ctx,
1006                                         uint8_t **buf,
1007                                         struct tsocket_address **src)
1008 {
1009         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1010                                         struct tdgram_bsd_recvfrom_state);
1011         ssize_t ret;
1012
1013         ret = tsocket_simple_int_recv(req, perrno);
1014         if (ret == 0) {
1015                 *buf = talloc_move(mem_ctx, &state->buf);
1016                 ret = state->len;
1017                 if (src) {
1018                         *src = talloc_move(mem_ctx, &state->src);
1019                 }
1020         }
1021
1022         tevent_req_received(req);
1023         return ret;
1024 }
1025
1026 struct tdgram_bsd_sendto_state {
1027         struct tdgram_context *dgram;
1028
1029         const uint8_t *buf;
1030         size_t len;
1031         const struct tsocket_address *dst;
1032
1033         ssize_t ret;
1034 };
1035
1036 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
1037 {
1038         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1039                                   struct tdgram_bsd);
1040
1041         tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1042
1043         return 0;
1044 }
1045
1046 static void tdgram_bsd_sendto_handler(void *private_data);
1047
1048 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
1049                                                  struct tevent_context *ev,
1050                                                  struct tdgram_context *dgram,
1051                                                  const uint8_t *buf,
1052                                                  size_t len,
1053                                                  const struct tsocket_address *dst)
1054 {
1055         struct tevent_req *req;
1056         struct tdgram_bsd_sendto_state *state;
1057         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1058         int ret;
1059
1060         req = tevent_req_create(mem_ctx, &state,
1061                                 struct tdgram_bsd_sendto_state);
1062         if (!req) {
1063                 return NULL;
1064         }
1065
1066         state->dgram    = dgram;
1067         state->buf      = buf;
1068         state->len      = len;
1069         state->dst      = dst;
1070         state->ret      = -1;
1071
1072         talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
1073
1074         if (bsds->fd == -1) {
1075                 tevent_req_error(req, ENOTCONN);
1076                 goto post;
1077         }
1078
1079         /*
1080          * this is a fast path, not waiting for the
1081          * socket to become explicit writeable gains
1082          * about 10%-20% performance in benchmark tests.
1083          */
1084         tdgram_bsd_sendto_handler(req);
1085         if (!tevent_req_is_in_progress(req)) {
1086                 goto post;
1087         }
1088
1089         ret = tdgram_bsd_set_writeable_handler(bsds, ev,
1090                                                tdgram_bsd_sendto_handler,
1091                                                req);
1092         if (ret == -1) {
1093                 tevent_req_error(req, errno);
1094                 goto post;
1095         }
1096
1097         return req;
1098
1099  post:
1100         tevent_req_post(req, ev);
1101         return req;
1102 }
1103
1104 static void tdgram_bsd_sendto_handler(void *private_data)
1105 {
1106         struct tevent_req *req = talloc_get_type_abort(private_data,
1107                                  struct tevent_req);
1108         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1109                                         struct tdgram_bsd_sendto_state);
1110         struct tdgram_context *dgram = state->dgram;
1111         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1112         struct sockaddr *sa = NULL;
1113         socklen_t sa_socklen = 0;
1114         ssize_t ret;
1115         int err;
1116         bool retry;
1117         int flags = 0;
1118
1119         if (state->dst) {
1120                 struct tsocket_address_bsd *bsda =
1121                         talloc_get_type(state->dst->private_data,
1122                         struct tsocket_address_bsd);
1123
1124                 sa = &bsda->u.sa;
1125                 sa_socklen = bsda->sa_socklen;
1126         }
1127
1128 #ifdef MSG_NOSIGNAL
1129         flags |= MSG_NOSIGNAL;
1130 #endif
1131         ret = sendto(bsds->fd, state->buf, state->len, flags, sa, sa_socklen);
1132         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1133         if (retry) {
1134                 /* retry later */
1135                 return;
1136         }
1137
1138         if (err == EMSGSIZE) {
1139                 /* round up in 1K increments */
1140                 int bufsize = ((state->len + 1023) & (~1023));
1141
1142                 ret = setsockopt(bsds->fd, SOL_SOCKET, SO_SNDBUF, &bufsize,
1143                                  sizeof(bufsize));
1144                 if (ret == 0) {
1145                         /*
1146                          * We do the retry here, rather then via the
1147                          * handler, as we only want to retry once for
1148                          * this condition, so if there is a mismatch
1149                          * between what setsockopt() accepts and what can
1150                          * actually be sent, we do not end up in a
1151                          * loop.
1152                          */
1153
1154                         ret = sendto(bsds->fd, state->buf, state->len,
1155                                      0, sa, sa_socklen);
1156                         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1157                         if (retry) { /* retry later */
1158                                 return;
1159                         }
1160                 }
1161         }
1162
1163         if (tevent_req_error(req, err)) {
1164                 return;
1165         }
1166
1167         state->ret = ret;
1168
1169         tevent_req_done(req);
1170 }
1171
1172 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
1173 {
1174         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1175                                         struct tdgram_bsd_sendto_state);
1176         ssize_t ret;
1177
1178         ret = tsocket_simple_int_recv(req, perrno);
1179         if (ret == 0) {
1180                 ret = state->ret;
1181         }
1182
1183         tevent_req_received(req);
1184         return ret;
1185 }
1186
1187 struct tdgram_bsd_disconnect_state {
1188         uint8_t __dummy;
1189 };
1190
1191 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1192                                                      struct tevent_context *ev,
1193                                                      struct tdgram_context *dgram)
1194 {
1195         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1196         struct tevent_req *req;
1197         struct tdgram_bsd_disconnect_state *state;
1198         int ret;
1199         int err;
1200         bool dummy;
1201
1202         req = tevent_req_create(mem_ctx, &state,
1203                                 struct tdgram_bsd_disconnect_state);
1204         if (req == NULL) {
1205                 return NULL;
1206         }
1207
1208         if (bsds->fd == -1) {
1209                 tevent_req_error(req, ENOTCONN);
1210                 goto post;
1211         }
1212
1213         TALLOC_FREE(bsds->fde);
1214         ret = close(bsds->fd);
1215         bsds->fd = -1;
1216         err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1217         if (tevent_req_error(req, err)) {
1218                 goto post;
1219         }
1220
1221         tevent_req_done(req);
1222 post:
1223         tevent_req_post(req, ev);
1224         return req;
1225 }
1226
1227 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1228                                       int *perrno)
1229 {
1230         int ret;
1231
1232         ret = tsocket_simple_int_recv(req, perrno);
1233
1234         tevent_req_received(req);
1235         return ret;
1236 }
1237
1238 static const struct tdgram_context_ops tdgram_bsd_ops = {
1239         .name                   = "bsd",
1240
1241         .recvfrom_send          = tdgram_bsd_recvfrom_send,
1242         .recvfrom_recv          = tdgram_bsd_recvfrom_recv,
1243
1244         .sendto_send            = tdgram_bsd_sendto_send,
1245         .sendto_recv            = tdgram_bsd_sendto_recv,
1246
1247         .disconnect_send        = tdgram_bsd_disconnect_send,
1248         .disconnect_recv        = tdgram_bsd_disconnect_recv,
1249 };
1250
1251 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1252 {
1253         TALLOC_FREE(bsds->fde);
1254         if (bsds->fd != -1) {
1255                 close(bsds->fd);
1256                 bsds->fd = -1;
1257         }
1258         return 0;
1259 }
1260
1261 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1262                                    const struct tsocket_address *remote,
1263                                    bool broadcast,
1264                                    TALLOC_CTX *mem_ctx,
1265                                    struct tdgram_context **_dgram,
1266                                    const char *location)
1267 {
1268         struct tsocket_address_bsd *lbsda =
1269                 talloc_get_type_abort(local->private_data,
1270                 struct tsocket_address_bsd);
1271         struct tsocket_address_bsd *rbsda = NULL;
1272         struct tdgram_context *dgram;
1273         struct tdgram_bsd *bsds;
1274         int fd;
1275         int ret;
1276         bool do_bind = false;
1277         bool do_reuseaddr = false;
1278         bool do_ipv6only = false;
1279         bool is_inet = false;
1280         int sa_fam = lbsda->u.sa.sa_family;
1281
1282         if (remote) {
1283                 rbsda = talloc_get_type_abort(remote->private_data,
1284                         struct tsocket_address_bsd);
1285         }
1286
1287         switch (lbsda->u.sa.sa_family) {
1288         case AF_UNIX:
1289                 if (broadcast) {
1290                         errno = EINVAL;
1291                         return -1;
1292                 }
1293                 if (lbsda->u.un.sun_path[0] != 0) {
1294                         do_reuseaddr = true;
1295                         do_bind = true;
1296                 }
1297                 break;
1298         case AF_INET:
1299                 if (lbsda->u.in.sin_port != 0) {
1300                         do_reuseaddr = true;
1301                         do_bind = true;
1302                 }
1303                 if (lbsda->u.in.sin_addr.s_addr != INADDR_ANY) {
1304                         do_bind = true;
1305                 }
1306                 is_inet = true;
1307                 break;
1308 #ifdef HAVE_IPV6
1309         case AF_INET6:
1310                 if (lbsda->u.in6.sin6_port != 0) {
1311                         do_reuseaddr = true;
1312                         do_bind = true;
1313                 }
1314                 if (memcmp(&in6addr_any,
1315                            &lbsda->u.in6.sin6_addr,
1316                            sizeof(in6addr_any)) != 0) {
1317                         do_bind = true;
1318                 }
1319                 is_inet = true;
1320                 do_ipv6only = true;
1321                 break;
1322 #endif
1323         default:
1324                 errno = EINVAL;
1325                 return -1;
1326         }
1327
1328         if (!do_bind && is_inet && rbsda) {
1329                 sa_fam = rbsda->u.sa.sa_family;
1330                 switch (sa_fam) {
1331                 case AF_INET:
1332                         do_ipv6only = false;
1333                         break;
1334 #ifdef HAVE_IPV6
1335                 case AF_INET6:
1336                         do_ipv6only = true;
1337                         break;
1338 #endif
1339                 }
1340         }
1341
1342         fd = socket(sa_fam, SOCK_DGRAM, 0);
1343         if (fd < 0) {
1344                 return -1;
1345         }
1346
1347         fd = tsocket_bsd_common_prepare_fd(fd, true);
1348         if (fd < 0) {
1349                 return -1;
1350         }
1351
1352         dgram = tdgram_context_create(mem_ctx,
1353                                       &tdgram_bsd_ops,
1354                                       &bsds,
1355                                       struct tdgram_bsd,
1356                                       location);
1357         if (!dgram) {
1358                 int saved_errno = errno;
1359                 close(fd);
1360                 errno = saved_errno;
1361                 return -1;
1362         }
1363         ZERO_STRUCTP(bsds);
1364         bsds->fd = fd;
1365         talloc_set_destructor(bsds, tdgram_bsd_destructor);
1366
1367 #ifdef HAVE_IPV6
1368         if (do_ipv6only) {
1369                 int val = 1;
1370
1371                 ret = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
1372                                  (const void *)&val, sizeof(val));
1373                 if (ret == -1) {
1374                         int saved_errno = errno;
1375                         talloc_free(dgram);
1376                         errno = saved_errno;
1377                         return -1;
1378                 }
1379         }
1380 #endif
1381
1382         if (broadcast) {
1383                 int val = 1;
1384
1385                 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1386                                  (const void *)&val, sizeof(val));
1387                 if (ret == -1) {
1388                         int saved_errno = errno;
1389                         talloc_free(dgram);
1390                         errno = saved_errno;
1391                         return -1;
1392                 }
1393         }
1394
1395         if (do_reuseaddr) {
1396                 int val = 1;
1397
1398                 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1399                                  (const void *)&val, sizeof(val));
1400                 if (ret == -1) {
1401                         int saved_errno = errno;
1402                         talloc_free(dgram);
1403                         errno = saved_errno;
1404                         return -1;
1405                 }
1406         }
1407
1408         if (do_bind) {
1409                 ret = bind(fd, &lbsda->u.sa, lbsda->sa_socklen);
1410                 if (ret == -1) {
1411                         int saved_errno = errno;
1412                         talloc_free(dgram);
1413                         errno = saved_errno;
1414                         return -1;
1415                 }
1416         }
1417
1418         if (rbsda) {
1419                 if (rbsda->u.sa.sa_family != sa_fam) {
1420                         talloc_free(dgram);
1421                         errno = EINVAL;
1422                         return -1;
1423                 }
1424
1425                 ret = connect(fd, &rbsda->u.sa, rbsda->sa_socklen);
1426                 if (ret == -1) {
1427                         int saved_errno = errno;
1428                         talloc_free(dgram);
1429                         errno = saved_errno;
1430                         return -1;
1431                 }
1432         }
1433
1434         *_dgram = dgram;
1435         return 0;
1436 }
1437
1438 int _tdgram_bsd_existing_socket(TALLOC_CTX *mem_ctx,
1439                                 int fd,
1440                                 struct tdgram_context **_dgram,
1441                                 const char *location)
1442 {
1443         struct tdgram_context *dgram;
1444         struct tdgram_bsd *bsds;
1445 #ifdef HAVE_LINUX_RTNETLINK_H
1446         int result;
1447         struct sockaddr sa;
1448         socklen_t sa_len = sizeof(struct sockaddr);
1449 #endif
1450
1451         dgram = tdgram_context_create(mem_ctx,
1452                                       &tdgram_bsd_ops,
1453                                       &bsds,
1454                                       struct tdgram_bsd,
1455                                       location);
1456         if (!dgram) {
1457                 return -1;
1458         }
1459         ZERO_STRUCTP(bsds);
1460         bsds->fd = fd;
1461         talloc_set_destructor(bsds, tdgram_bsd_destructor);
1462
1463         *_dgram = dgram;
1464
1465 #ifdef HAVE_LINUX_RTNETLINK_H
1466         /*
1467          * Try to determine the protocol family and remember if it's
1468          * AF_NETLINK. We don't care if this fails.
1469          */
1470         result = getsockname(fd, &sa, &sa_len);
1471         if (result == 0 && sa.sa_family == AF_NETLINK) {
1472                 bsds->netlink = true;
1473         }
1474 #endif
1475
1476         return 0;
1477 }
1478
1479 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1480                             const struct tsocket_address *remote,
1481                             TALLOC_CTX *mem_ctx,
1482                             struct tdgram_context **dgram,
1483                             const char *location)
1484 {
1485         struct tsocket_address_bsd *lbsda =
1486                 talloc_get_type_abort(local->private_data,
1487                 struct tsocket_address_bsd);
1488         int ret;
1489
1490         switch (lbsda->u.sa.sa_family) {
1491         case AF_INET:
1492                 break;
1493 #ifdef HAVE_IPV6
1494         case AF_INET6:
1495                 break;
1496 #endif
1497         default:
1498                 errno = EINVAL;
1499                 return -1;
1500         }
1501
1502         ret = tdgram_bsd_dgram_socket(local, remote, false,
1503                                       mem_ctx, dgram, location);
1504
1505         return ret;
1506 }
1507
1508 int _tdgram_inet_udp_broadcast_socket(const struct tsocket_address *local,
1509                                       TALLOC_CTX *mem_ctx,
1510                                       struct tdgram_context **dgram,
1511                                       const char *location)
1512 {
1513         struct tsocket_address_bsd *lbsda =
1514                 talloc_get_type_abort(local->private_data,
1515                 struct tsocket_address_bsd);
1516         int ret;
1517
1518         switch (lbsda->u.sa.sa_family) {
1519         case AF_INET:
1520                 break;
1521 #ifdef HAVE_IPV6
1522         case AF_INET6:
1523                 /* only ipv4 */
1524                 errno = EINVAL;
1525                 return -1;
1526 #endif
1527         default:
1528                 errno = EINVAL;
1529                 return -1;
1530         }
1531
1532         ret = tdgram_bsd_dgram_socket(local, NULL, true,
1533                                       mem_ctx, dgram, location);
1534
1535         return ret;
1536 }
1537
1538 int _tdgram_unix_socket(const struct tsocket_address *local,
1539                         const struct tsocket_address *remote,
1540                         TALLOC_CTX *mem_ctx,
1541                         struct tdgram_context **dgram,
1542                         const char *location)
1543 {
1544         struct tsocket_address_bsd *lbsda =
1545                 talloc_get_type_abort(local->private_data,
1546                 struct tsocket_address_bsd);
1547         int ret;
1548
1549         switch (lbsda->u.sa.sa_family) {
1550         case AF_UNIX:
1551                 break;
1552         default:
1553                 errno = EINVAL;
1554                 return -1;
1555         }
1556
1557         ret = tdgram_bsd_dgram_socket(local, remote, false,
1558                                       mem_ctx, dgram, location);
1559
1560         return ret;
1561 }
1562
1563 struct tstream_bsd {
1564         int fd;
1565
1566         void *event_ptr;
1567         struct tevent_fd *fde;
1568         bool optimize_readv;
1569
1570         void *readable_private;
1571         void (*readable_handler)(void *private_data);
1572         void *writeable_private;
1573         void (*writeable_handler)(void *private_data);
1574 };
1575
1576 bool tstream_bsd_optimize_readv(struct tstream_context *stream,
1577                                 bool on)
1578 {
1579         struct tstream_bsd *bsds =
1580                 talloc_get_type(_tstream_context_data(stream),
1581                 struct tstream_bsd);
1582         bool old;
1583
1584         if (bsds == NULL) {
1585                 /* not a bsd socket */
1586                 return false;
1587         }
1588
1589         old = bsds->optimize_readv;
1590         bsds->optimize_readv = on;
1591
1592         return old;
1593 }
1594
1595 static void tstream_bsd_fde_handler(struct tevent_context *ev,
1596                                     struct tevent_fd *fde,
1597                                     uint16_t flags,
1598                                     void *private_data)
1599 {
1600         struct tstream_bsd *bsds = talloc_get_type_abort(private_data,
1601                                    struct tstream_bsd);
1602
1603         if (flags & TEVENT_FD_WRITE) {
1604                 bsds->writeable_handler(bsds->writeable_private);
1605                 return;
1606         }
1607         if (flags & TEVENT_FD_READ) {
1608                 if (!bsds->readable_handler) {
1609                         if (bsds->writeable_handler) {
1610                                 bsds->writeable_handler(bsds->writeable_private);
1611                                 return;
1612                         }
1613                         TEVENT_FD_NOT_READABLE(bsds->fde);
1614                         return;
1615                 }
1616                 bsds->readable_handler(bsds->readable_private);
1617                 return;
1618         }
1619 }
1620
1621 static int tstream_bsd_set_readable_handler(struct tstream_bsd *bsds,
1622                                             struct tevent_context *ev,
1623                                             void (*handler)(void *private_data),
1624                                             void *private_data)
1625 {
1626         if (ev == NULL) {
1627                 if (handler) {
1628                         errno = EINVAL;
1629                         return -1;
1630                 }
1631                 if (!bsds->readable_handler) {
1632                         return 0;
1633                 }
1634                 bsds->readable_handler = NULL;
1635                 bsds->readable_private = NULL;
1636
1637                 return 0;
1638         }
1639
1640         /* read and write must use the same tevent_context */
1641         if (bsds->event_ptr != ev) {
1642                 if (bsds->readable_handler || bsds->writeable_handler) {
1643                         errno = EINVAL;
1644                         return -1;
1645                 }
1646                 bsds->event_ptr = NULL;
1647                 TALLOC_FREE(bsds->fde);
1648         }
1649
1650         if (tevent_fd_get_flags(bsds->fde) == 0) {
1651                 TALLOC_FREE(bsds->fde);
1652
1653                 bsds->fde = tevent_add_fd(ev, bsds,
1654                                           bsds->fd, TEVENT_FD_READ,
1655                                           tstream_bsd_fde_handler,
1656                                           bsds);
1657                 if (!bsds->fde) {
1658                         errno = ENOMEM;
1659                         return -1;
1660                 }
1661
1662                 /* cache the event context we're running on */
1663                 bsds->event_ptr = ev;
1664         } else if (!bsds->readable_handler) {
1665                 TEVENT_FD_READABLE(bsds->fde);
1666         }
1667
1668         bsds->readable_handler = handler;
1669         bsds->readable_private = private_data;
1670
1671         return 0;
1672 }
1673
1674 static int tstream_bsd_set_writeable_handler(struct tstream_bsd *bsds,
1675                                              struct tevent_context *ev,
1676                                              void (*handler)(void *private_data),
1677                                              void *private_data)
1678 {
1679         if (ev == NULL) {
1680                 if (handler) {
1681                         errno = EINVAL;
1682                         return -1;
1683                 }
1684                 if (!bsds->writeable_handler) {
1685                         return 0;
1686                 }
1687                 bsds->writeable_handler = NULL;
1688                 bsds->writeable_private = NULL;
1689                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1690
1691                 return 0;
1692         }
1693
1694         /* read and write must use the same tevent_context */
1695         if (bsds->event_ptr != ev) {
1696                 if (bsds->readable_handler || bsds->writeable_handler) {
1697                         errno = EINVAL;
1698                         return -1;
1699                 }
1700                 bsds->event_ptr = NULL;
1701                 TALLOC_FREE(bsds->fde);
1702         }
1703
1704         if (tevent_fd_get_flags(bsds->fde) == 0) {
1705                 TALLOC_FREE(bsds->fde);
1706
1707                 bsds->fde = tevent_add_fd(ev, bsds,
1708                                           bsds->fd,
1709                                           TEVENT_FD_READ | TEVENT_FD_WRITE,
1710                                           tstream_bsd_fde_handler,
1711                                           bsds);
1712                 if (!bsds->fde) {
1713                         errno = ENOMEM;
1714                         return -1;
1715                 }
1716
1717                 /* cache the event context we're running on */
1718                 bsds->event_ptr = ev;
1719         } else if (!bsds->writeable_handler) {
1720                 uint16_t flags = tevent_fd_get_flags(bsds->fde);
1721                 flags |= TEVENT_FD_READ | TEVENT_FD_WRITE;
1722                 tevent_fd_set_flags(bsds->fde, flags);
1723         }
1724
1725         bsds->writeable_handler = handler;
1726         bsds->writeable_private = private_data;
1727
1728         return 0;
1729 }
1730
1731 static ssize_t tstream_bsd_pending_bytes(struct tstream_context *stream)
1732 {
1733         struct tstream_bsd *bsds = tstream_context_data(stream,
1734                                    struct tstream_bsd);
1735         ssize_t ret;
1736
1737         if (bsds->fd == -1) {
1738                 errno = ENOTCONN;
1739                 return -1;
1740         }
1741
1742         ret = tsocket_bsd_pending(bsds->fd);
1743
1744         return ret;
1745 }
1746
1747 struct tstream_bsd_readv_state {
1748         struct tstream_context *stream;
1749
1750         struct iovec *vector;
1751         size_t count;
1752
1753         int ret;
1754 };
1755
1756 static int tstream_bsd_readv_destructor(struct tstream_bsd_readv_state *state)
1757 {
1758         struct tstream_bsd *bsds = tstream_context_data(state->stream,
1759                                    struct tstream_bsd);
1760
1761         tstream_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1762
1763         return 0;
1764 }
1765
1766 static void tstream_bsd_readv_handler(void *private_data);
1767
1768 static struct tevent_req *tstream_bsd_readv_send(TALLOC_CTX *mem_ctx,
1769                                         struct tevent_context *ev,
1770                                         struct tstream_context *stream,
1771                                         struct iovec *vector,
1772                                         size_t count)
1773 {
1774         struct tevent_req *req;
1775         struct tstream_bsd_readv_state *state;
1776         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1777         int ret;
1778
1779         req = tevent_req_create(mem_ctx, &state,
1780                                 struct tstream_bsd_readv_state);
1781         if (!req) {
1782                 return NULL;
1783         }
1784
1785         state->stream   = stream;
1786         /* we make a copy of the vector so that we can modify it */
1787         state->vector   = talloc_array(state, struct iovec, count);
1788         if (tevent_req_nomem(state->vector, req)) {
1789                 goto post;
1790         }
1791         memcpy(state->vector, vector, sizeof(struct iovec)*count);
1792         state->count    = count;
1793         state->ret      = 0;
1794
1795         talloc_set_destructor(state, tstream_bsd_readv_destructor);
1796
1797         if (bsds->fd == -1) {
1798                 tevent_req_error(req, ENOTCONN);
1799                 goto post;
1800         }
1801
1802         /*
1803          * this is a fast path, not waiting for the
1804          * socket to become explicit readable gains
1805          * about 10%-20% performance in benchmark tests.
1806          */
1807         if (bsds->optimize_readv) {
1808                 /*
1809                  * We only do the optimization on
1810                  * readv if the caller asked for it.
1811                  *
1812                  * This is needed because in most cases
1813                  * we prefer to flush send buffers before
1814                  * receiving incoming requests.
1815                  */
1816                 tstream_bsd_readv_handler(req);
1817                 if (!tevent_req_is_in_progress(req)) {
1818                         goto post;
1819                 }
1820         }
1821
1822         ret = tstream_bsd_set_readable_handler(bsds, ev,
1823                                               tstream_bsd_readv_handler,
1824                                               req);
1825         if (ret == -1) {
1826                 tevent_req_error(req, errno);
1827                 goto post;
1828         }
1829
1830         return req;
1831
1832  post:
1833         tevent_req_post(req, ev);
1834         return req;
1835 }
1836
1837 static void tstream_bsd_readv_handler(void *private_data)
1838 {
1839         struct tevent_req *req = talloc_get_type_abort(private_data,
1840                                  struct tevent_req);
1841         struct tstream_bsd_readv_state *state = tevent_req_data(req,
1842                                         struct tstream_bsd_readv_state);
1843         struct tstream_context *stream = state->stream;
1844         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1845         int ret;
1846         int err;
1847         int _count;
1848         bool ok, retry;
1849
1850         ret = readv(bsds->fd, state->vector, state->count);
1851         if (ret == 0) {
1852                 /* propagate end of file */
1853                 tevent_req_error(req, EPIPE);
1854                 return;
1855         }
1856         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1857         if (retry) {
1858                 /* retry later */
1859                 return;
1860         }
1861         if (tevent_req_error(req, err)) {
1862                 return;
1863         }
1864
1865         state->ret += ret;
1866
1867         _count = state->count; /* tstream has size_t count, readv has int */
1868         ok = iov_advance(&state->vector, &_count, ret);
1869         state->count = _count;
1870
1871         if (!ok) {
1872                 tevent_req_error(req, EINVAL);
1873                 return;
1874         }
1875
1876         if (state->count > 0) {
1877                 /* we have more to read */
1878                 return;
1879         }
1880
1881         tevent_req_done(req);
1882 }
1883
1884 static int tstream_bsd_readv_recv(struct tevent_req *req,
1885                                   int *perrno)
1886 {
1887         struct tstream_bsd_readv_state *state = tevent_req_data(req,
1888                                         struct tstream_bsd_readv_state);
1889         int ret;
1890
1891         ret = tsocket_simple_int_recv(req, perrno);
1892         if (ret == 0) {
1893                 ret = state->ret;
1894         }
1895
1896         tevent_req_received(req);
1897         return ret;
1898 }
1899
1900 struct tstream_bsd_writev_state {
1901         struct tstream_context *stream;
1902
1903         struct iovec *vector;
1904         size_t count;
1905
1906         int ret;
1907 };
1908
1909 static int tstream_bsd_writev_destructor(struct tstream_bsd_writev_state *state)
1910 {
1911         struct tstream_bsd *bsds = tstream_context_data(state->stream,
1912                                   struct tstream_bsd);
1913
1914         tstream_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1915
1916         return 0;
1917 }
1918
1919 static void tstream_bsd_writev_handler(void *private_data);
1920
1921 static struct tevent_req *tstream_bsd_writev_send(TALLOC_CTX *mem_ctx,
1922                                                  struct tevent_context *ev,
1923                                                  struct tstream_context *stream,
1924                                                  const struct iovec *vector,
1925                                                  size_t count)
1926 {
1927         struct tevent_req *req;
1928         struct tstream_bsd_writev_state *state;
1929         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1930         int ret;
1931
1932         req = tevent_req_create(mem_ctx, &state,
1933                                 struct tstream_bsd_writev_state);
1934         if (!req) {
1935                 return NULL;
1936         }
1937
1938         state->stream   = stream;
1939         /* we make a copy of the vector so that we can modify it */
1940         state->vector   = talloc_array(state, struct iovec, count);
1941         if (tevent_req_nomem(state->vector, req)) {
1942                 goto post;
1943         }
1944         memcpy(state->vector, vector, sizeof(struct iovec)*count);
1945         state->count    = count;
1946         state->ret      = 0;
1947
1948         talloc_set_destructor(state, tstream_bsd_writev_destructor);
1949
1950         if (bsds->fd == -1) {
1951                 tevent_req_error(req, ENOTCONN);
1952                 goto post;
1953         }
1954
1955         /*
1956          * this is a fast path, not waiting for the
1957          * socket to become explicit writeable gains
1958          * about 10%-20% performance in benchmark tests.
1959          */
1960         tstream_bsd_writev_handler(req);
1961         if (!tevent_req_is_in_progress(req)) {
1962                 goto post;
1963         }
1964
1965         ret = tstream_bsd_set_writeable_handler(bsds, ev,
1966                                                tstream_bsd_writev_handler,
1967                                                req);
1968         if (ret == -1) {
1969                 tevent_req_error(req, errno);
1970                 goto post;
1971         }
1972
1973         return req;
1974
1975  post:
1976         tevent_req_post(req, ev);
1977         return req;
1978 }
1979
1980 static void tstream_bsd_writev_handler(void *private_data)
1981 {
1982         struct tevent_req *req = talloc_get_type_abort(private_data,
1983                                  struct tevent_req);
1984         struct tstream_bsd_writev_state *state = tevent_req_data(req,
1985                                         struct tstream_bsd_writev_state);
1986         struct tstream_context *stream = state->stream;
1987         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1988         ssize_t ret;
1989         int err;
1990         int _count;
1991         bool ok, retry;
1992         struct msghdr msg;
1993         int flags = 0;
1994
1995         msg.msg_name = NULL;           /* optional address */
1996         msg.msg_namelen = 0;           /* size of address */
1997         msg.msg_iov = state->vector;   /* scatter/gather array */
1998         msg.msg_iovlen = state->count; /* # elements in msg_iov */
1999         msg.msg_control = NULL;        /* ancillary data, see below */
2000         msg.msg_controllen = 0;        /* ancillary data buffer len */
2001         msg.msg_flags = 0;             /* flags on received message */
2002
2003 #ifdef MSG_NOSIGNAL
2004         flags |= MSG_NOSIGNAL;
2005 #endif
2006         ret = sendmsg(bsds->fd, &msg, flags);
2007         if (ret == 0) {
2008                 /* propagate end of file */
2009                 tevent_req_error(req, EPIPE);
2010                 return;
2011         }
2012         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2013         if (retry) {
2014                 /* retry later */
2015                 return;
2016         }
2017         if (tevent_req_error(req, err)) {
2018                 return;
2019         }
2020
2021         state->ret += ret;
2022
2023         _count = state->count; /* tstream has size_t count, writev has int */
2024         ok = iov_advance(&state->vector, &_count, ret);
2025         state->count = _count;
2026
2027         if (!ok) {
2028                 tevent_req_error(req, EINVAL);
2029                 return;
2030         }
2031
2032         if (state->count > 0) {
2033                 /* we have more to read */
2034                 return;
2035         }
2036
2037         tevent_req_done(req);
2038 }
2039
2040 static int tstream_bsd_writev_recv(struct tevent_req *req, int *perrno)
2041 {
2042         struct tstream_bsd_writev_state *state = tevent_req_data(req,
2043                                         struct tstream_bsd_writev_state);
2044         int ret;
2045
2046         ret = tsocket_simple_int_recv(req, perrno);
2047         if (ret == 0) {
2048                 ret = state->ret;
2049         }
2050
2051         tevent_req_received(req);
2052         return ret;
2053 }
2054
2055 struct tstream_bsd_disconnect_state {
2056         void *__dummy;
2057 };
2058
2059 static struct tevent_req *tstream_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
2060                                                      struct tevent_context *ev,
2061                                                      struct tstream_context *stream)
2062 {
2063         struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2064         struct tevent_req *req;
2065         struct tstream_bsd_disconnect_state *state;
2066         int ret;
2067         int err;
2068         bool dummy;
2069
2070         req = tevent_req_create(mem_ctx, &state,
2071                                 struct tstream_bsd_disconnect_state);
2072         if (req == NULL) {
2073                 return NULL;
2074         }
2075
2076         if (bsds->fd == -1) {
2077                 tevent_req_error(req, ENOTCONN);
2078                 goto post;
2079         }
2080
2081         TALLOC_FREE(bsds->fde);
2082         ret = close(bsds->fd);
2083         bsds->fd = -1;
2084         err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
2085         if (tevent_req_error(req, err)) {
2086                 goto post;
2087         }
2088
2089         tevent_req_done(req);
2090 post:
2091         tevent_req_post(req, ev);
2092         return req;
2093 }
2094
2095 static int tstream_bsd_disconnect_recv(struct tevent_req *req,
2096                                       int *perrno)
2097 {
2098         int ret;
2099
2100         ret = tsocket_simple_int_recv(req, perrno);
2101
2102         tevent_req_received(req);
2103         return ret;
2104 }
2105
2106 static const struct tstream_context_ops tstream_bsd_ops = {
2107         .name                   = "bsd",
2108
2109         .pending_bytes          = tstream_bsd_pending_bytes,
2110
2111         .readv_send             = tstream_bsd_readv_send,
2112         .readv_recv             = tstream_bsd_readv_recv,
2113
2114         .writev_send            = tstream_bsd_writev_send,
2115         .writev_recv            = tstream_bsd_writev_recv,
2116
2117         .disconnect_send        = tstream_bsd_disconnect_send,
2118         .disconnect_recv        = tstream_bsd_disconnect_recv,
2119 };
2120
2121 static int tstream_bsd_destructor(struct tstream_bsd *bsds)
2122 {
2123         TALLOC_FREE(bsds->fde);
2124         if (bsds->fd != -1) {
2125                 close(bsds->fd);
2126                 bsds->fd = -1;
2127         }
2128         return 0;
2129 }
2130
2131 int _tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
2132                                  int fd,
2133                                  struct tstream_context **_stream,
2134                                  const char *location)
2135 {
2136         struct tstream_context *stream;
2137         struct tstream_bsd *bsds;
2138
2139         stream = tstream_context_create(mem_ctx,
2140                                         &tstream_bsd_ops,
2141                                         &bsds,
2142                                         struct tstream_bsd,
2143                                         location);
2144         if (!stream) {
2145                 return -1;
2146         }
2147         ZERO_STRUCTP(bsds);
2148         bsds->fd = fd;
2149         talloc_set_destructor(bsds, tstream_bsd_destructor);
2150
2151         *_stream = stream;
2152         return 0;
2153 }
2154
2155 struct tstream_bsd_connect_state {
2156         int fd;
2157         struct tevent_fd *fde;
2158         struct tstream_conext *stream;
2159         struct tsocket_address *local;
2160 };
2161
2162 static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state *state)
2163 {
2164         TALLOC_FREE(state->fde);
2165         if (state->fd != -1) {
2166                 close(state->fd);
2167                 state->fd = -1;
2168         }
2169
2170         return 0;
2171 }
2172
2173 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
2174                                             struct tevent_fd *fde,
2175                                             uint16_t flags,
2176                                             void *private_data);
2177
2178 static struct tevent_req *tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
2179                                         struct tevent_context *ev,
2180                                         int sys_errno,
2181                                         const struct tsocket_address *local,
2182                                         const struct tsocket_address *remote)
2183 {
2184         struct tevent_req *req;
2185         struct tstream_bsd_connect_state *state;
2186         struct tsocket_address_bsd *lbsda =
2187                 talloc_get_type_abort(local->private_data,
2188                 struct tsocket_address_bsd);
2189         struct tsocket_address_bsd *lrbsda = NULL;
2190         struct tsocket_address_bsd *rbsda =
2191                 talloc_get_type_abort(remote->private_data,
2192                 struct tsocket_address_bsd);
2193         int ret;
2194         bool do_bind = false;
2195         bool do_reuseaddr = false;
2196         bool do_ipv6only = false;
2197         bool is_inet = false;
2198         int sa_fam = lbsda->u.sa.sa_family;
2199
2200         req = tevent_req_create(mem_ctx, &state,
2201                                 struct tstream_bsd_connect_state);
2202         if (!req) {
2203                 return NULL;
2204         }
2205         state->fd = -1;
2206         state->fde = NULL;
2207
2208         talloc_set_destructor(state, tstream_bsd_connect_destructor);
2209
2210         /* give the wrappers a chance to report an error */
2211         if (sys_errno != 0) {
2212                 tevent_req_error(req, sys_errno);
2213                 goto post;
2214         }
2215
2216         switch (lbsda->u.sa.sa_family) {
2217         case AF_UNIX:
2218                 if (lbsda->u.un.sun_path[0] != 0) {
2219                         do_reuseaddr = true;
2220                         do_bind = true;
2221                 }
2222                 break;
2223         case AF_INET:
2224                 if (lbsda->u.in.sin_port != 0) {
2225                         do_reuseaddr = true;
2226                         do_bind = true;
2227                 }
2228                 if (lbsda->u.in.sin_addr.s_addr != INADDR_ANY) {
2229                         do_bind = true;
2230                 }
2231                 is_inet = true;
2232                 break;
2233 #ifdef HAVE_IPV6
2234         case AF_INET6:
2235                 if (lbsda->u.in6.sin6_port != 0) {
2236                         do_reuseaddr = true;
2237                         do_bind = true;
2238                 }
2239                 if (memcmp(&in6addr_any,
2240                            &lbsda->u.in6.sin6_addr,
2241                            sizeof(in6addr_any)) != 0) {
2242                         do_bind = true;
2243                 }
2244                 is_inet = true;
2245                 do_ipv6only = true;
2246                 break;
2247 #endif
2248         default:
2249                 tevent_req_error(req, EINVAL);
2250                 goto post;
2251         }
2252
2253         if (!do_bind && is_inet) {
2254                 sa_fam = rbsda->u.sa.sa_family;
2255                 switch (sa_fam) {
2256                 case AF_INET:
2257                         do_ipv6only = false;
2258                         break;
2259 #ifdef HAVE_IPV6
2260                 case AF_INET6:
2261                         do_ipv6only = true;
2262                         break;
2263 #endif
2264                 }
2265         }
2266
2267         if (is_inet) {
2268                 state->local = tsocket_address_create(state,
2269                                                       &tsocket_address_bsd_ops,
2270                                                       &lrbsda,
2271                                                       struct tsocket_address_bsd,
2272                                                       __location__ "bsd_connect");
2273                 if (tevent_req_nomem(state->local, req)) {
2274                         goto post;
2275                 }
2276
2277                 ZERO_STRUCTP(lrbsda);
2278                 lrbsda->sa_socklen = sizeof(lrbsda->u.ss);
2279 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2280                 lrbsda->u.sa.sa_len = lrbsda->sa_socklen;
2281 #endif
2282         }
2283
2284         state->fd = socket(sa_fam, SOCK_STREAM, 0);
2285         if (state->fd == -1) {
2286                 tevent_req_error(req, errno);
2287                 goto post;
2288         }
2289
2290         state->fd = tsocket_bsd_common_prepare_fd(state->fd, true);
2291         if (state->fd == -1) {
2292                 tevent_req_error(req, errno);
2293                 goto post;
2294         }
2295
2296 #ifdef HAVE_IPV6
2297         if (do_ipv6only) {
2298                 int val = 1;
2299
2300                 ret = setsockopt(state->fd, IPPROTO_IPV6, IPV6_V6ONLY,
2301                                  (const void *)&val, sizeof(val));
2302                 if (ret == -1) {
2303                         tevent_req_error(req, errno);
2304                         goto post;
2305                 }
2306         }
2307 #endif
2308
2309         if (do_reuseaddr) {
2310                 int val = 1;
2311
2312                 ret = setsockopt(state->fd, SOL_SOCKET, SO_REUSEADDR,
2313                                  (const void *)&val, sizeof(val));
2314                 if (ret == -1) {
2315                         tevent_req_error(req, errno);
2316                         goto post;
2317                 }
2318         }
2319
2320         if (do_bind) {
2321                 ret = bind(state->fd, &lbsda->u.sa, lbsda->sa_socklen);
2322                 if (ret == -1) {
2323                         tevent_req_error(req, errno);
2324                         goto post;
2325                 }
2326         }
2327
2328         if (rbsda->u.sa.sa_family != sa_fam) {
2329                 tevent_req_error(req, EINVAL);
2330                 goto post;
2331         }
2332
2333         ret = connect(state->fd, &rbsda->u.sa, rbsda->sa_socklen);
2334         if (ret == -1) {
2335                 if (errno == EINPROGRESS) {
2336                         goto async;
2337                 }
2338                 tevent_req_error(req, errno);
2339                 goto post;
2340         }
2341
2342         if (!state->local) {
2343                 tevent_req_done(req);
2344                 goto post;
2345         }
2346
2347         if (lrbsda != NULL) {
2348                 ret = getsockname(state->fd,
2349                                   &lrbsda->u.sa,
2350                                   &lrbsda->sa_socklen);
2351                 if (ret == -1) {
2352                         tevent_req_error(req, errno);
2353                         goto post;
2354                 }
2355         }
2356
2357         tevent_req_done(req);
2358         goto post;
2359
2360  async:
2361         state->fde = tevent_add_fd(ev, state,
2362                                    state->fd,
2363                                    TEVENT_FD_READ | TEVENT_FD_WRITE,
2364                                    tstream_bsd_connect_fde_handler,
2365                                    req);
2366         if (tevent_req_nomem(state->fde, req)) {
2367                 goto post;
2368         }
2369
2370         return req;
2371
2372  post:
2373         tevent_req_post(req, ev);
2374         return req;
2375 }
2376
2377 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
2378                                             struct tevent_fd *fde,
2379                                             uint16_t flags,
2380                                             void *private_data)
2381 {
2382         struct tevent_req *req = talloc_get_type_abort(private_data,
2383                                  struct tevent_req);
2384         struct tstream_bsd_connect_state *state = tevent_req_data(req,
2385                                         struct tstream_bsd_connect_state);
2386         struct tsocket_address_bsd *lrbsda = NULL;
2387         int ret;
2388         int error=0;
2389         socklen_t len = sizeof(error);
2390         int err;
2391         bool retry;
2392
2393         ret = getsockopt(state->fd, SOL_SOCKET, SO_ERROR, &error, &len);
2394         if (ret == 0) {
2395                 if (error != 0) {
2396                         errno = error;
2397                         ret = -1;
2398                 }
2399         }
2400         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2401         if (retry) {
2402                 /* retry later */
2403                 return;
2404         }
2405         if (tevent_req_error(req, err)) {
2406                 return;
2407         }
2408
2409         if (!state->local) {
2410                 tevent_req_done(req);
2411                 return;
2412         }
2413
2414         lrbsda = talloc_get_type_abort(state->local->private_data,
2415                                        struct tsocket_address_bsd);
2416
2417         ret = getsockname(state->fd, &lrbsda->u.sa, &lrbsda->sa_socklen);
2418         if (ret == -1) {
2419                 tevent_req_error(req, errno);
2420                 return;
2421         }
2422
2423         tevent_req_done(req);
2424 }
2425
2426 static int tstream_bsd_connect_recv(struct tevent_req *req,
2427                                     int *perrno,
2428                                     TALLOC_CTX *mem_ctx,
2429                                     struct tstream_context **stream,
2430                                     struct tsocket_address **local,
2431                                     const char *location)
2432 {
2433         struct tstream_bsd_connect_state *state = tevent_req_data(req,
2434                                         struct tstream_bsd_connect_state);
2435         int ret;
2436
2437         ret = tsocket_simple_int_recv(req, perrno);
2438         if (ret == 0) {
2439                 ret = _tstream_bsd_existing_socket(mem_ctx,
2440                                                    state->fd,
2441                                                    stream,
2442                                                    location);
2443                 if (ret == -1) {
2444                         *perrno = errno;
2445                         goto done;
2446                 }
2447                 TALLOC_FREE(state->fde);
2448                 state->fd = -1;
2449
2450                 if (local) {
2451                         *local = talloc_move(mem_ctx, &state->local);
2452                 }
2453         }
2454
2455 done:
2456         tevent_req_received(req);
2457         return ret;
2458 }
2459
2460 struct tevent_req * tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
2461                                         struct tevent_context *ev,
2462                                         const struct tsocket_address *local,
2463                                         const struct tsocket_address *remote)
2464 {
2465         struct tsocket_address_bsd *lbsda =
2466                 talloc_get_type_abort(local->private_data,
2467                 struct tsocket_address_bsd);
2468         struct tevent_req *req;
2469         int sys_errno = 0;
2470
2471         switch (lbsda->u.sa.sa_family) {
2472         case AF_INET:
2473                 break;
2474 #ifdef HAVE_IPV6
2475         case AF_INET6:
2476                 break;
2477 #endif
2478         default:
2479                 sys_errno = EINVAL;
2480                 break;
2481         }
2482
2483         req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2484
2485         return req;
2486 }
2487
2488 int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
2489                                    int *perrno,
2490                                    TALLOC_CTX *mem_ctx,
2491                                    struct tstream_context **stream,
2492                                    struct tsocket_address **local,
2493                                    const char *location)
2494 {
2495         return tstream_bsd_connect_recv(req, perrno,
2496                                         mem_ctx, stream, local,
2497                                         location);
2498 }
2499
2500 struct tevent_req * tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
2501                                         struct tevent_context *ev,
2502                                         const struct tsocket_address *local,
2503                                         const struct tsocket_address *remote)
2504 {
2505         struct tsocket_address_bsd *lbsda =
2506                 talloc_get_type_abort(local->private_data,
2507                 struct tsocket_address_bsd);
2508         struct tevent_req *req;
2509         int sys_errno = 0;
2510
2511         switch (lbsda->u.sa.sa_family) {
2512         case AF_UNIX:
2513                 break;
2514         default:
2515                 sys_errno = EINVAL;
2516                 break;
2517         }
2518
2519         req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2520
2521         return req;
2522 }
2523
2524 int _tstream_unix_connect_recv(struct tevent_req *req,
2525                                       int *perrno,
2526                                       TALLOC_CTX *mem_ctx,
2527                                       struct tstream_context **stream,
2528                                       const char *location)
2529 {
2530         return tstream_bsd_connect_recv(req, perrno,
2531                                         mem_ctx, stream, NULL,
2532                                         location);
2533 }
2534
2535 int _tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
2536                              struct tstream_context **_stream1,
2537                              TALLOC_CTX *mem_ctx2,
2538                              struct tstream_context **_stream2,
2539                              const char *location)
2540 {
2541         int ret;
2542         int fds[2];
2543         int fd1;
2544         int fd2;
2545         struct tstream_context *stream1 = NULL;
2546         struct tstream_context *stream2 = NULL;
2547
2548         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
2549         if (ret == -1) {
2550                 return -1;
2551         }
2552         fd1 = fds[0];
2553         fd2 = fds[1];
2554
2555         fd1 = tsocket_bsd_common_prepare_fd(fd1, true);
2556         if (fd1 == -1) {
2557                 int sys_errno = errno;
2558                 close(fd2);
2559                 errno = sys_errno;
2560                 return -1;
2561         }
2562
2563         fd2 = tsocket_bsd_common_prepare_fd(fd2, true);
2564         if (fd2 == -1) {
2565                 int sys_errno = errno;
2566                 close(fd1);
2567                 errno = sys_errno;
2568                 return -1;
2569         }
2570
2571         ret = _tstream_bsd_existing_socket(mem_ctx1,
2572                                            fd1,
2573                                            &stream1,
2574                                            location);
2575         if (ret == -1) {
2576                 int sys_errno = errno;
2577                 close(fd1);
2578                 close(fd2);
2579                 errno = sys_errno;
2580                 return -1;
2581         }
2582
2583         ret = _tstream_bsd_existing_socket(mem_ctx2,
2584                                            fd2,
2585                                            &stream2,
2586                                            location);
2587         if (ret == -1) {
2588                 int sys_errno = errno;
2589                 talloc_free(stream1);
2590                 close(fd2);
2591                 errno = sys_errno;
2592                 return -1;
2593         }
2594
2595         *_stream1 = stream1;
2596         *_stream2 = stream2;
2597         return 0;
2598 }
2599