6c60ef2ebd13928b114479d2961ea0b40a1b2880
[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                 bsds->readable_handler(bsds->readable_private);
1317                 return;
1318         }
1319 }
1320
1321 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
1322                                            struct tevent_context *ev,
1323                                            void (*handler)(void *private_data),
1324                                            void *private_data)
1325 {
1326         if (ev == NULL) {
1327                 if (handler) {
1328                         errno = EINVAL;
1329                         return -1;
1330                 }
1331
1332                 bsds->readable_handler = NULL;
1333                 bsds->readable_private = NULL;
1334                 TEVENT_FD_NOT_READABLE(bsds->fde);
1335
1336                 if (bsds->fde && !bsds->writeable_handler) {
1337                         /* we don't need the fd event anymore */
1338                         bsds->event_ptr = NULL;
1339                         TALLOC_FREE(bsds->fde);
1340                 }
1341                 return 0;
1342         }
1343
1344         if (bsds->fde == NULL) {
1345                 bsds->fde = tevent_add_fd(ev, bsds,
1346                                           bsds->fd, TEVENT_FD_READ,
1347                                           tdgram_bsd_fde_handler,
1348                                           bsds);
1349                 if (!bsds->fde) {
1350                         return -1;
1351                 }
1352
1353                 /* cache the event context we're running on */
1354                 bsds->event_ptr = ev;
1355         }
1356
1357         /* read and write must use the same tevent_context */
1358         if (bsds->event_ptr != ev) {
1359                 errno = EINVAL;
1360                 return -1;
1361         }
1362
1363         TEVENT_FD_READABLE(bsds->fde);
1364         bsds->readable_handler = handler;
1365         bsds->readable_private = private_data;
1366
1367         return 0;
1368 }
1369
1370 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
1371                                             struct tevent_context *ev,
1372                                             void (*handler)(void *private_data),
1373                                             void *private_data)
1374 {
1375         if (ev == NULL) {
1376                 if (handler) {
1377                         errno = EINVAL;
1378                         return -1;
1379                 }
1380
1381                 bsds->writeable_handler = NULL;
1382                 bsds->writeable_private = NULL;
1383                 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1384
1385                 if (bsds->fde && !bsds->readable_handler) {
1386                         /* we don't need the fd event anymore */
1387                         bsds->event_ptr = NULL;
1388                         TALLOC_FREE(bsds->fde);
1389                 }
1390                 return 0;
1391         }
1392
1393         if (bsds->fde == NULL) {
1394                 bsds->fde = tevent_add_fd(ev, bsds,
1395                                           bsds->fd, TEVENT_FD_WRITE,
1396                                           tdgram_bsd_fde_handler,
1397                                           bsds);
1398                 if (!bsds->fde) {
1399                         return -1;
1400                 }
1401
1402                 /* cache the event context we're running on */
1403                 bsds->event_ptr = ev;
1404         }
1405
1406         /* read and write must use the same tevent_context */
1407         if (bsds->event_ptr != ev) {
1408                 errno = EINVAL;
1409                 return -1;
1410         }
1411
1412         TEVENT_FD_WRITEABLE(bsds->fde);
1413         bsds->writeable_handler = handler;
1414         bsds->writeable_private = private_data;
1415
1416         return 0;
1417 }
1418
1419 struct tdgram_bsd_recvfrom_state {
1420         struct tdgram_context *dgram;
1421
1422         uint8_t *buf;
1423         size_t len;
1424         struct tsocket_address *src;
1425 };
1426
1427 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
1428 {
1429         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1430                                   struct tdgram_bsd);
1431
1432         bsds->read_req = NULL;
1433         tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1434
1435         return 0;
1436 }
1437
1438 static void tdgram_bsd_recvfrom_handler(void *private_data);
1439
1440 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
1441                                         struct tevent_context *ev,
1442                                         struct tdgram_context *dgram)
1443 {
1444         struct tevent_req *req;
1445         struct tdgram_bsd_recvfrom_state *state;
1446         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1447         int ret;
1448
1449         req = tevent_req_create(mem_ctx, &state,
1450                                 struct tdgram_bsd_recvfrom_state);
1451         if (!req) {
1452                 return NULL;
1453         }
1454
1455         state->dgram    = dgram;
1456         state->buf      = NULL;
1457         state->len      = 0;
1458         state->src      = NULL;
1459
1460         if (bsds->read_req) {
1461                 tevent_req_error(req, EBUSY);
1462                 goto post;
1463         }
1464         bsds->read_req = req;
1465
1466         talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
1467
1468         if (bsds->fd == -1) {
1469                 tevent_req_error(req, ENOTCONN);
1470                 goto post;
1471         }
1472
1473         ret = tdgram_bsd_set_readable_handler(bsds, ev,
1474                                               tdgram_bsd_recvfrom_handler,
1475                                               req);
1476         if (ret == -1) {
1477                 tevent_req_error(req, errno);
1478                 goto post;
1479         }
1480
1481         return req;
1482
1483  post:
1484         tevent_req_post(req, ev);
1485         return req;
1486 }
1487
1488 static void tdgram_bsd_recvfrom_handler(void *private_data)
1489 {
1490         struct tevent_req *req = talloc_get_type_abort(private_data,
1491                                  struct tevent_req);
1492         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1493                                         struct tdgram_bsd_recvfrom_state);
1494         struct tdgram_context *dgram = state->dgram;
1495         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1496         struct tsocket_address_bsd *bsda;
1497         ssize_t ret;
1498         struct sockaddr *sa = NULL;
1499         socklen_t sa_len = 0;
1500         int err;
1501         bool retry;
1502
1503         ret = tsocket_bsd_pending(bsds->fd);
1504         if (ret == 0) {
1505                 /* retry later */
1506                 return;
1507         }
1508         err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1509         if (retry) {
1510                 /* retry later */
1511                 return;
1512         }
1513         if (tevent_req_error(req, err)) {
1514                 return;
1515         }
1516
1517         state->buf = talloc_array(state, uint8_t, ret);
1518         if (tevent_req_nomem(state->buf, req)) {
1519                 return;
1520         }
1521         state->len = ret;
1522
1523         state->src = tsocket_address_create(state,
1524                                             &tsocket_address_bsd_ops,
1525                                             &bsda,
1526                                             struct tsocket_address_bsd,
1527                                             __location__ "bsd_recvfrom");
1528         if (tevent_req_nomem(state->src, req)) {
1529                 return;
1530         }
1531
1532         ZERO_STRUCTP(bsda);
1533
1534         sa = &bsda->u.sa;
1535         sa_len = sizeof(bsda->u.ss);
1536
1537         ret = recvfrom(bsds->fd, state->buf, state->len, 0, sa, &sa_len);
1538         err = tsocket_error_from_errno(ret, errno, &retry);
1539         if (retry) {
1540                 /* retry later */
1541                 return;
1542         }
1543         if (tevent_req_error(req, err)) {
1544                 return;
1545         }
1546
1547         if (ret != state->len) {
1548                 tevent_req_error(req, EIO);
1549                 return;
1550         }
1551
1552         tevent_req_done(req);
1553 }
1554
1555 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
1556                                         int *perrno,
1557                                         TALLOC_CTX *mem_ctx,
1558                                         uint8_t **buf,
1559                                         struct tsocket_address **src)
1560 {
1561         struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1562                                         struct tdgram_bsd_recvfrom_state);
1563         ssize_t ret;
1564
1565         ret = tsocket_simple_int_recv(req, perrno);
1566         if (ret == 0) {
1567                 *buf = talloc_move(mem_ctx, &state->buf);
1568                 ret = state->len;
1569                 if (src) {
1570                         *src = talloc_move(mem_ctx, &state->src);
1571                 }
1572         }
1573
1574         tevent_req_received(req);
1575         return ret;
1576 }
1577
1578 struct tdgram_bsd_sendto_state {
1579         struct tdgram_context *dgram;
1580
1581         const uint8_t *buf;
1582         size_t len;
1583         const struct tsocket_address *dst;
1584
1585         ssize_t ret;
1586 };
1587
1588 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
1589 {
1590         struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1591                                   struct tdgram_bsd);
1592
1593         bsds->write_req = NULL;
1594         tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1595         return 0;
1596 }
1597
1598 static void tdgram_bsd_sendto_handler(void *private_data);
1599
1600 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
1601                                                  struct tevent_context *ev,
1602                                                  struct tdgram_context *dgram,
1603                                                  const uint8_t *buf,
1604                                                  size_t len,
1605                                                  const struct tsocket_address *dst)
1606 {
1607         struct tevent_req *req;
1608         struct tdgram_bsd_sendto_state *state;
1609         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1610         int ret;
1611
1612         req = tevent_req_create(mem_ctx, &state,
1613                                 struct tdgram_bsd_sendto_state);
1614         if (!req) {
1615                 return NULL;
1616         }
1617
1618         state->dgram    = dgram;
1619         state->buf      = buf;
1620         state->len      = len;
1621         state->dst      = dst;
1622         state->ret      = -1;
1623
1624         if (bsds->write_req) {
1625                 tevent_req_error(req, EBUSY);
1626                 goto post;
1627         }
1628         bsds->write_req = req;
1629
1630         talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
1631
1632         if (bsds->fd == -1) {
1633                 tevent_req_error(req, ENOTCONN);
1634                 goto post;
1635         }
1636
1637         ret = tdgram_bsd_set_writeable_handler(bsds, ev,
1638                                                tdgram_bsd_sendto_handler,
1639                                                req);
1640         if (ret == -1) {
1641                 tevent_req_error(req, errno);
1642                 goto post;
1643         }
1644
1645         return req;
1646
1647  post:
1648         tevent_req_post(req, ev);
1649         return req;
1650 }
1651
1652 static void tdgram_bsd_sendto_handler(void *private_data)
1653 {
1654         struct tevent_req *req = talloc_get_type_abort(private_data,
1655                                  struct tevent_req);
1656         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1657                                         struct tdgram_bsd_sendto_state);
1658         struct tdgram_context *dgram = state->dgram;
1659         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1660         struct sockaddr *sa = NULL;
1661         socklen_t sa_len = 0;
1662         ssize_t ret;
1663         int err;
1664         bool retry;
1665
1666         if (state->dst) {
1667                 struct tsocket_address_bsd *bsda =
1668                         talloc_get_type(state->dst->private_data,
1669                         struct tsocket_address_bsd);
1670
1671                 sa = &bsda->u.sa;
1672                 sa_len = sizeof(bsda->u.ss);
1673         }
1674
1675         ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_len);
1676         err = tsocket_error_from_errno(ret, errno, &retry);
1677         if (retry) {
1678                 /* retry later */
1679                 return;
1680         }
1681         if (tevent_req_error(req, err)) {
1682                 return;
1683         }
1684
1685         state->ret = ret;
1686
1687         tevent_req_done(req);
1688 }
1689
1690 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
1691 {
1692         struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1693                                         struct tdgram_bsd_sendto_state);
1694         ssize_t ret;
1695
1696         ret = tsocket_simple_int_recv(req, perrno);
1697         if (ret == 0) {
1698                 ret = state->ret;
1699         }
1700
1701         tevent_req_received(req);
1702         return ret;
1703 }
1704
1705 struct tdgram_bsd_disconnect_state {
1706         int ret;
1707 };
1708
1709 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1710                                                      struct tevent_context *ev,
1711                                                      struct tdgram_context *dgram)
1712 {
1713         struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1714         struct tevent_req *req;
1715         struct tdgram_bsd_disconnect_state *state;
1716         int ret;
1717         int err;
1718         bool dummy;
1719
1720         req = tevent_req_create(mem_ctx, &state,
1721                                 struct tdgram_bsd_disconnect_state);
1722         if (req == NULL) {
1723                 return NULL;
1724         }
1725         state->ret = -1;
1726
1727         if (bsds->read_req || bsds->write_req) {
1728                 tevent_req_error(req, EBUSY);
1729                 goto post;
1730         }
1731
1732         if (bsds->fd == -1) {
1733                 tevent_req_error(req, ENOTCONN);
1734                 goto post;
1735         }
1736
1737         state->ret = close(bsds->fd);
1738         bsds->fd = -1;
1739         err = tsocket_error_from_errno(ret, errno, &dummy);
1740         if (tevent_req_error(req, err)) {
1741                 goto post;
1742         }
1743
1744         tevent_req_done(req);
1745 post:
1746         tevent_req_post(req, ev);
1747         return req;
1748 }
1749
1750 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1751                                       int *perrno)
1752 {
1753         struct tdgram_bsd_disconnect_state *state = tevent_req_data(req,
1754                                         struct tdgram_bsd_disconnect_state);
1755         int ret;
1756
1757         ret = tsocket_simple_int_recv(req, perrno);
1758         if (ret == 0) {
1759                 ret = state->ret;
1760         }
1761
1762         tevent_req_received(req);
1763         return ret;
1764 }
1765
1766 static const struct tdgram_context_ops tdgram_bsd_ops = {
1767         .name                   = "bsd",
1768
1769         .recvfrom_send          = tdgram_bsd_recvfrom_send,
1770         .recvfrom_recv          = tdgram_bsd_recvfrom_recv,
1771
1772         .sendto_send            = tdgram_bsd_sendto_send,
1773         .sendto_recv            = tdgram_bsd_sendto_recv,
1774
1775         .disconnect_send        = tdgram_bsd_disconnect_send,
1776         .disconnect_recv        = tdgram_bsd_disconnect_recv,
1777 };
1778
1779 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1780 {
1781         TALLOC_FREE(bsds->fde);
1782         if (bsds->fd != -1) {
1783                 close(bsds->fd);
1784                 bsds->fd = -1;
1785         }
1786         return 0;
1787 }
1788
1789 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1790                                    const struct tsocket_address *remote,
1791                                    TALLOC_CTX *mem_ctx,
1792                                    struct tdgram_context **_dgram,
1793                                    const char *location)
1794 {
1795         struct tsocket_address_bsd *lbsda =
1796                 talloc_get_type_abort(local->private_data,
1797                 struct tsocket_address_bsd);
1798         struct tsocket_address_bsd *rbsda = NULL;
1799         struct tdgram_context *dgram;
1800         struct tdgram_bsd *bsds;
1801         int fd;
1802         int ret;
1803         bool do_bind = false;
1804         bool do_reuseaddr = false;
1805
1806         if (remote) {
1807                 rbsda = talloc_get_type_abort(remote->private_data,
1808                         struct tsocket_address_bsd);
1809         }
1810
1811         switch (lbsda->u.sa.sa_family) {
1812         case AF_UNIX:
1813                 if (lbsda->u.un.sun_path[0] != 0) {
1814                         do_reuseaddr = true;
1815                         do_bind = true;
1816                 }
1817                 break;
1818         case AF_INET:
1819                 if (lbsda->u.in.sin_port != 0) {
1820                         do_reuseaddr = true;
1821                         do_bind = true;
1822                 }
1823                 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1824                         do_bind = true;
1825                 }
1826                 break;
1827 #ifdef HAVE_IPV6
1828         case AF_INET6:
1829                 if (lbsda->u.in6.sin6_port != 0) {
1830                         do_reuseaddr = true;
1831                         do_bind = true;
1832                 }
1833                 if (memcmp(&in6addr_any,
1834                            &lbsda->u.in6.sin6_addr,
1835                            sizeof(in6addr_any)) != 0) {
1836                         do_bind = true;
1837                 }
1838                 break;
1839 #endif
1840         default:
1841                 errno = EINVAL;
1842                 return -1;
1843         }
1844
1845         fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
1846         if (fd < 0) {
1847                 return fd;
1848         }
1849
1850         fd = tsocket_bsd_common_prepare_fd(fd, true);
1851         if (fd < 0) {
1852                 return fd;
1853         }
1854
1855         dgram = tdgram_context_create(mem_ctx,
1856                                       &tdgram_bsd_ops,
1857                                       &bsds,
1858                                       struct tdgram_bsd,
1859                                       location);
1860         if (!dgram) {
1861                 int saved_errno = errno;
1862                 close(fd);
1863                 errno = saved_errno;
1864                 return -1;
1865         }
1866         ZERO_STRUCTP(bsds);
1867         bsds->fd = fd;
1868         talloc_set_destructor(bsds, tdgram_bsd_destructor);
1869
1870         if (lbsda->broadcast) {
1871                 int val = 1;
1872
1873                 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1874                                  (const void *)&val, sizeof(val));
1875                 if (ret == -1) {
1876                         int saved_errno = errno;
1877                         talloc_free(dgram);
1878                         errno = saved_errno;
1879                         return ret;
1880                 }
1881         }
1882
1883         if (do_reuseaddr) {
1884                 int val = 1;
1885
1886                 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1887                                  (const void *)&val, sizeof(val));
1888                 if (ret == -1) {
1889                         int saved_errno = errno;
1890                         talloc_free(dgram);
1891                         errno = saved_errno;
1892                         return ret;
1893                 }
1894         }
1895
1896         if (do_bind) {
1897                 ret = bind(fd, &lbsda->u.sa, sizeof(lbsda->u.ss));
1898                 if (ret == -1) {
1899                         int saved_errno = errno;
1900                         talloc_free(dgram);
1901                         errno = saved_errno;
1902                         return ret;
1903                 }
1904         }
1905
1906         if (rbsda) {
1907                 ret = connect(fd, &rbsda->u.sa, sizeof(rbsda->u.ss));
1908                 if (ret == -1) {
1909                         int saved_errno = errno;
1910                         talloc_free(dgram);
1911                         errno = saved_errno;
1912                         return ret;
1913                 }
1914         }
1915
1916         *_dgram = dgram;
1917         return 0;
1918 }
1919
1920 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1921                             const struct tsocket_address *remote,
1922                             TALLOC_CTX *mem_ctx,
1923                             struct tdgram_context **dgram,
1924                             const char *location)
1925 {
1926         struct tsocket_address_bsd *lbsda =
1927                 talloc_get_type_abort(local->private_data,
1928                 struct tsocket_address_bsd);
1929         int ret;
1930
1931         switch (lbsda->u.sa.sa_family) {
1932         case AF_INET:
1933                 break;
1934 #ifdef HAVE_IPV6
1935         case AF_INET6:
1936                 break;
1937 #endif
1938         default:
1939                 errno = EINVAL;
1940                 return -1;
1941         }
1942
1943         ret = tdgram_bsd_dgram_socket(local, remote, mem_ctx, dgram, location);
1944
1945         return ret;
1946 }
1947
1948 int _tdgram_unix_dgram_socket(const struct tsocket_address *local,
1949                               const struct tsocket_address *remote,
1950                               TALLOC_CTX *mem_ctx,
1951                               struct tdgram_context **dgram,
1952                               const char *location)
1953 {
1954         struct tsocket_address_bsd *lbsda =
1955                 talloc_get_type_abort(local->private_data,
1956                 struct tsocket_address_bsd);
1957         int ret;
1958
1959         switch (lbsda->u.sa.sa_family) {
1960         case AF_UNIX:
1961                 break;
1962         default:
1963                 errno = EINVAL;
1964                 return -1;
1965         }
1966
1967         ret = tdgram_bsd_dgram_socket(local, remote, mem_ctx, dgram, location);
1968
1969         return ret;
1970 }
1971