Merge commit 'origin/master' into libcli-auth-merge-without-netlogond
[samba.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 #ifdef HAVE_IPV6
527         case AF_INET6:
528                 prefix = "ipv6";
529                 break;
530 #endif
531         default:
532                 errno = EINVAL;
533                 return NULL;
534         }
535
536         addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
537         if (!addr_str) {
538                 return NULL;
539         }
540
541         port = tsocket_address_inet_port(addr);
542
543         str = talloc_asprintf(mem_ctx, "%s:%s:%u",
544                               prefix, addr_str, port);
545         talloc_free(addr_str);
546
547         return str;
548 }
549
550 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
551                                                          TALLOC_CTX *mem_ctx,
552                                                          const char *location)
553 {
554         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
555                                            struct tsocket_address_bsd);
556         struct tsocket_address *copy;
557         int ret;
558
559         ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
560                                                  &bsda->u.sa,
561                                                  sizeof(bsda->u.ss),
562                                                  &copy,
563                                                  location);
564         if (ret != 0) {
565                 return NULL;
566         }
567
568         tsocket_address_inet_set_broadcast(copy, bsda->broadcast);
569         return copy;
570 }
571
572 int _tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
573                                        int fd, bool close_on_disconnect,
574                                        struct tsocket_context **_sock,
575                                        const char *location)
576 {
577         struct tsocket_context *sock;
578         struct tsocket_context_bsd *bsds;
579
580         sock = tsocket_context_create(mem_ctx,
581                                       &tsocket_context_bsd_ops,
582                                       &bsds,
583                                       struct tsocket_context_bsd,
584                                       location);
585         if (!sock) {
586                 return -1;
587         }
588
589         bsds->close_on_disconnect       = close_on_disconnect;
590         bsds->fd                        = fd;
591         bsds->fde                       = NULL;
592
593         *_sock = sock;
594         return 0;
595 }
596
597 static int tsocket_address_bsd_create_socket(const struct tsocket_address *addr,
598                                              enum tsocket_type type,
599                                              TALLOC_CTX *mem_ctx,
600                                              struct tsocket_context **_sock,
601                                              const char *location)
602 {
603         struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
604                                            struct tsocket_address_bsd);
605         struct tsocket_context *sock;
606         int bsd_type;
607         int fd;
608         int ret;
609         bool do_bind = false;
610         bool do_reuseaddr = false;
611
612         switch (type) {
613         case TSOCKET_TYPE_STREAM:
614                 if (bsda->broadcast) {
615                         errno = EINVAL;
616                         return -1;
617                 }
618                 bsd_type = SOCK_STREAM;
619                 break;
620         default:
621                 errno = EPROTONOSUPPORT;
622                 return -1;
623         }
624
625         switch (bsda->u.sa.sa_family) {
626         case AF_UNIX:
627                 if (bsda->broadcast) {
628                         errno = EINVAL;
629                         return -1;
630                 }
631                 if (bsda->u.un.sun_path[0] != 0) {
632                         do_bind = true;
633                 }
634                 break;
635         case AF_INET:
636                 if (bsda->u.in.sin_port != 0) {
637                         do_reuseaddr = true;
638                         do_bind = true;
639                 }
640                 if (bsda->u.in.sin_addr.s_addr == INADDR_ANY) {
641                         do_bind = true;
642                 }
643                 break;
644 #ifdef HAVE_IPV6
645         case AF_INET6:
646                 if (bsda->u.in6.sin6_port != 0) {
647                         do_reuseaddr = true;
648                         do_bind = true;
649                 }
650                 if (memcmp(&in6addr_any,
651                            &bsda->u.in6.sin6_addr,
652                            sizeof(in6addr_any)) != 0) {
653                         do_bind = true;
654                 }
655                 break;
656 #endif
657         default:
658                 errno = EINVAL;
659                 return -1;
660         }
661
662         fd = socket(bsda->u.sa.sa_family, bsd_type, 0);
663         if (fd < 0) {
664                 return fd;
665         }
666
667         fd = tsocket_common_prepare_fd(fd, true);
668         if (fd < 0) {
669                 return fd;
670         }
671
672         ret = _tsocket_context_bsd_wrap_existing(mem_ctx, fd, true,
673                                                  &sock, location);
674         if (ret != 0) {
675                 int saved_errno = errno;
676                 close(fd);
677                 errno = saved_errno;
678                 return ret;
679         }
680
681         if (bsda->broadcast) {
682                 ret = tsocket_context_bsd_set_option(sock, "SO_BROADCAST", true, "1");
683                 if (ret != 0) {
684                         int saved_errno = errno;
685                         talloc_free(sock);
686                         errno = saved_errno;
687                         return ret;
688                 }
689         }
690
691         if (do_reuseaddr) {
692                 ret = tsocket_context_bsd_set_option(sock, "SO_REUSEADDR", true, "1");
693                 if (ret != 0) {
694                         int saved_errno = errno;
695                         talloc_free(sock);
696                         errno = saved_errno;
697                         return ret;
698                 }
699         }
700
701         if (do_bind) {
702                 ret = bind(fd, &bsda->u.sa, sizeof(bsda->u.ss));
703                 if (ret != 0) {
704                         int saved_errno = errno;
705                         talloc_free(sock);
706                         errno = saved_errno;
707                         return ret;
708                 }
709         }
710
711         *_sock = sock;
712         return 0;
713 }
714
715 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
716         .name           = "bsd",
717         .string         = tsocket_address_bsd_string,
718         .copy           = tsocket_address_bsd_copy,
719         .create_socket  = tsocket_address_bsd_create_socket
720 };
721
722 static void tsocket_context_bsd_fde_handler(struct tevent_context *ev,
723                                             struct tevent_fd *fde,
724                                             uint16_t flags,
725                                             void *private_data)
726 {
727         struct tsocket_context *sock = talloc_get_type(private_data,
728                                        struct tsocket_context);
729
730         if (flags & TEVENT_FD_WRITE) {
731                 sock->event.write_handler(sock, sock->event.write_private);
732                 return;
733         }
734         if (flags & TEVENT_FD_READ) {
735                 sock->event.read_handler(sock, sock->event.read_private);
736                 return;
737         }
738 }
739
740 static int tsocket_context_bsd_set_event_context(struct tsocket_context *sock,
741                                                  struct tevent_context *ev)
742 {
743         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
744                                            struct tsocket_context_bsd);
745
746         talloc_free(bsds->fde);
747         bsds->fde = NULL;
748         ZERO_STRUCT(sock->event);
749
750         if (!ev) {
751                 return 0;
752         }
753
754         bsds->fde = tevent_add_fd(ev, bsds,
755                                   bsds->fd,
756                                   0,
757                                   tsocket_context_bsd_fde_handler,
758                                   sock);
759         if (!bsds->fde) {
760                 if (errno == 0) {
761                         errno = ENOMEM;
762                 }
763                 return -1;
764         }
765
766         sock->event.ctx = ev;
767
768         return 0;
769 }
770
771 static int tsocket_context_bsd_set_read_handler(struct tsocket_context *sock,
772                                                 tsocket_event_handler_t handler,
773                                                 void *private_data)
774 {
775         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
776                                            struct tsocket_context_bsd);
777
778         if (sock->event.read_handler && !handler) {
779                 TEVENT_FD_NOT_READABLE(bsds->fde);
780         } else if (!sock->event.read_handler && handler) {
781                 TEVENT_FD_READABLE(bsds->fde);
782         }
783
784         sock->event.read_handler = handler;
785         sock->event.read_private = private_data;
786
787         return 0;
788 }
789
790 static int tsocket_context_bsd_set_write_handler(struct tsocket_context *sock,
791                                                  tsocket_event_handler_t handler,
792                                                  void *private_data)
793 {
794         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
795                                            struct tsocket_context_bsd);
796
797         if (sock->event.write_handler && !handler) {
798                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
799         } else if (!sock->event.write_handler && handler) {
800                 TEVENT_FD_WRITEABLE(bsds->fde);
801         }
802
803         sock->event.write_handler = handler;
804         sock->event.write_private = private_data;
805
806         return 0;
807 }
808
809 static int tsocket_context_bsd_connect_to(struct tsocket_context *sock,
810                                           const struct tsocket_address *remote)
811 {
812         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
813                                            struct tsocket_context_bsd);
814         struct tsocket_address_bsd *bsda = talloc_get_type(remote->private_data,
815                                            struct tsocket_address_bsd);
816         int ret;
817
818         ret = connect(bsds->fd, &bsda->u.sa,
819                       sizeof(bsda->u.ss));
820
821         return ret;
822 }
823
824 static int tsocket_context_bsd_listen_on(struct tsocket_context *sock,
825                                           int queue_size)
826 {
827         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
828                                            struct tsocket_context_bsd);
829         int ret;
830
831         ret = listen(bsds->fd, queue_size);
832
833         return ret;
834 }
835
836 static int tsocket_context_bsd_accept_new(struct tsocket_context *sock,
837                                            TALLOC_CTX *mem_ctx,
838                                            struct tsocket_context **_new_sock,
839                                            const char *location)
840 {
841         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
842                                            struct tsocket_context_bsd);
843         int new_fd;
844         struct tsocket_context *new_sock;
845         struct tsocket_context_bsd *new_bsds;
846         struct sockaddr_storage ss;
847         void *p = &ss;
848         socklen_t ss_len = sizeof(ss);
849
850         new_fd = accept(bsds->fd, (struct sockaddr *)p, &ss_len);
851         if (new_fd < 0) {
852                 return new_fd;
853         }
854
855         new_fd = tsocket_common_prepare_fd(new_fd, true);
856         if (new_fd < 0) {
857                 return new_fd;
858         }
859
860         new_sock = tsocket_context_create(mem_ctx,
861                                           &tsocket_context_bsd_ops,
862                                           &new_bsds,
863                                           struct tsocket_context_bsd,
864                                           location);
865         if (!new_sock) {
866                 int saved_errno = errno;
867                 close(new_fd);
868                 errno = saved_errno;
869                 return -1;
870         }
871
872         new_bsds->close_on_disconnect   = true;
873         new_bsds->fd                    = new_fd;
874         new_bsds->fde                   = NULL;
875
876         *_new_sock = new_sock;
877         return 0;
878 }
879
880 static ssize_t tsocket_context_bsd_pending_data(struct tsocket_context *sock)
881 {
882         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
883                                            struct tsocket_context_bsd);
884         int ret;
885         int value = 0;
886
887         ret = ioctl(bsds->fd, FIONREAD, &value);
888         if (ret == -1) {
889                 return ret;
890         }
891
892         if (ret == 0) {
893                 if (value == 0) {
894                         int error=0;
895                         socklen_t len = sizeof(error);
896                         /*
897                          * if no data is available check if the socket
898                          * is in error state. For dgram sockets
899                          * it's the way to return ICMP error messages
900                          * of connected sockets to the caller.
901                          */
902                         ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR,
903                                          &error, &len);
904                         if (ret == -1) {
905                                 return ret;
906                         }
907                         if (error != 0) {
908                                 errno = error;
909                                 return -1;
910                         }
911                 }
912                 return value;
913         }
914
915         /* this should not be reached */
916         errno = EIO;
917         return -1;
918 }
919
920 static int tsocket_context_bsd_readv_data(struct tsocket_context *sock,
921                                           const struct iovec *vector,
922                                           size_t count)
923 {
924         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
925                                            struct tsocket_context_bsd);
926         int ret;
927
928         ret = readv(bsds->fd, vector, count);
929
930         return ret;
931 }
932
933 static int tsocket_context_bsd_writev_data(struct tsocket_context *sock,
934                                            const struct iovec *vector,
935                                            size_t count)
936 {
937         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
938                                            struct tsocket_context_bsd);
939         int ret;
940
941         ret = writev(bsds->fd, vector, count);
942
943         return ret;
944 }
945
946 static int tsocket_context_bsd_get_status(const struct tsocket_context *sock)
947 {
948         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
949                                            struct tsocket_context_bsd);
950         int ret;
951         int error=0;
952         socklen_t len = sizeof(error);
953
954         if (bsds->fd == -1) {
955                 errno = EPIPE;
956                 return -1;
957         }
958
959         ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR, &error, &len);
960         if (ret == -1) {
961                 return ret;
962         }
963         if (error != 0) {
964                 errno = error;
965                 return -1;
966         }
967
968         return 0;
969 }
970
971 static int tsocket_context_bsd_get_local_address(const struct tsocket_context *sock,
972                                                   TALLOC_CTX *mem_ctx,
973                                                   struct tsocket_address **_addr,
974                                                   const char *location)
975 {
976         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
977                                            struct tsocket_context_bsd);
978         struct tsocket_address *addr;
979         struct tsocket_address_bsd *bsda;
980         ssize_t ret;
981         socklen_t sa_len;
982
983         addr = tsocket_address_create(mem_ctx,
984                                       &tsocket_address_bsd_ops,
985                                       &bsda,
986                                       struct tsocket_address_bsd,
987                                       location);
988         if (!addr) {
989                 return -1;
990         }
991
992         ZERO_STRUCTP(bsda);
993
994         sa_len = sizeof(bsda->u.ss);
995         ret = getsockname(bsds->fd, &bsda->u.sa, &sa_len);
996         if (ret < 0) {
997                 int saved_errno = errno;
998                 talloc_free(addr);
999                 errno = saved_errno;
1000                 return ret;
1001         }
1002
1003         *_addr = addr;
1004         return 0;
1005 }
1006
1007 static int tsocket_context_bsd_get_remote_address(const struct tsocket_context *sock,
1008                                                    TALLOC_CTX *mem_ctx,
1009                                                    struct tsocket_address **_addr,
1010                                                    const char *location)
1011 {
1012         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1013                                            struct tsocket_context_bsd);
1014         struct tsocket_address *addr;
1015         struct tsocket_address_bsd *bsda;
1016         ssize_t ret;
1017         socklen_t sa_len;
1018
1019         addr = tsocket_address_create(mem_ctx,
1020                                       &tsocket_address_bsd_ops,
1021                                       &bsda,
1022                                       struct tsocket_address_bsd,
1023                                       location);
1024         if (!addr) {
1025                 return -1;
1026         }
1027
1028         ZERO_STRUCTP(bsda);
1029
1030         sa_len = sizeof(bsda->u.ss);
1031         ret = getpeername(bsds->fd, &bsda->u.sa, &sa_len);
1032         if (ret < 0) {
1033                 int saved_errno = errno;
1034                 talloc_free(addr);
1035                 errno = saved_errno;
1036                 return ret;
1037         }
1038
1039         *_addr = addr;
1040         return 0;
1041 }
1042
1043 static const struct tsocket_context_bsd_option {
1044         const char *name;
1045         int level;
1046         int optnum;
1047         int optval;
1048 } tsocket_context_bsd_options[] = {
1049 #define TSOCKET_OPTION(_level, _optnum, _optval) { \
1050         .name = #_optnum, \
1051         .level = _level, \
1052         .optnum = _optnum, \
1053         .optval = _optval \
1054 }
1055         TSOCKET_OPTION(SOL_SOCKET, SO_REUSEADDR, 0),
1056         TSOCKET_OPTION(SOL_SOCKET, SO_BROADCAST, 0)
1057 };
1058
1059 static int tsocket_context_bsd_get_option(const struct tsocket_context *sock,
1060                                           const char *option,
1061                                           TALLOC_CTX *mem_ctx,
1062                                           char **_value)
1063 {
1064         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1065                                            struct tsocket_context_bsd);
1066         const struct tsocket_context_bsd_option *opt = NULL;
1067         uint32_t i;
1068         int optval;
1069         socklen_t optval_len = sizeof(optval);
1070         char *value;
1071         int ret;
1072
1073         for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
1074                 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
1075                         continue;
1076                 }
1077
1078                 opt = &tsocket_context_bsd_options[i];
1079                 break;
1080         }
1081
1082         if (!opt) {
1083                 goto nosys;
1084         }
1085
1086         ret = getsockopt(bsds->fd, opt->level, opt->optnum,
1087                          (void *)&optval, &optval_len);
1088         if (ret != 0) {
1089                 return ret;
1090         }
1091
1092         if (optval_len != sizeof(optval)) {
1093                 value = NULL;
1094         } if (opt->optval != 0) {
1095                 if (optval == opt->optval) {
1096                         value = talloc_strdup(mem_ctx, "1");
1097                 } else {
1098                         value = talloc_strdup(mem_ctx, "0");
1099                 }
1100                 if (!value) {
1101                         goto nomem;
1102                 }
1103         } else {
1104                 value = talloc_asprintf(mem_ctx, "%d", optval);
1105                 if (!value) {
1106                         goto nomem;
1107                 }
1108         }
1109
1110         *_value = value;
1111         return 0;
1112
1113  nomem:
1114         errno = ENOMEM;
1115         return -1;
1116  nosys:
1117         errno = ENOSYS;
1118         return -1;
1119 }
1120
1121 static int tsocket_context_bsd_set_option(const struct tsocket_context *sock,
1122                                           const char *option,
1123                                           bool force,
1124                                           const char *value)
1125 {
1126         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1127                                            struct tsocket_context_bsd);
1128         const struct tsocket_context_bsd_option *opt = NULL;
1129         uint32_t i;
1130         int optval;
1131         int ret;
1132
1133         for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
1134                 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
1135                         continue;
1136                 }
1137
1138                 opt = &tsocket_context_bsd_options[i];
1139                 break;
1140         }
1141
1142         if (!opt) {
1143                 goto nosys;
1144         }
1145
1146         if (value) {
1147                 if (opt->optval != 0) {
1148                         errno = EINVAL;
1149                         return -1;
1150                 }
1151
1152                 optval = atoi(value);
1153         } else {
1154                 optval = opt->optval;
1155         }
1156
1157         ret = setsockopt(bsds->fd, opt->level, opt->optnum,
1158                          (const void *)&optval, sizeof(optval));
1159         if (ret != 0) {
1160                 if (!force) {
1161                         errno = 0;
1162                         return 0;
1163                 }
1164                 return ret;
1165         }
1166
1167         return 0;
1168
1169  nosys:
1170         if (!force) {
1171                 return 0;
1172         }
1173
1174         errno = ENOSYS;
1175         return -1;
1176 }
1177
1178 static void tsocket_context_bsd_disconnect(struct tsocket_context *sock)
1179 {
1180         struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1181                                            struct tsocket_context_bsd);
1182
1183         tsocket_context_bsd_set_event_context(sock, NULL);
1184
1185         if (bsds->fd != -1) {
1186                 if (bsds->close_on_disconnect) {
1187                         close(bsds->fd);
1188                 }
1189                 bsds->fd = -1;
1190         }
1191 }
1192
1193 static const struct tsocket_context_ops tsocket_context_bsd_ops = {
1194         .name                   = "bsd",
1195
1196         .set_event_context      = tsocket_context_bsd_set_event_context,
1197         .set_read_handler       = tsocket_context_bsd_set_read_handler,
1198         .set_write_handler      = tsocket_context_bsd_set_write_handler,
1199
1200         .connect_to             = tsocket_context_bsd_connect_to,
1201         .listen_on              = tsocket_context_bsd_listen_on,
1202         .accept_new             = tsocket_context_bsd_accept_new,
1203
1204         .pending_data           = tsocket_context_bsd_pending_data,
1205         .readv_data             = tsocket_context_bsd_readv_data,
1206         .writev_data            = tsocket_context_bsd_writev_data,
1207
1208         .get_status             = tsocket_context_bsd_get_status,
1209         .get_local_address      = tsocket_context_bsd_get_local_address,
1210         .get_remote_address     = tsocket_context_bsd_get_remote_address,
1211
1212         .get_option             = tsocket_context_bsd_get_option,
1213         .set_option             = tsocket_context_bsd_set_option,
1214
1215         .disconnect             = tsocket_context_bsd_disconnect
1216 };
1217
1218 struct tdgram_bsd {
1219         int fd;
1220
1221         void *event_ptr;
1222         struct tevent_fd *fde;
1223
1224         void *readable_private;
1225         void (*readable_handler)(void *private_data);
1226         void *writeable_private;
1227         void (*writeable_handler)(void *private_data);
1228
1229         struct tevent_req *read_req;
1230         struct tevent_req *write_req;
1231 };
1232
1233 static void tdgram_bsd_fde_handler(struct tevent_context *ev,
1234                                    struct tevent_fd *fde,
1235                                    uint16_t flags,
1236                                    void *private_data)
1237 {
1238         struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
1239                                   struct tdgram_bsd);
1240
1241         if (flags & TEVENT_FD_WRITE) {
1242                 bsds->writeable_handler(bsds->writeable_private);
1243                 return;
1244         }
1245         if (flags & TEVENT_FD_READ) {
1246                 if (!bsds->readable_handler) {
1247                         TEVENT_FD_NOT_READABLE(bsds->fde);
1248                         return;
1249                 }
1250                 bsds->readable_handler(bsds->readable_private);
1251                 return;
1252         }
1253 }
1254
1255 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
1256                                            struct tevent_context *ev,
1257                                            void (*handler)(void *private_data),
1258                                            void *private_data)
1259 {
1260         if (ev == NULL) {
1261                 if (handler) {
1262                         errno = EINVAL;
1263                         return -1;
1264                 }
1265                 if (!bsds->readable_handler) {
1266                         return 0;
1267                 }
1268                 bsds->readable_handler = NULL;
1269                 bsds->readable_private = NULL;
1270
1271                 return 0;
1272         }
1273
1274         /* read and write must use the same tevent_context */
1275         if (bsds->event_ptr != ev) {
1276                 if (bsds->readable_handler || bsds->writeable_handler) {
1277                         errno = EINVAL;
1278                         return -1;
1279                 }
1280                 bsds->event_ptr = NULL;
1281                 TALLOC_FREE(bsds->fde);
1282         }
1283
1284         if (bsds->fde == NULL) {
1285                 bsds->fde = tevent_add_fd(ev, bsds,
1286                                           bsds->fd, TEVENT_FD_READ,
1287                                           tdgram_bsd_fde_handler,
1288                                           bsds);
1289                 if (!bsds->fde) {
1290                         return -1;
1291                 }
1292
1293                 /* cache the event context we're running on */
1294                 bsds->event_ptr = ev;
1295         } else if (!bsds->readable_handler) {
1296                 TEVENT_FD_READABLE(bsds->fde);
1297         }
1298
1299         bsds->readable_handler = handler;
1300         bsds->readable_private = private_data;
1301
1302         return 0;
1303 }
1304
1305 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
1306                                             struct tevent_context *ev,
1307                                             void (*handler)(void *private_data),
1308                                             void *private_data)
1309 {
1310         if (ev == NULL) {
1311                 if (handler) {
1312                         errno = EINVAL;
1313                         return -1;
1314                 }
1315                 if (!bsds->writeable_handler) {
1316                         return 0;
1317                 }
1318                 bsds->writeable_handler = NULL;
1319                 bsds->writeable_private = NULL;
1320                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1321
1322                 return 0;
1323         }
1324
1325         /* read and write must use the same tevent_context */
1326         if (bsds->event_ptr != ev) {
1327                 if (bsds->readable_handler || bsds->writeable_handler) {
1328                         errno = EINVAL;
1329                         return -1;
1330                 }
1331                 bsds->event_ptr = NULL;
1332                 TALLOC_FREE(bsds->fde);
1333         }
1334
1335         if (bsds->fde == NULL) {
1336                 bsds->fde = tevent_add_fd(ev, bsds,
1337                                           bsds->fd, TEVENT_FD_WRITE,
1338                                           tdgram_bsd_fde_handler,
1339                                           bsds);
1340                 if (!bsds->fde) {
1341                         return -1;
1342                 }
1343
1344                 /* cache the event context we're running on */
1345                 bsds->event_ptr = ev;
1346         } else if (!bsds->writeable_handler) {
1347                 TEVENT_FD_WRITEABLE(bsds->fde);
1348         }
1349
1350         bsds->writeable_handler = handler;
1351         bsds->writeable_private = private_data;
1352
1353         return 0;
1354 }
1355
1356 struct tdgram_bsd_recvfrom_state {
1357         struct tdgram_context *dgram;
1358
1359         uint8_t *buf;
1360         size_t len;
1361         struct tsocket_address *src;
1362 };
1363
1364 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
1365 {
1366         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1367                                   struct tdgram_bsd);
1368
1369         bsds->read_req = NULL;
1370         tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1371
1372         return 0;
1373 }
1374
1375 static void tdgram_bsd_recvfrom_handler(void *private_data);
1376
1377 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
1378                                         struct tevent_context *ev,
1379                                         struct tdgram_context *dgram)
1380 {
1381         struct tevent_req *req;
1382         struct tdgram_bsd_recvfrom_state *state;
1383         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1384         int ret;
1385
1386         req = tevent_req_create(mem_ctx, &state,
1387                                 struct tdgram_bsd_recvfrom_state);
1388         if (!req) {
1389                 return NULL;
1390         }
1391
1392         state->dgram    = dgram;
1393         state->buf      = NULL;
1394         state->len      = 0;
1395         state->src      = NULL;
1396
1397         if (bsds->read_req) {
1398                 tevent_req_error(req, EBUSY);
1399                 goto post;
1400         }
1401         bsds->read_req = req;
1402
1403         talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
1404
1405         if (bsds->fd == -1) {
1406                 tevent_req_error(req, ENOTCONN);
1407                 goto post;
1408         }
1409
1410         /*
1411          * this is a fast path, not waiting for the
1412          * socket to become explicit readable gains
1413          * about 10%-20% performance in benchmark tests.
1414          */
1415         tdgram_bsd_recvfrom_handler(req);
1416         if (!tevent_req_is_in_progress(req)) {
1417                 goto post;
1418         }
1419
1420         ret = tdgram_bsd_set_readable_handler(bsds, ev,
1421                                               tdgram_bsd_recvfrom_handler,
1422                                               req);
1423         if (ret == -1) {
1424                 tevent_req_error(req, errno);
1425                 goto post;
1426         }
1427
1428         return req;
1429
1430  post:
1431         tevent_req_post(req, ev);
1432         return req;
1433 }
1434
1435 static void tdgram_bsd_recvfrom_handler(void *private_data)
1436 {
1437         struct tevent_req *req = talloc_get_type_abort(private_data,
1438                                  struct tevent_req);
1439         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1440                                         struct tdgram_bsd_recvfrom_state);
1441         struct tdgram_context *dgram = state->dgram;
1442         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1443         struct tsocket_address_bsd *bsda;
1444         ssize_t ret;
1445         struct sockaddr *sa = NULL;
1446         socklen_t sa_len = 0;
1447         int err;
1448         bool retry;
1449
1450         ret = tsocket_bsd_pending(bsds->fd);
1451         if (ret == 0) {
1452                 /* retry later */
1453                 return;
1454         }
1455         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1456         if (retry) {
1457                 /* retry later */
1458                 return;
1459         }
1460         if (tevent_req_error(req, err)) {
1461                 return;
1462         }
1463
1464         state->buf = talloc_array(state, uint8_t, ret);
1465         if (tevent_req_nomem(state->buf, req)) {
1466                 return;
1467         }
1468         state->len = ret;
1469
1470         state->src = tsocket_address_create(state,
1471                                             &tsocket_address_bsd_ops,
1472                                             &bsda,
1473                                             struct tsocket_address_bsd,
1474                                             __location__ "bsd_recvfrom");
1475         if (tevent_req_nomem(state->src, req)) {
1476                 return;
1477         }
1478
1479         ZERO_STRUCTP(bsda);
1480
1481         sa = &bsda->u.sa;
1482         sa_len = sizeof(bsda->u.ss);
1483
1484         ret = recvfrom(bsds->fd, state->buf, state->len, 0, sa, &sa_len);
1485         err = tsocket_error_from_errno(ret, errno, &retry);
1486         if (retry) {
1487                 /* retry later */
1488                 return;
1489         }
1490         if (tevent_req_error(req, err)) {
1491                 return;
1492         }
1493
1494         if (ret != state->len) {
1495                 tevent_req_error(req, EIO);
1496                 return;
1497         }
1498
1499         tevent_req_done(req);
1500 }
1501
1502 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
1503                                         int *perrno,
1504                                         TALLOC_CTX *mem_ctx,
1505                                         uint8_t **buf,
1506                                         struct tsocket_address **src)
1507 {
1508         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1509                                         struct tdgram_bsd_recvfrom_state);
1510         ssize_t ret;
1511
1512         ret = tsocket_simple_int_recv(req, perrno);
1513         if (ret == 0) {
1514                 *buf = talloc_move(mem_ctx, &state->buf);
1515                 ret = state->len;
1516                 if (src) {
1517                         *src = talloc_move(mem_ctx, &state->src);
1518                 }
1519         }
1520
1521         tevent_req_received(req);
1522         return ret;
1523 }
1524
1525 struct tdgram_bsd_sendto_state {
1526         struct tdgram_context *dgram;
1527
1528         const uint8_t *buf;
1529         size_t len;
1530         const struct tsocket_address *dst;
1531
1532         ssize_t ret;
1533 };
1534
1535 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
1536 {
1537         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1538                                   struct tdgram_bsd);
1539
1540         bsds->write_req = NULL;
1541         tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1542         return 0;
1543 }
1544
1545 static void tdgram_bsd_sendto_handler(void *private_data);
1546
1547 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
1548                                                  struct tevent_context *ev,
1549                                                  struct tdgram_context *dgram,
1550                                                  const uint8_t *buf,
1551                                                  size_t len,
1552                                                  const struct tsocket_address *dst)
1553 {
1554         struct tevent_req *req;
1555         struct tdgram_bsd_sendto_state *state;
1556         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1557         int ret;
1558
1559         req = tevent_req_create(mem_ctx, &state,
1560                                 struct tdgram_bsd_sendto_state);
1561         if (!req) {
1562                 return NULL;
1563         }
1564
1565         state->dgram    = dgram;
1566         state->buf      = buf;
1567         state->len      = len;
1568         state->dst      = dst;
1569         state->ret      = -1;
1570
1571         if (bsds->write_req) {
1572                 tevent_req_error(req, EBUSY);
1573                 goto post;
1574         }
1575         bsds->write_req = req;
1576
1577         talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
1578
1579         if (bsds->fd == -1) {
1580                 tevent_req_error(req, ENOTCONN);
1581                 goto post;
1582         }
1583
1584         /*
1585          * this is a fast path, not waiting for the
1586          * socket to become explicit writeable gains
1587          * about 10%-20% performance in benchmark tests.
1588          */
1589         tdgram_bsd_sendto_handler(req);
1590         if (!tevent_req_is_in_progress(req)) {
1591                 goto post;
1592         }
1593
1594         ret = tdgram_bsd_set_writeable_handler(bsds, ev,
1595                                                tdgram_bsd_sendto_handler,
1596                                                req);
1597         if (ret == -1) {
1598                 tevent_req_error(req, errno);
1599                 goto post;
1600         }
1601
1602         return req;
1603
1604  post:
1605         tevent_req_post(req, ev);
1606         return req;
1607 }
1608
1609 static void tdgram_bsd_sendto_handler(void *private_data)
1610 {
1611         struct tevent_req *req = talloc_get_type_abort(private_data,
1612                                  struct tevent_req);
1613         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1614                                         struct tdgram_bsd_sendto_state);
1615         struct tdgram_context *dgram = state->dgram;
1616         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1617         struct sockaddr *sa = NULL;
1618         socklen_t sa_len = 0;
1619         ssize_t ret;
1620         int err;
1621         bool retry;
1622
1623         if (state->dst) {
1624                 struct tsocket_address_bsd *bsda =
1625                         talloc_get_type(state->dst->private_data,
1626                         struct tsocket_address_bsd);
1627
1628                 sa = &bsda->u.sa;
1629                 sa_len = sizeof(bsda->u.ss);
1630         }
1631
1632         ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_len);
1633         err = tsocket_error_from_errno(ret, errno, &retry);
1634         if (retry) {
1635                 /* retry later */
1636                 return;
1637         }
1638         if (tevent_req_error(req, err)) {
1639                 return;
1640         }
1641
1642         state->ret = ret;
1643
1644         tevent_req_done(req);
1645 }
1646
1647 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
1648 {
1649         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1650                                         struct tdgram_bsd_sendto_state);
1651         ssize_t ret;
1652
1653         ret = tsocket_simple_int_recv(req, perrno);
1654         if (ret == 0) {
1655                 ret = state->ret;
1656         }
1657
1658         tevent_req_received(req);
1659         return ret;
1660 }
1661
1662 struct tdgram_bsd_disconnect_state {
1663         uint8_t __dummy;
1664 };
1665
1666 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1667                                                      struct tevent_context *ev,
1668                                                      struct tdgram_context *dgram)
1669 {
1670         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1671         struct tevent_req *req;
1672         struct tdgram_bsd_disconnect_state *state;
1673         int ret;
1674         int err;
1675         bool dummy;
1676
1677         req = tevent_req_create(mem_ctx, &state,
1678                                 struct tdgram_bsd_disconnect_state);
1679         if (req == NULL) {
1680                 return NULL;
1681         }
1682
1683         if (bsds->read_req || bsds->write_req) {
1684                 tevent_req_error(req, EBUSY);
1685                 goto post;
1686         }
1687
1688         if (bsds->fd == -1) {
1689                 tevent_req_error(req, ENOTCONN);
1690                 goto post;
1691         }
1692
1693         ret = close(bsds->fd);
1694         bsds->fd = -1;
1695         err = tsocket_error_from_errno(ret, errno, &dummy);
1696         if (tevent_req_error(req, err)) {
1697                 goto post;
1698         }
1699
1700         tevent_req_done(req);
1701 post:
1702         tevent_req_post(req, ev);
1703         return req;
1704 }
1705
1706 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1707                                       int *perrno)
1708 {
1709         int ret;
1710
1711         ret = tsocket_simple_int_recv(req, perrno);
1712
1713         tevent_req_received(req);
1714         return ret;
1715 }
1716
1717 static const struct tdgram_context_ops tdgram_bsd_ops = {
1718         .name                   = "bsd",
1719
1720         .recvfrom_send          = tdgram_bsd_recvfrom_send,
1721         .recvfrom_recv          = tdgram_bsd_recvfrom_recv,
1722
1723         .sendto_send            = tdgram_bsd_sendto_send,
1724         .sendto_recv            = tdgram_bsd_sendto_recv,
1725
1726         .disconnect_send        = tdgram_bsd_disconnect_send,
1727         .disconnect_recv        = tdgram_bsd_disconnect_recv,
1728 };
1729
1730 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1731 {
1732         TALLOC_FREE(bsds->fde);
1733         if (bsds->fd != -1) {
1734                 close(bsds->fd);
1735                 bsds->fd = -1;
1736         }
1737         return 0;
1738 }
1739
1740 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1741                                    const struct tsocket_address *remote,
1742                                    TALLOC_CTX *mem_ctx,
1743                                    struct tdgram_context **_dgram,
1744                                    const char *location)
1745 {
1746         struct tsocket_address_bsd *lbsda =
1747                 talloc_get_type_abort(local->private_data,
1748                 struct tsocket_address_bsd);
1749         struct tsocket_address_bsd *rbsda = NULL;
1750         struct tdgram_context *dgram;
1751         struct tdgram_bsd *bsds;
1752         int fd;
1753         int ret;
1754         bool do_bind = false;
1755         bool do_reuseaddr = false;
1756
1757         if (remote) {
1758                 rbsda = talloc_get_type_abort(remote->private_data,
1759                         struct tsocket_address_bsd);
1760         }
1761
1762         switch (lbsda->u.sa.sa_family) {
1763         case AF_UNIX:
1764                 if (lbsda->u.un.sun_path[0] != 0) {
1765                         do_reuseaddr = true;
1766                         do_bind = true;
1767                 }
1768                 break;
1769         case AF_INET:
1770                 if (lbsda->u.in.sin_port != 0) {
1771                         do_reuseaddr = true;
1772                         do_bind = true;
1773                 }
1774                 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1775                         do_bind = true;
1776                 }
1777                 break;
1778 #ifdef HAVE_IPV6
1779         case AF_INET6:
1780                 if (lbsda->u.in6.sin6_port != 0) {
1781                         do_reuseaddr = true;
1782                         do_bind = true;
1783                 }
1784                 if (memcmp(&in6addr_any,
1785                            &lbsda->u.in6.sin6_addr,
1786                            sizeof(in6addr_any)) != 0) {
1787                         do_bind = true;
1788                 }
1789                 break;
1790 #endif
1791         default:
1792                 errno = EINVAL;
1793                 return -1;
1794         }
1795
1796         fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
1797         if (fd < 0) {
1798                 return fd;
1799         }
1800
1801         fd = tsocket_bsd_common_prepare_fd(fd, true);
1802         if (fd < 0) {
1803                 return fd;
1804         }
1805
1806         dgram = tdgram_context_create(mem_ctx,
1807                                       &tdgram_bsd_ops,
1808                                       &bsds,
1809                                       struct tdgram_bsd,
1810                                       location);
1811         if (!dgram) {
1812                 int saved_errno = errno;
1813                 close(fd);
1814                 errno = saved_errno;
1815                 return -1;
1816         }
1817         ZERO_STRUCTP(bsds);
1818         bsds->fd = fd;
1819         talloc_set_destructor(bsds, tdgram_bsd_destructor);
1820
1821         if (lbsda->broadcast) {
1822                 int val = 1;
1823
1824                 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1825                                  (const void *)&val, sizeof(val));
1826                 if (ret == -1) {
1827                         int saved_errno = errno;
1828                         talloc_free(dgram);
1829                         errno = saved_errno;
1830                         return ret;
1831                 }
1832         }
1833
1834         if (do_reuseaddr) {
1835                 int val = 1;
1836
1837                 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1838                                  (const void *)&val, sizeof(val));
1839                 if (ret == -1) {
1840                         int saved_errno = errno;
1841                         talloc_free(dgram);
1842                         errno = saved_errno;
1843                         return ret;
1844                 }
1845         }
1846
1847         if (do_bind) {
1848                 ret = bind(fd, &lbsda->u.sa, sizeof(lbsda->u.ss));
1849                 if (ret == -1) {
1850                         int saved_errno = errno;
1851                         talloc_free(dgram);
1852                         errno = saved_errno;
1853                         return ret;
1854                 }
1855         }
1856
1857         if (rbsda) {
1858                 ret = connect(fd, &rbsda->u.sa, sizeof(rbsda->u.ss));
1859                 if (ret == -1) {
1860                         int saved_errno = errno;
1861                         talloc_free(dgram);
1862                         errno = saved_errno;
1863                         return ret;
1864                 }
1865         }
1866
1867         *_dgram = dgram;
1868         return 0;
1869 }
1870
1871 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1872                             const struct tsocket_address *remote,
1873                             TALLOC_CTX *mem_ctx,
1874                             struct tdgram_context **dgram,
1875                             const char *location)
1876 {
1877         struct tsocket_address_bsd *lbsda =
1878                 talloc_get_type_abort(local->private_data,
1879                 struct tsocket_address_bsd);
1880         int ret;
1881
1882         switch (lbsda->u.sa.sa_family) {
1883         case AF_INET:
1884                 break;
1885 #ifdef HAVE_IPV6
1886         case AF_INET6:
1887                 break;
1888 #endif
1889         default:
1890                 errno = EINVAL;
1891                 return -1;
1892         }
1893
1894         ret = tdgram_bsd_dgram_socket(local, remote, mem_ctx, dgram, location);
1895
1896         return ret;
1897 }
1898
1899 int _tdgram_unix_dgram_socket(const struct tsocket_address *local,
1900                               const struct tsocket_address *remote,
1901                               TALLOC_CTX *mem_ctx,
1902                               struct tdgram_context **dgram,
1903                               const char *location)
1904 {
1905         struct tsocket_address_bsd *lbsda =
1906                 talloc_get_type_abort(local->private_data,
1907                 struct tsocket_address_bsd);
1908         int ret;
1909
1910         switch (lbsda->u.sa.sa_family) {
1911         case AF_UNIX:
1912                 break;
1913         default:
1914                 errno = EINVAL;
1915                 return -1;
1916         }
1917
1918         ret = tdgram_bsd_dgram_socket(local, remote, mem_ctx, dgram, location);
1919
1920         return ret;
1921 }
1922