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