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