2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tsocket
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
25 #include "system/filesys.h"
26 #include "system/network.h"
28 #include "tsocket_internal.h"
29 #include "lib/util/iov_buf.h"
31 static int tsocket_bsd_error_from_errno(int ret
,
49 if (sys_errno
== EINTR
) {
54 if (sys_errno
== EINPROGRESS
) {
59 if (sys_errno
== EAGAIN
) {
64 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
65 if (sys_errno
== ENOMEM
) {
71 if (sys_errno
== EWOULDBLOCK
) {
80 static int tsocket_bsd_common_prepare_fd(int fd
, bool high_fd
)
93 /* first make a fd >= 3 */
103 for (i
=0; i
<num_fds
; i
++) {
112 /* fd should be nonblocking. */
115 #define FLAG_TO_SET O_NONBLOCK
118 #define FLAG_TO_SET O_NDELAY
120 #define FLAG_TO_SET FNDELAY
124 if ((flags
= fcntl(fd
, F_GETFL
)) == -1) {
128 flags
|= FLAG_TO_SET
;
129 if (fcntl(fd
, F_SETFL
, flags
) == -1) {
135 /* fd should be closed on exec() */
137 result
= flags
= fcntl(fd
, F_GETFD
, 0);
140 result
= fcntl(fd
, F_SETFD
, flags
);
157 static ssize_t
tsocket_bsd_pending(int fd
)
163 ret
= ioctl(fd
, FIONREAD
, &value
);
169 /* this should not be reached */
182 * if no data is available check if the socket is in error state. For
183 * dgram sockets it's the way to return ICMP error messages of
184 * connected sockets to the caller.
186 ret
= getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
);
197 static const struct tsocket_address_ops tsocket_address_bsd_ops
;
199 struct tsocket_address_bsd
{
200 socklen_t sa_socklen
;
203 struct sockaddr_in in
;
205 struct sockaddr_in6 in6
;
207 struct sockaddr_un un
;
208 struct sockaddr_storage ss
;
212 int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX
*mem_ctx
,
213 const struct sockaddr
*sa
,
215 struct tsocket_address
**_addr
,
216 const char *location
)
218 struct tsocket_address
*addr
;
219 struct tsocket_address_bsd
*bsda
;
221 if (sa_socklen
< sizeof(sa
->sa_family
)) {
226 switch (sa
->sa_family
) {
228 if (sa_socklen
> sizeof(struct sockaddr_un
)) {
229 sa_socklen
= sizeof(struct sockaddr_un
);
233 if (sa_socklen
< sizeof(struct sockaddr_in
)) {
237 sa_socklen
= sizeof(struct sockaddr_in
);
241 if (sa_socklen
< sizeof(struct sockaddr_in6
)) {
245 sa_socklen
= sizeof(struct sockaddr_in6
);
249 errno
= EAFNOSUPPORT
;
253 if (sa_socklen
> sizeof(struct sockaddr_storage
)) {
258 addr
= tsocket_address_create(mem_ctx
,
259 &tsocket_address_bsd_ops
,
261 struct tsocket_address_bsd
,
270 memcpy(&bsda
->u
.ss
, sa
, sa_socklen
);
272 bsda
->sa_socklen
= sa_socklen
;
273 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
274 bsda
->u
.sa
.sa_len
= bsda
->sa_socklen
;
281 ssize_t
tsocket_address_bsd_sockaddr(const struct tsocket_address
*addr
,
285 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
286 struct tsocket_address_bsd
);
293 if (sa_socklen
< bsda
->sa_socklen
) {
298 if (sa_socklen
> bsda
->sa_socklen
) {
299 memset(sa
, 0, sa_socklen
);
300 sa_socklen
= bsda
->sa_socklen
;
303 memcpy(sa
, &bsda
->u
.ss
, sa_socklen
);
304 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
305 sa
->sa_len
= sa_socklen
;
310 bool tsocket_address_is_inet(const struct tsocket_address
*addr
, const char *fam
)
312 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
313 struct tsocket_address_bsd
);
319 switch (bsda
->u
.sa
.sa_family
) {
321 if (strcasecmp(fam
, "ip") == 0) {
325 if (strcasecmp(fam
, "ipv4") == 0) {
332 if (strcasecmp(fam
, "ip") == 0) {
336 if (strcasecmp(fam
, "ipv6") == 0) {
347 int _tsocket_address_inet_from_strings(TALLOC_CTX
*mem_ctx
,
351 struct tsocket_address
**_addr
,
352 const char *location
)
354 struct addrinfo hints
;
355 struct addrinfo
*result
= NULL
;
361 * we use SOCKET_STREAM here to get just one result
362 * back from getaddrinfo().
364 hints
.ai_socktype
= SOCK_STREAM
;
365 hints
.ai_flags
= AI_NUMERICHOST
| AI_NUMERICSERV
;
367 if (strcasecmp(fam
, "ip") == 0) {
368 hints
.ai_family
= AF_UNSPEC
;
376 } else if (strcasecmp(fam
, "ipv4") == 0) {
377 hints
.ai_family
= AF_INET
;
382 } else if (strcasecmp(fam
, "ipv6") == 0) {
383 hints
.ai_family
= AF_INET6
;
389 errno
= EAFNOSUPPORT
;
393 snprintf(port_str
, sizeof(port_str
), "%u", port
);
395 ret
= getaddrinfo(addr
, port_str
, &hints
, &result
);
406 if (result
->ai_socktype
!= SOCK_STREAM
) {
412 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
420 freeaddrinfo(result
);
425 char *tsocket_address_inet_addr_string(const struct tsocket_address
*addr
,
428 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
429 struct tsocket_address_bsd
);
430 char addr_str
[INET6_ADDRSTRLEN
+1];
438 switch (bsda
->u
.sa
.sa_family
) {
440 str
= inet_ntop(bsda
->u
.in
.sin_family
,
441 &bsda
->u
.in
.sin_addr
,
442 addr_str
, sizeof(addr_str
));
446 str
= inet_ntop(bsda
->u
.in6
.sin6_family
,
447 &bsda
->u
.in6
.sin6_addr
,
448 addr_str
, sizeof(addr_str
));
460 return talloc_strdup(mem_ctx
, str
);
463 uint16_t tsocket_address_inet_port(const struct tsocket_address
*addr
)
465 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
466 struct tsocket_address_bsd
);
474 switch (bsda
->u
.sa
.sa_family
) {
476 port
= ntohs(bsda
->u
.in
.sin_port
);
480 port
= ntohs(bsda
->u
.in6
.sin6_port
);
491 int tsocket_address_inet_set_port(struct tsocket_address
*addr
,
494 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
495 struct tsocket_address_bsd
);
502 switch (bsda
->u
.sa
.sa_family
) {
504 bsda
->u
.in
.sin_port
= htons(port
);
508 bsda
->u
.in6
.sin6_port
= htons(port
);
519 bool tsocket_address_is_unix(const struct tsocket_address
*addr
)
521 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
522 struct tsocket_address_bsd
);
528 switch (bsda
->u
.sa
.sa_family
) {
536 int _tsocket_address_unix_from_path(TALLOC_CTX
*mem_ctx
,
538 struct tsocket_address
**_addr
,
539 const char *location
)
541 struct sockaddr_un un
;
549 if (strlen(path
) > sizeof(un
.sun_path
)-1) {
550 errno
= ENAMETOOLONG
;
555 un
.sun_family
= AF_UNIX
;
556 strncpy(un
.sun_path
, path
, sizeof(un
.sun_path
)-1);
558 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
559 (struct sockaddr
*)p
,
567 char *tsocket_address_unix_path(const struct tsocket_address
*addr
,
570 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
571 struct tsocket_address_bsd
);
579 switch (bsda
->u
.sa
.sa_family
) {
581 str
= bsda
->u
.un
.sun_path
;
588 return talloc_strdup(mem_ctx
, str
);
591 static char *tsocket_address_bsd_string(const struct tsocket_address
*addr
,
594 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
595 struct tsocket_address_bsd
);
598 const char *prefix
= NULL
;
601 switch (bsda
->u
.sa
.sa_family
) {
603 return talloc_asprintf(mem_ctx
, "unix:%s",
604 bsda
->u
.un
.sun_path
);
618 addr_str
= tsocket_address_inet_addr_string(addr
, mem_ctx
);
623 port
= tsocket_address_inet_port(addr
);
625 str
= talloc_asprintf(mem_ctx
, "%s:%s:%u",
626 prefix
, addr_str
, port
);
627 talloc_free(addr_str
);
632 static struct tsocket_address
*tsocket_address_bsd_copy(const struct tsocket_address
*addr
,
634 const char *location
)
636 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
637 struct tsocket_address_bsd
);
638 struct tsocket_address
*copy
;
641 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
653 static const struct tsocket_address_ops tsocket_address_bsd_ops
= {
655 .string
= tsocket_address_bsd_string
,
656 .copy
= tsocket_address_bsd_copy
,
663 struct tevent_fd
*fde
;
664 bool optimize_recvfrom
;
666 void *readable_private
;
667 void (*readable_handler
)(void *private_data
);
668 void *writeable_private
;
669 void (*writeable_handler
)(void *private_data
);
672 bool tdgram_bsd_optimize_recvfrom(struct tdgram_context
*dgram
,
675 struct tdgram_bsd
*bsds
=
676 talloc_get_type(_tdgram_context_data(dgram
),
681 /* not a bsd socket */
685 old
= bsds
->optimize_recvfrom
;
686 bsds
->optimize_recvfrom
= on
;
691 static void tdgram_bsd_fde_handler(struct tevent_context
*ev
,
692 struct tevent_fd
*fde
,
696 struct tdgram_bsd
*bsds
= talloc_get_type_abort(private_data
,
699 if (flags
& TEVENT_FD_WRITE
) {
700 bsds
->writeable_handler(bsds
->writeable_private
);
703 if (flags
& TEVENT_FD_READ
) {
704 if (!bsds
->readable_handler
) {
705 TEVENT_FD_NOT_READABLE(bsds
->fde
);
708 bsds
->readable_handler(bsds
->readable_private
);
713 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd
*bsds
,
714 struct tevent_context
*ev
,
715 void (*handler
)(void *private_data
),
723 if (!bsds
->readable_handler
) {
726 bsds
->readable_handler
= NULL
;
727 bsds
->readable_private
= NULL
;
732 /* read and write must use the same tevent_context */
733 if (bsds
->event_ptr
!= ev
) {
734 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
738 bsds
->event_ptr
= NULL
;
739 TALLOC_FREE(bsds
->fde
);
742 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
743 TALLOC_FREE(bsds
->fde
);
745 bsds
->fde
= tevent_add_fd(ev
, bsds
,
746 bsds
->fd
, TEVENT_FD_READ
,
747 tdgram_bsd_fde_handler
,
754 /* cache the event context we're running on */
755 bsds
->event_ptr
= ev
;
756 } else if (!bsds
->readable_handler
) {
757 TEVENT_FD_READABLE(bsds
->fde
);
760 bsds
->readable_handler
= handler
;
761 bsds
->readable_private
= private_data
;
766 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd
*bsds
,
767 struct tevent_context
*ev
,
768 void (*handler
)(void *private_data
),
776 if (!bsds
->writeable_handler
) {
779 bsds
->writeable_handler
= NULL
;
780 bsds
->writeable_private
= NULL
;
781 TEVENT_FD_NOT_WRITEABLE(bsds
->fde
);
786 /* read and write must use the same tevent_context */
787 if (bsds
->event_ptr
!= ev
) {
788 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
792 bsds
->event_ptr
= NULL
;
793 TALLOC_FREE(bsds
->fde
);
796 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
797 TALLOC_FREE(bsds
->fde
);
799 bsds
->fde
= tevent_add_fd(ev
, bsds
,
800 bsds
->fd
, TEVENT_FD_WRITE
,
801 tdgram_bsd_fde_handler
,
808 /* cache the event context we're running on */
809 bsds
->event_ptr
= ev
;
810 } else if (!bsds
->writeable_handler
) {
811 TEVENT_FD_WRITEABLE(bsds
->fde
);
814 bsds
->writeable_handler
= handler
;
815 bsds
->writeable_private
= private_data
;
820 struct tdgram_bsd_recvfrom_state
{
821 struct tdgram_context
*dgram
;
825 struct tsocket_address
*src
;
828 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state
*state
)
830 struct tdgram_bsd
*bsds
= tdgram_context_data(state
->dgram
,
833 tdgram_bsd_set_readable_handler(bsds
, NULL
, NULL
, NULL
);
838 static void tdgram_bsd_recvfrom_handler(void *private_data
);
840 static struct tevent_req
*tdgram_bsd_recvfrom_send(TALLOC_CTX
*mem_ctx
,
841 struct tevent_context
*ev
,
842 struct tdgram_context
*dgram
)
844 struct tevent_req
*req
;
845 struct tdgram_bsd_recvfrom_state
*state
;
846 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
849 req
= tevent_req_create(mem_ctx
, &state
,
850 struct tdgram_bsd_recvfrom_state
);
855 state
->dgram
= dgram
;
856 state
->first_try
= true;
861 talloc_set_destructor(state
, tdgram_bsd_recvfrom_destructor
);
863 if (bsds
->fd
== -1) {
864 tevent_req_error(req
, ENOTCONN
);
870 * this is a fast path, not waiting for the
871 * socket to become explicit readable gains
872 * about 10%-20% performance in benchmark tests.
874 if (bsds
->optimize_recvfrom
) {
876 * We only do the optimization on
877 * recvfrom if the caller asked for it.
879 * This is needed because in most cases
880 * we preferr to flush send buffers before
881 * receiving incoming requests.
883 tdgram_bsd_recvfrom_handler(req
);
884 if (!tevent_req_is_in_progress(req
)) {
889 ret
= tdgram_bsd_set_readable_handler(bsds
, ev
,
890 tdgram_bsd_recvfrom_handler
,
893 tevent_req_error(req
, errno
);
900 tevent_req_post(req
, ev
);
904 static void tdgram_bsd_recvfrom_handler(void *private_data
)
906 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
908 struct tdgram_bsd_recvfrom_state
*state
= tevent_req_data(req
,
909 struct tdgram_bsd_recvfrom_state
);
910 struct tdgram_context
*dgram
= state
->dgram
;
911 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
912 struct tsocket_address_bsd
*bsda
;
917 ret
= tsocket_bsd_pending(bsds
->fd
);
918 if (state
->first_try
&& ret
== 0) {
919 state
->first_try
= false;
923 state
->first_try
= false;
925 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
930 if (tevent_req_error(req
, err
)) {
934 /* note that 'ret' can be 0 here */
935 state
->buf
= talloc_array(state
, uint8_t, ret
);
936 if (tevent_req_nomem(state
->buf
, req
)) {
941 state
->src
= tsocket_address_create(state
,
942 &tsocket_address_bsd_ops
,
944 struct tsocket_address_bsd
,
945 __location__
"bsd_recvfrom");
946 if (tevent_req_nomem(state
->src
, req
)) {
951 bsda
->sa_socklen
= sizeof(bsda
->u
.ss
);
952 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
953 bsda
->u
.sa
.sa_len
= bsda
->sa_socklen
;
956 ret
= recvfrom(bsds
->fd
, state
->buf
, state
->len
, 0,
957 &bsda
->u
.sa
, &bsda
->sa_socklen
);
958 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
963 if (tevent_req_error(req
, err
)) {
968 * Some systems (FreeBSD, see bug #7115) return too much
969 * bytes in tsocket_bsd_pending()/ioctl(fd, FIONREAD, ...),
970 * the return value includes some IP/UDP header bytes,
971 * while recvfrom() just returns the payload.
973 state
->buf
= talloc_realloc(state
, state
->buf
, uint8_t, ret
);
974 if (tevent_req_nomem(state
->buf
, req
)) {
979 tevent_req_done(req
);
982 static ssize_t
tdgram_bsd_recvfrom_recv(struct tevent_req
*req
,
986 struct tsocket_address
**src
)
988 struct tdgram_bsd_recvfrom_state
*state
= tevent_req_data(req
,
989 struct tdgram_bsd_recvfrom_state
);
992 ret
= tsocket_simple_int_recv(req
, perrno
);
994 *buf
= talloc_move(mem_ctx
, &state
->buf
);
997 *src
= talloc_move(mem_ctx
, &state
->src
);
1001 tevent_req_received(req
);
1005 struct tdgram_bsd_sendto_state
{
1006 struct tdgram_context
*dgram
;
1010 const struct tsocket_address
*dst
;
1015 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state
*state
)
1017 struct tdgram_bsd
*bsds
= tdgram_context_data(state
->dgram
,
1020 tdgram_bsd_set_writeable_handler(bsds
, NULL
, NULL
, NULL
);
1025 static void tdgram_bsd_sendto_handler(void *private_data
);
1027 static struct tevent_req
*tdgram_bsd_sendto_send(TALLOC_CTX
*mem_ctx
,
1028 struct tevent_context
*ev
,
1029 struct tdgram_context
*dgram
,
1032 const struct tsocket_address
*dst
)
1034 struct tevent_req
*req
;
1035 struct tdgram_bsd_sendto_state
*state
;
1036 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1039 req
= tevent_req_create(mem_ctx
, &state
,
1040 struct tdgram_bsd_sendto_state
);
1045 state
->dgram
= dgram
;
1051 talloc_set_destructor(state
, tdgram_bsd_sendto_destructor
);
1053 if (bsds
->fd
== -1) {
1054 tevent_req_error(req
, ENOTCONN
);
1059 * this is a fast path, not waiting for the
1060 * socket to become explicit writeable gains
1061 * about 10%-20% performance in benchmark tests.
1063 tdgram_bsd_sendto_handler(req
);
1064 if (!tevent_req_is_in_progress(req
)) {
1068 ret
= tdgram_bsd_set_writeable_handler(bsds
, ev
,
1069 tdgram_bsd_sendto_handler
,
1072 tevent_req_error(req
, errno
);
1079 tevent_req_post(req
, ev
);
1083 static void tdgram_bsd_sendto_handler(void *private_data
)
1085 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1087 struct tdgram_bsd_sendto_state
*state
= tevent_req_data(req
,
1088 struct tdgram_bsd_sendto_state
);
1089 struct tdgram_context
*dgram
= state
->dgram
;
1090 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1091 struct sockaddr
*sa
= NULL
;
1092 socklen_t sa_socklen
= 0;
1098 struct tsocket_address_bsd
*bsda
=
1099 talloc_get_type(state
->dst
->private_data
,
1100 struct tsocket_address_bsd
);
1103 sa_socklen
= bsda
->sa_socklen
;
1106 ret
= sendto(bsds
->fd
, state
->buf
, state
->len
, 0, sa
, sa_socklen
);
1107 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1113 if (err
== EMSGSIZE
) {
1114 /* round up in 1K increments */
1115 int bufsize
= ((state
->len
+ 1023) & (~1023));
1117 ret
= setsockopt(bsds
->fd
, SOL_SOCKET
, SO_SNDBUF
, &bufsize
,
1121 * We do the retry here, rather then via the
1122 * handler, as we only want to retry once for
1123 * this condition, so if there is a mismatch
1124 * between what setsockopt() accepts and what can
1125 * actually be sent, we do not end up in a
1129 ret
= sendto(bsds
->fd
, state
->buf
, state
->len
,
1131 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1132 if (retry
) { /* retry later */
1138 if (tevent_req_error(req
, err
)) {
1144 tevent_req_done(req
);
1147 static ssize_t
tdgram_bsd_sendto_recv(struct tevent_req
*req
, int *perrno
)
1149 struct tdgram_bsd_sendto_state
*state
= tevent_req_data(req
,
1150 struct tdgram_bsd_sendto_state
);
1153 ret
= tsocket_simple_int_recv(req
, perrno
);
1158 tevent_req_received(req
);
1162 struct tdgram_bsd_disconnect_state
{
1166 static struct tevent_req
*tdgram_bsd_disconnect_send(TALLOC_CTX
*mem_ctx
,
1167 struct tevent_context
*ev
,
1168 struct tdgram_context
*dgram
)
1170 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1171 struct tevent_req
*req
;
1172 struct tdgram_bsd_disconnect_state
*state
;
1177 req
= tevent_req_create(mem_ctx
, &state
,
1178 struct tdgram_bsd_disconnect_state
);
1183 if (bsds
->fd
== -1) {
1184 tevent_req_error(req
, ENOTCONN
);
1188 TALLOC_FREE(bsds
->fde
);
1189 ret
= close(bsds
->fd
);
1191 err
= tsocket_bsd_error_from_errno(ret
, errno
, &dummy
);
1192 if (tevent_req_error(req
, err
)) {
1196 tevent_req_done(req
);
1198 tevent_req_post(req
, ev
);
1202 static int tdgram_bsd_disconnect_recv(struct tevent_req
*req
,
1207 ret
= tsocket_simple_int_recv(req
, perrno
);
1209 tevent_req_received(req
);
1213 static const struct tdgram_context_ops tdgram_bsd_ops
= {
1216 .recvfrom_send
= tdgram_bsd_recvfrom_send
,
1217 .recvfrom_recv
= tdgram_bsd_recvfrom_recv
,
1219 .sendto_send
= tdgram_bsd_sendto_send
,
1220 .sendto_recv
= tdgram_bsd_sendto_recv
,
1222 .disconnect_send
= tdgram_bsd_disconnect_send
,
1223 .disconnect_recv
= tdgram_bsd_disconnect_recv
,
1226 static int tdgram_bsd_destructor(struct tdgram_bsd
*bsds
)
1228 TALLOC_FREE(bsds
->fde
);
1229 if (bsds
->fd
!= -1) {
1236 static int tdgram_bsd_dgram_socket(const struct tsocket_address
*local
,
1237 const struct tsocket_address
*remote
,
1239 TALLOC_CTX
*mem_ctx
,
1240 struct tdgram_context
**_dgram
,
1241 const char *location
)
1243 struct tsocket_address_bsd
*lbsda
=
1244 talloc_get_type_abort(local
->private_data
,
1245 struct tsocket_address_bsd
);
1246 struct tsocket_address_bsd
*rbsda
= NULL
;
1247 struct tdgram_context
*dgram
;
1248 struct tdgram_bsd
*bsds
;
1251 bool do_bind
= false;
1252 bool do_reuseaddr
= false;
1253 bool do_ipv6only
= false;
1254 bool is_inet
= false;
1255 int sa_fam
= lbsda
->u
.sa
.sa_family
;
1258 rbsda
= talloc_get_type_abort(remote
->private_data
,
1259 struct tsocket_address_bsd
);
1262 switch (lbsda
->u
.sa
.sa_family
) {
1268 if (lbsda
->u
.un
.sun_path
[0] != 0) {
1269 do_reuseaddr
= true;
1274 if (lbsda
->u
.in
.sin_port
!= 0) {
1275 do_reuseaddr
= true;
1278 if (lbsda
->u
.in
.sin_addr
.s_addr
!= INADDR_ANY
) {
1285 if (lbsda
->u
.in6
.sin6_port
!= 0) {
1286 do_reuseaddr
= true;
1289 if (memcmp(&in6addr_any
,
1290 &lbsda
->u
.in6
.sin6_addr
,
1291 sizeof(in6addr_any
)) != 0) {
1303 if (!do_bind
&& is_inet
&& rbsda
) {
1304 sa_fam
= rbsda
->u
.sa
.sa_family
;
1307 do_ipv6only
= false;
1317 fd
= socket(sa_fam
, SOCK_DGRAM
, 0);
1322 fd
= tsocket_bsd_common_prepare_fd(fd
, true);
1327 dgram
= tdgram_context_create(mem_ctx
,
1333 int saved_errno
= errno
;
1335 errno
= saved_errno
;
1340 talloc_set_destructor(bsds
, tdgram_bsd_destructor
);
1346 ret
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1347 (const void *)&val
, sizeof(val
));
1349 int saved_errno
= errno
;
1351 errno
= saved_errno
;
1360 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
,
1361 (const void *)&val
, sizeof(val
));
1363 int saved_errno
= errno
;
1365 errno
= saved_errno
;
1373 ret
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
1374 (const void *)&val
, sizeof(val
));
1376 int saved_errno
= errno
;
1378 errno
= saved_errno
;
1384 ret
= bind(fd
, &lbsda
->u
.sa
, lbsda
->sa_socklen
);
1386 int saved_errno
= errno
;
1388 errno
= saved_errno
;
1394 if (rbsda
->u
.sa
.sa_family
!= sa_fam
) {
1400 ret
= connect(fd
, &rbsda
->u
.sa
, rbsda
->sa_socklen
);
1402 int saved_errno
= errno
;
1404 errno
= saved_errno
;
1413 int _tdgram_inet_udp_socket(const struct tsocket_address
*local
,
1414 const struct tsocket_address
*remote
,
1415 TALLOC_CTX
*mem_ctx
,
1416 struct tdgram_context
**dgram
,
1417 const char *location
)
1419 struct tsocket_address_bsd
*lbsda
=
1420 talloc_get_type_abort(local
->private_data
,
1421 struct tsocket_address_bsd
);
1424 switch (lbsda
->u
.sa
.sa_family
) {
1436 ret
= tdgram_bsd_dgram_socket(local
, remote
, false,
1437 mem_ctx
, dgram
, location
);
1442 int _tdgram_unix_socket(const struct tsocket_address
*local
,
1443 const struct tsocket_address
*remote
,
1444 TALLOC_CTX
*mem_ctx
,
1445 struct tdgram_context
**dgram
,
1446 const char *location
)
1448 struct tsocket_address_bsd
*lbsda
=
1449 talloc_get_type_abort(local
->private_data
,
1450 struct tsocket_address_bsd
);
1453 switch (lbsda
->u
.sa
.sa_family
) {
1461 ret
= tdgram_bsd_dgram_socket(local
, remote
, false,
1462 mem_ctx
, dgram
, location
);
1467 struct tstream_bsd
{
1471 struct tevent_fd
*fde
;
1472 bool optimize_readv
;
1474 void *readable_private
;
1475 void (*readable_handler
)(void *private_data
);
1476 void *writeable_private
;
1477 void (*writeable_handler
)(void *private_data
);
1480 bool tstream_bsd_optimize_readv(struct tstream_context
*stream
,
1483 struct tstream_bsd
*bsds
=
1484 talloc_get_type(_tstream_context_data(stream
),
1485 struct tstream_bsd
);
1489 /* not a bsd socket */
1493 old
= bsds
->optimize_readv
;
1494 bsds
->optimize_readv
= on
;
1499 static void tstream_bsd_fde_handler(struct tevent_context
*ev
,
1500 struct tevent_fd
*fde
,
1504 struct tstream_bsd
*bsds
= talloc_get_type_abort(private_data
,
1505 struct tstream_bsd
);
1507 if (flags
& TEVENT_FD_WRITE
) {
1508 bsds
->writeable_handler(bsds
->writeable_private
);
1511 if (flags
& TEVENT_FD_READ
) {
1512 if (!bsds
->readable_handler
) {
1513 if (bsds
->writeable_handler
) {
1514 bsds
->writeable_handler(bsds
->writeable_private
);
1517 TEVENT_FD_NOT_READABLE(bsds
->fde
);
1520 bsds
->readable_handler(bsds
->readable_private
);
1525 static int tstream_bsd_set_readable_handler(struct tstream_bsd
*bsds
,
1526 struct tevent_context
*ev
,
1527 void (*handler
)(void *private_data
),
1535 if (!bsds
->readable_handler
) {
1538 bsds
->readable_handler
= NULL
;
1539 bsds
->readable_private
= NULL
;
1544 /* read and write must use the same tevent_context */
1545 if (bsds
->event_ptr
!= ev
) {
1546 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
1550 bsds
->event_ptr
= NULL
;
1551 TALLOC_FREE(bsds
->fde
);
1554 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
1555 TALLOC_FREE(bsds
->fde
);
1557 bsds
->fde
= tevent_add_fd(ev
, bsds
,
1558 bsds
->fd
, TEVENT_FD_READ
,
1559 tstream_bsd_fde_handler
,
1566 /* cache the event context we're running on */
1567 bsds
->event_ptr
= ev
;
1568 } else if (!bsds
->readable_handler
) {
1569 TEVENT_FD_READABLE(bsds
->fde
);
1572 bsds
->readable_handler
= handler
;
1573 bsds
->readable_private
= private_data
;
1578 static int tstream_bsd_set_writeable_handler(struct tstream_bsd
*bsds
,
1579 struct tevent_context
*ev
,
1580 void (*handler
)(void *private_data
),
1588 if (!bsds
->writeable_handler
) {
1591 bsds
->writeable_handler
= NULL
;
1592 bsds
->writeable_private
= NULL
;
1593 TEVENT_FD_NOT_WRITEABLE(bsds
->fde
);
1598 /* read and write must use the same tevent_context */
1599 if (bsds
->event_ptr
!= ev
) {
1600 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
1604 bsds
->event_ptr
= NULL
;
1605 TALLOC_FREE(bsds
->fde
);
1608 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
1609 TALLOC_FREE(bsds
->fde
);
1611 bsds
->fde
= tevent_add_fd(ev
, bsds
,
1613 TEVENT_FD_READ
| TEVENT_FD_WRITE
,
1614 tstream_bsd_fde_handler
,
1621 /* cache the event context we're running on */
1622 bsds
->event_ptr
= ev
;
1623 } else if (!bsds
->writeable_handler
) {
1624 uint16_t flags
= tevent_fd_get_flags(bsds
->fde
);
1625 flags
|= TEVENT_FD_READ
| TEVENT_FD_WRITE
;
1626 tevent_fd_set_flags(bsds
->fde
, flags
);
1629 bsds
->writeable_handler
= handler
;
1630 bsds
->writeable_private
= private_data
;
1635 static ssize_t
tstream_bsd_pending_bytes(struct tstream_context
*stream
)
1637 struct tstream_bsd
*bsds
= tstream_context_data(stream
,
1638 struct tstream_bsd
);
1641 if (bsds
->fd
== -1) {
1646 ret
= tsocket_bsd_pending(bsds
->fd
);
1651 struct tstream_bsd_readv_state
{
1652 struct tstream_context
*stream
;
1654 struct iovec
*vector
;
1660 static int tstream_bsd_readv_destructor(struct tstream_bsd_readv_state
*state
)
1662 struct tstream_bsd
*bsds
= tstream_context_data(state
->stream
,
1663 struct tstream_bsd
);
1665 tstream_bsd_set_readable_handler(bsds
, NULL
, NULL
, NULL
);
1670 static void tstream_bsd_readv_handler(void *private_data
);
1672 static struct tevent_req
*tstream_bsd_readv_send(TALLOC_CTX
*mem_ctx
,
1673 struct tevent_context
*ev
,
1674 struct tstream_context
*stream
,
1675 struct iovec
*vector
,
1678 struct tevent_req
*req
;
1679 struct tstream_bsd_readv_state
*state
;
1680 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
1683 req
= tevent_req_create(mem_ctx
, &state
,
1684 struct tstream_bsd_readv_state
);
1689 state
->stream
= stream
;
1690 /* we make a copy of the vector so that we can modify it */
1691 state
->vector
= talloc_array(state
, struct iovec
, count
);
1692 if (tevent_req_nomem(state
->vector
, req
)) {
1695 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
1696 state
->count
= count
;
1699 talloc_set_destructor(state
, tstream_bsd_readv_destructor
);
1701 if (bsds
->fd
== -1) {
1702 tevent_req_error(req
, ENOTCONN
);
1707 * this is a fast path, not waiting for the
1708 * socket to become explicit readable gains
1709 * about 10%-20% performance in benchmark tests.
1711 if (bsds
->optimize_readv
) {
1713 * We only do the optimization on
1714 * readv if the caller asked for it.
1716 * This is needed because in most cases
1717 * we preferr to flush send buffers before
1718 * receiving incoming requests.
1720 tstream_bsd_readv_handler(req
);
1721 if (!tevent_req_is_in_progress(req
)) {
1726 ret
= tstream_bsd_set_readable_handler(bsds
, ev
,
1727 tstream_bsd_readv_handler
,
1730 tevent_req_error(req
, errno
);
1737 tevent_req_post(req
, ev
);
1741 static void tstream_bsd_readv_handler(void *private_data
)
1743 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1745 struct tstream_bsd_readv_state
*state
= tevent_req_data(req
,
1746 struct tstream_bsd_readv_state
);
1747 struct tstream_context
*stream
= state
->stream
;
1748 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
1754 ret
= readv(bsds
->fd
, state
->vector
, state
->count
);
1756 /* propagate end of file */
1757 tevent_req_error(req
, EPIPE
);
1760 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1765 if (tevent_req_error(req
, err
)) {
1771 _count
= state
->count
; /* tstream has size_t count, readv has int */
1772 ok
= iov_advance(&state
->vector
, &_count
, ret
);
1773 state
->count
= _count
;
1776 tevent_req_error(req
, EINVAL
);
1780 if (state
->count
> 0) {
1781 /* we have more to read */
1785 tevent_req_done(req
);
1788 static int tstream_bsd_readv_recv(struct tevent_req
*req
,
1791 struct tstream_bsd_readv_state
*state
= tevent_req_data(req
,
1792 struct tstream_bsd_readv_state
);
1795 ret
= tsocket_simple_int_recv(req
, perrno
);
1800 tevent_req_received(req
);
1804 struct tstream_bsd_writev_state
{
1805 struct tstream_context
*stream
;
1807 struct iovec
*vector
;
1813 static int tstream_bsd_writev_destructor(struct tstream_bsd_writev_state
*state
)
1815 struct tstream_bsd
*bsds
= tstream_context_data(state
->stream
,
1816 struct tstream_bsd
);
1818 tstream_bsd_set_writeable_handler(bsds
, NULL
, NULL
, NULL
);
1823 static void tstream_bsd_writev_handler(void *private_data
);
1825 static struct tevent_req
*tstream_bsd_writev_send(TALLOC_CTX
*mem_ctx
,
1826 struct tevent_context
*ev
,
1827 struct tstream_context
*stream
,
1828 const struct iovec
*vector
,
1831 struct tevent_req
*req
;
1832 struct tstream_bsd_writev_state
*state
;
1833 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
1836 req
= tevent_req_create(mem_ctx
, &state
,
1837 struct tstream_bsd_writev_state
);
1842 state
->stream
= stream
;
1843 /* we make a copy of the vector so that we can modify it */
1844 state
->vector
= talloc_array(state
, struct iovec
, count
);
1845 if (tevent_req_nomem(state
->vector
, req
)) {
1848 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
1849 state
->count
= count
;
1852 talloc_set_destructor(state
, tstream_bsd_writev_destructor
);
1854 if (bsds
->fd
== -1) {
1855 tevent_req_error(req
, ENOTCONN
);
1860 * this is a fast path, not waiting for the
1861 * socket to become explicit writeable gains
1862 * about 10%-20% performance in benchmark tests.
1864 tstream_bsd_writev_handler(req
);
1865 if (!tevent_req_is_in_progress(req
)) {
1869 ret
= tstream_bsd_set_writeable_handler(bsds
, ev
,
1870 tstream_bsd_writev_handler
,
1873 tevent_req_error(req
, errno
);
1880 tevent_req_post(req
, ev
);
1884 static void tstream_bsd_writev_handler(void *private_data
)
1886 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1888 struct tstream_bsd_writev_state
*state
= tevent_req_data(req
,
1889 struct tstream_bsd_writev_state
);
1890 struct tstream_context
*stream
= state
->stream
;
1891 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
1897 ret
= writev(bsds
->fd
, state
->vector
, state
->count
);
1899 /* propagate end of file */
1900 tevent_req_error(req
, EPIPE
);
1903 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1908 if (tevent_req_error(req
, err
)) {
1914 _count
= state
->count
; /* tstream has size_t count, writev has int */
1915 ok
= iov_advance(&state
->vector
, &_count
, ret
);
1916 state
->count
= _count
;
1919 tevent_req_error(req
, EINVAL
);
1923 if (state
->count
> 0) {
1924 /* we have more to read */
1928 tevent_req_done(req
);
1931 static int tstream_bsd_writev_recv(struct tevent_req
*req
, int *perrno
)
1933 struct tstream_bsd_writev_state
*state
= tevent_req_data(req
,
1934 struct tstream_bsd_writev_state
);
1937 ret
= tsocket_simple_int_recv(req
, perrno
);
1942 tevent_req_received(req
);
1946 struct tstream_bsd_disconnect_state
{
1950 static struct tevent_req
*tstream_bsd_disconnect_send(TALLOC_CTX
*mem_ctx
,
1951 struct tevent_context
*ev
,
1952 struct tstream_context
*stream
)
1954 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
1955 struct tevent_req
*req
;
1956 struct tstream_bsd_disconnect_state
*state
;
1961 req
= tevent_req_create(mem_ctx
, &state
,
1962 struct tstream_bsd_disconnect_state
);
1967 if (bsds
->fd
== -1) {
1968 tevent_req_error(req
, ENOTCONN
);
1972 TALLOC_FREE(bsds
->fde
);
1973 ret
= close(bsds
->fd
);
1975 err
= tsocket_bsd_error_from_errno(ret
, errno
, &dummy
);
1976 if (tevent_req_error(req
, err
)) {
1980 tevent_req_done(req
);
1982 tevent_req_post(req
, ev
);
1986 static int tstream_bsd_disconnect_recv(struct tevent_req
*req
,
1991 ret
= tsocket_simple_int_recv(req
, perrno
);
1993 tevent_req_received(req
);
1997 static const struct tstream_context_ops tstream_bsd_ops
= {
2000 .pending_bytes
= tstream_bsd_pending_bytes
,
2002 .readv_send
= tstream_bsd_readv_send
,
2003 .readv_recv
= tstream_bsd_readv_recv
,
2005 .writev_send
= tstream_bsd_writev_send
,
2006 .writev_recv
= tstream_bsd_writev_recv
,
2008 .disconnect_send
= tstream_bsd_disconnect_send
,
2009 .disconnect_recv
= tstream_bsd_disconnect_recv
,
2012 static int tstream_bsd_destructor(struct tstream_bsd
*bsds
)
2014 TALLOC_FREE(bsds
->fde
);
2015 if (bsds
->fd
!= -1) {
2022 int _tstream_bsd_existing_socket(TALLOC_CTX
*mem_ctx
,
2024 struct tstream_context
**_stream
,
2025 const char *location
)
2027 struct tstream_context
*stream
;
2028 struct tstream_bsd
*bsds
;
2030 stream
= tstream_context_create(mem_ctx
,
2040 talloc_set_destructor(bsds
, tstream_bsd_destructor
);
2046 struct tstream_bsd_connect_state
{
2048 struct tevent_fd
*fde
;
2049 struct tstream_conext
*stream
;
2050 struct tsocket_address
*local
;
2053 static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state
*state
)
2055 TALLOC_FREE(state
->fde
);
2056 if (state
->fd
!= -1) {
2064 static void tstream_bsd_connect_fde_handler(struct tevent_context
*ev
,
2065 struct tevent_fd
*fde
,
2067 void *private_data
);
2069 static struct tevent_req
*tstream_bsd_connect_send(TALLOC_CTX
*mem_ctx
,
2070 struct tevent_context
*ev
,
2072 const struct tsocket_address
*local
,
2073 const struct tsocket_address
*remote
)
2075 struct tevent_req
*req
;
2076 struct tstream_bsd_connect_state
*state
;
2077 struct tsocket_address_bsd
*lbsda
=
2078 talloc_get_type_abort(local
->private_data
,
2079 struct tsocket_address_bsd
);
2080 struct tsocket_address_bsd
*lrbsda
= NULL
;
2081 struct tsocket_address_bsd
*rbsda
=
2082 talloc_get_type_abort(remote
->private_data
,
2083 struct tsocket_address_bsd
);
2087 bool do_bind
= false;
2088 bool do_reuseaddr
= false;
2089 bool do_ipv6only
= false;
2090 bool is_inet
= false;
2091 int sa_fam
= lbsda
->u
.sa
.sa_family
;
2093 req
= tevent_req_create(mem_ctx
, &state
,
2094 struct tstream_bsd_connect_state
);
2101 talloc_set_destructor(state
, tstream_bsd_connect_destructor
);
2103 /* give the wrappers a chance to report an error */
2104 if (sys_errno
!= 0) {
2105 tevent_req_error(req
, sys_errno
);
2109 switch (lbsda
->u
.sa
.sa_family
) {
2111 if (lbsda
->u
.un
.sun_path
[0] != 0) {
2112 do_reuseaddr
= true;
2117 if (lbsda
->u
.in
.sin_port
!= 0) {
2118 do_reuseaddr
= true;
2121 if (lbsda
->u
.in
.sin_addr
.s_addr
!= INADDR_ANY
) {
2128 if (lbsda
->u
.in6
.sin6_port
!= 0) {
2129 do_reuseaddr
= true;
2132 if (memcmp(&in6addr_any
,
2133 &lbsda
->u
.in6
.sin6_addr
,
2134 sizeof(in6addr_any
)) != 0) {
2142 tevent_req_error(req
, EINVAL
);
2146 if (!do_bind
&& is_inet
) {
2147 sa_fam
= rbsda
->u
.sa
.sa_family
;
2150 do_ipv6only
= false;
2161 state
->local
= tsocket_address_create(state
,
2162 &tsocket_address_bsd_ops
,
2164 struct tsocket_address_bsd
,
2165 __location__
"bsd_connect");
2166 if (tevent_req_nomem(state
->local
, req
)) {
2170 ZERO_STRUCTP(lrbsda
);
2171 lrbsda
->sa_socklen
= sizeof(lrbsda
->u
.ss
);
2172 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2173 lrbsda
->u
.sa
.sa_len
= lrbsda
->sa_socklen
;
2177 state
->fd
= socket(sa_fam
, SOCK_STREAM
, 0);
2178 if (state
->fd
== -1) {
2179 tevent_req_error(req
, errno
);
2183 state
->fd
= tsocket_bsd_common_prepare_fd(state
->fd
, true);
2184 if (state
->fd
== -1) {
2185 tevent_req_error(req
, errno
);
2193 ret
= setsockopt(state
->fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
2194 (const void *)&val
, sizeof(val
));
2196 tevent_req_error(req
, errno
);
2205 ret
= setsockopt(state
->fd
, SOL_SOCKET
, SO_REUSEADDR
,
2206 (const void *)&val
, sizeof(val
));
2208 tevent_req_error(req
, errno
);
2214 ret
= bind(state
->fd
, &lbsda
->u
.sa
, lbsda
->sa_socklen
);
2216 tevent_req_error(req
, errno
);
2221 if (rbsda
->u
.sa
.sa_family
!= sa_fam
) {
2222 tevent_req_error(req
, EINVAL
);
2226 ret
= connect(state
->fd
, &rbsda
->u
.sa
, rbsda
->sa_socklen
);
2227 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
2232 if (tevent_req_error(req
, err
)) {
2236 if (!state
->local
) {
2237 tevent_req_done(req
);
2241 ret
= getsockname(state
->fd
, &lrbsda
->u
.sa
, &lrbsda
->sa_socklen
);
2243 tevent_req_error(req
, errno
);
2247 tevent_req_done(req
);
2251 state
->fde
= tevent_add_fd(ev
, state
,
2253 TEVENT_FD_READ
| TEVENT_FD_WRITE
,
2254 tstream_bsd_connect_fde_handler
,
2256 if (tevent_req_nomem(state
->fde
, req
)) {
2263 tevent_req_post(req
, ev
);
2267 static void tstream_bsd_connect_fde_handler(struct tevent_context
*ev
,
2268 struct tevent_fd
*fde
,
2272 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
2274 struct tstream_bsd_connect_state
*state
= tevent_req_data(req
,
2275 struct tstream_bsd_connect_state
);
2276 struct tsocket_address_bsd
*lrbsda
= NULL
;
2279 socklen_t len
= sizeof(error
);
2283 ret
= getsockopt(state
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
);
2290 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
2295 if (tevent_req_error(req
, err
)) {
2299 if (!state
->local
) {
2300 tevent_req_done(req
);
2304 lrbsda
= talloc_get_type_abort(state
->local
->private_data
,
2305 struct tsocket_address_bsd
);
2307 ret
= getsockname(state
->fd
, &lrbsda
->u
.sa
, &lrbsda
->sa_socklen
);
2309 tevent_req_error(req
, errno
);
2313 tevent_req_done(req
);
2316 static int tstream_bsd_connect_recv(struct tevent_req
*req
,
2318 TALLOC_CTX
*mem_ctx
,
2319 struct tstream_context
**stream
,
2320 struct tsocket_address
**local
,
2321 const char *location
)
2323 struct tstream_bsd_connect_state
*state
= tevent_req_data(req
,
2324 struct tstream_bsd_connect_state
);
2327 ret
= tsocket_simple_int_recv(req
, perrno
);
2329 ret
= _tstream_bsd_existing_socket(mem_ctx
,
2337 TALLOC_FREE(state
->fde
);
2341 *local
= talloc_move(mem_ctx
, &state
->local
);
2346 tevent_req_received(req
);
2350 struct tevent_req
* tstream_inet_tcp_connect_send(TALLOC_CTX
*mem_ctx
,
2351 struct tevent_context
*ev
,
2352 const struct tsocket_address
*local
,
2353 const struct tsocket_address
*remote
)
2355 struct tsocket_address_bsd
*lbsda
=
2356 talloc_get_type_abort(local
->private_data
,
2357 struct tsocket_address_bsd
);
2358 struct tevent_req
*req
;
2361 switch (lbsda
->u
.sa
.sa_family
) {
2373 req
= tstream_bsd_connect_send(mem_ctx
, ev
, sys_errno
, local
, remote
);
2378 int _tstream_inet_tcp_connect_recv(struct tevent_req
*req
,
2380 TALLOC_CTX
*mem_ctx
,
2381 struct tstream_context
**stream
,
2382 struct tsocket_address
**local
,
2383 const char *location
)
2385 return tstream_bsd_connect_recv(req
, perrno
,
2386 mem_ctx
, stream
, local
,
2390 struct tevent_req
* tstream_unix_connect_send(TALLOC_CTX
*mem_ctx
,
2391 struct tevent_context
*ev
,
2392 const struct tsocket_address
*local
,
2393 const struct tsocket_address
*remote
)
2395 struct tsocket_address_bsd
*lbsda
=
2396 talloc_get_type_abort(local
->private_data
,
2397 struct tsocket_address_bsd
);
2398 struct tevent_req
*req
;
2401 switch (lbsda
->u
.sa
.sa_family
) {
2409 req
= tstream_bsd_connect_send(mem_ctx
, ev
, sys_errno
, local
, remote
);
2414 int _tstream_unix_connect_recv(struct tevent_req
*req
,
2416 TALLOC_CTX
*mem_ctx
,
2417 struct tstream_context
**stream
,
2418 const char *location
)
2420 return tstream_bsd_connect_recv(req
, perrno
,
2421 mem_ctx
, stream
, NULL
,
2425 int _tstream_unix_socketpair(TALLOC_CTX
*mem_ctx1
,
2426 struct tstream_context
**_stream1
,
2427 TALLOC_CTX
*mem_ctx2
,
2428 struct tstream_context
**_stream2
,
2429 const char *location
)
2435 struct tstream_context
*stream1
= NULL
;
2436 struct tstream_context
*stream2
= NULL
;
2438 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
);
2445 fd1
= tsocket_bsd_common_prepare_fd(fd1
, true);
2447 int sys_errno
= errno
;
2453 fd2
= tsocket_bsd_common_prepare_fd(fd2
, true);
2455 int sys_errno
= errno
;
2461 ret
= _tstream_bsd_existing_socket(mem_ctx1
,
2466 int sys_errno
= errno
;
2473 ret
= _tstream_bsd_existing_socket(mem_ctx2
,
2478 int sys_errno
= errno
;
2479 talloc_free(stream1
);
2485 *_stream1
= stream1
;
2486 *_stream2
= stream2
;