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"
30 #include "lib/util/blocking.h"
31 #include "lib/util/util_net.h"
32 #include "lib/util/samba_util.h"
34 static int tsocket_bsd_error_from_errno(int ret
,
52 if (sys_errno
== EINTR
) {
57 if (sys_errno
== EINPROGRESS
) {
62 if (sys_errno
== EAGAIN
) {
67 /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
68 if (sys_errno
== ENOMEM
) {
74 if (sys_errno
== EWOULDBLOCK
) {
83 static int tsocket_bsd_common_prepare_fd(int fd
, bool high_fd
)
97 /* first make a fd >= 3 */
107 for (i
=0; i
<num_fds
; i
++) {
116 result
= set_blocking(fd
, false);
121 ok
= smb_set_close_on_exec(fd
);
137 #ifdef HAVE_LINUX_RTNETLINK_H
139 * Get the amount of pending bytes from a netlink socket
141 * For some reason netlink sockets don't support querying the amount of pending
142 * data via ioctl with FIONREAD, which is what we use in tsocket_bsd_pending()
145 * We know we are on Linux as we're using netlink, which means we have a working
146 * MSG_TRUNC flag to recvmsg() as well, so we use that together with MSG_PEEK.
148 static ssize_t
tsocket_bsd_netlink_pending(int fd
)
154 iov
= (struct iovec
) {
156 .iov_len
= sizeof(buf
)
159 msg
= (struct msghdr
) {
164 return recvmsg(fd
, &msg
, MSG_PEEK
| MSG_TRUNC
);
167 static ssize_t
tsocket_bsd_netlink_pending(int fd
)
174 static ssize_t
tsocket_bsd_pending(int fd
)
179 ret
= ioctl(fd
, FIONREAD
, &value
);
185 /* this should not be reached */
194 return samba_socket_poll_or_sock_error(fd
);
197 static const struct tsocket_address_ops tsocket_address_bsd_ops
;
199 int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX
*mem_ctx
,
200 const struct sockaddr
*sa
,
202 struct tsocket_address
**_addr
,
203 const char *location
)
205 struct tsocket_address
*addr
;
206 struct samba_sockaddr
*bsda
= NULL
;
208 if (sa_socklen
< sizeof(sa
->sa_family
)) {
213 switch (sa
->sa_family
) {
215 if (sa_socklen
> sizeof(struct sockaddr_un
)) {
216 sa_socklen
= sizeof(struct sockaddr_un
);
220 if (sa_socklen
< sizeof(struct sockaddr_in
)) {
224 sa_socklen
= sizeof(struct sockaddr_in
);
228 if (sa_socklen
< sizeof(struct sockaddr_in6
)) {
232 sa_socklen
= sizeof(struct sockaddr_in6
);
236 errno
= EAFNOSUPPORT
;
240 if (sa_socklen
> sizeof(struct sockaddr_storage
)) {
245 addr
= tsocket_address_create(mem_ctx
,
246 &tsocket_address_bsd_ops
,
248 struct samba_sockaddr
,
257 memcpy(&bsda
->u
.ss
, sa
, sa_socklen
);
259 bsda
->sa_socklen
= sa_socklen
;
260 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
261 bsda
->u
.sa
.sa_len
= bsda
->sa_socklen
;
268 int _tsocket_address_bsd_from_samba_sockaddr(TALLOC_CTX
*mem_ctx
,
269 const struct samba_sockaddr
*xs_addr
,
270 struct tsocket_address
**t_addr
,
271 const char *location
)
273 return _tsocket_address_bsd_from_sockaddr(mem_ctx
,
280 ssize_t
tsocket_address_bsd_sockaddr(const struct tsocket_address
*addr
,
284 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
285 struct samba_sockaddr
);
292 if (sa_socklen
< bsda
->sa_socklen
) {
297 if (sa_socklen
> bsda
->sa_socklen
) {
298 memset(sa
, 0, sa_socklen
);
299 sa_socklen
= bsda
->sa_socklen
;
302 memcpy(sa
, &bsda
->u
.ss
, sa_socklen
);
303 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
304 sa
->sa_len
= sa_socklen
;
309 bool tsocket_address_is_inet(const struct tsocket_address
*addr
, const char *fam
)
311 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
312 struct samba_sockaddr
);
318 switch (bsda
->u
.sa
.sa_family
) {
320 if (strcasecmp(fam
, "ip") == 0) {
324 if (strcasecmp(fam
, "ipv4") == 0) {
331 if (strcasecmp(fam
, "ip") == 0) {
335 if (strcasecmp(fam
, "ipv6") == 0) {
346 int _tsocket_address_inet_from_strings(TALLOC_CTX
*mem_ctx
,
350 struct tsocket_address
**_addr
,
351 const char *location
)
353 struct addrinfo hints
;
354 struct addrinfo
*result
= NULL
;
360 * we use SOCKET_STREAM here to get just one result
361 * back from getaddrinfo().
363 hints
.ai_socktype
= SOCK_STREAM
;
364 hints
.ai_flags
= AI_NUMERICHOST
| AI_NUMERICSERV
;
366 if (strcasecmp(fam
, "ip") == 0) {
367 hints
.ai_family
= AF_UNSPEC
;
375 } else if (strcasecmp(fam
, "ipv4") == 0) {
376 hints
.ai_family
= AF_INET
;
381 } else if (strcasecmp(fam
, "ipv6") == 0) {
382 hints
.ai_family
= AF_INET6
;
388 errno
= EAFNOSUPPORT
;
392 snprintf(port_str
, sizeof(port_str
), "%u", port
);
394 ret
= getaddrinfo(addr
, port_str
, &hints
, &result
);
399 #ifdef EAI_ADDRFAMILY
409 if (result
->ai_socktype
!= SOCK_STREAM
) {
415 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
423 freeaddrinfo(result
);
428 int _tsocket_address_inet_from_hostport_strings(TALLOC_CTX
*mem_ctx
,
430 const char *host_port_addr
,
431 uint16_t default_port
,
432 struct tsocket_address
**_addr
,
433 const char *location
)
437 char *pl_period
= NULL
;
438 char *port_sep
= NULL
;
444 uint16_t s_port
= default_port
;
446 bool is_ipv6_by_squares
= false;
448 if (host_port_addr
== NULL
) {
449 /* got straight to next function if host_port_addr is NULL */
452 buf
= talloc_strdup(mem_ctx
, host_port_addr
);
457 pl_period
= strchr_m(buf
, '.');
458 port_sep
= strrchr_m(buf
, ':');
459 pl_sq
= strchr_m(buf
, '[');
460 pr_sq
= strrchr_m(buf
, ']');
461 /* See if its IPv4 or IPv6 */
462 /* Only parse IPv6 with squares with/without port, and IPv4 with port */
463 /* Everything else, let tsocket_address_inet_from string() */
464 /* find parsing errors */
466 is_ipv6_by_squares
= (pl_sq
!= NULL
&& pr_sq
!= NULL
&& pr_sq
> pl_sq
);
468 if (is_ipv6_by_squares
) {
469 /* IPv6 possibly with port - squares detected */
470 port_sep
= pr_sq
+ 1;
471 if (*port_sep
== '\0') {
474 s_port
= default_port
;
477 if (*port_sep
!= ':') {
481 cport
= port_sep
+ 1;
482 conv_ret
= conv_str_u64(cport
, &port
);
491 s_port
= (uint16_t)port
;
497 } else if (pl_period
!= NULL
&& port_sep
!= NULL
) {
498 /* IPv4 with port - more than one period in string */
499 cport
= port_sep
+ 1;
500 conv_ret
= conv_str_u64(cport
, &port
);
509 s_port
= (uint16_t)port
;
514 /* Everything else, let tsocket_address_inet_from string() */
515 /* find parsing errors */
517 s_port
= default_port
;
521 ret
= _tsocket_address_inet_from_strings(
522 mem_ctx
, fam
, s_addr
, s_port
, _addr
, location
);
527 char *tsocket_address_inet_addr_string(const struct tsocket_address
*addr
,
530 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
531 struct samba_sockaddr
);
532 char addr_str
[INET6_ADDRSTRLEN
+1];
540 switch (bsda
->u
.sa
.sa_family
) {
542 str
= inet_ntop(bsda
->u
.in
.sin_family
,
543 &bsda
->u
.in
.sin_addr
,
544 addr_str
, sizeof(addr_str
));
548 str
= inet_ntop(bsda
->u
.in6
.sin6_family
,
549 &bsda
->u
.in6
.sin6_addr
,
550 addr_str
, sizeof(addr_str
));
562 return talloc_strdup(mem_ctx
, str
);
565 uint16_t tsocket_address_inet_port(const struct tsocket_address
*addr
)
567 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
568 struct samba_sockaddr
);
576 switch (bsda
->u
.sa
.sa_family
) {
578 port
= ntohs(bsda
->u
.in
.sin_port
);
582 port
= ntohs(bsda
->u
.in6
.sin6_port
);
593 int tsocket_address_inet_set_port(struct tsocket_address
*addr
,
596 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
597 struct samba_sockaddr
);
604 switch (bsda
->u
.sa
.sa_family
) {
606 bsda
->u
.in
.sin_port
= htons(port
);
610 bsda
->u
.in6
.sin6_port
= htons(port
);
621 bool tsocket_address_is_unix(const struct tsocket_address
*addr
)
623 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
624 struct samba_sockaddr
);
630 switch (bsda
->u
.sa
.sa_family
) {
638 int _tsocket_address_unix_from_path(TALLOC_CTX
*mem_ctx
,
640 struct tsocket_address
**_addr
,
641 const char *location
)
643 struct sockaddr_un un
;
651 if (strlen(path
) > sizeof(un
.sun_path
)-1) {
652 errno
= ENAMETOOLONG
;
657 un
.sun_family
= AF_UNIX
;
658 strncpy(un
.sun_path
, path
, sizeof(un
.sun_path
)-1);
660 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
661 (struct sockaddr
*)p
,
669 char *tsocket_address_unix_path(const struct tsocket_address
*addr
,
672 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
673 struct samba_sockaddr
);
681 switch (bsda
->u
.sa
.sa_family
) {
683 str
= bsda
->u
.un
.sun_path
;
690 return talloc_strdup(mem_ctx
, str
);
693 static char *tsocket_address_bsd_string(const struct tsocket_address
*addr
,
696 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
697 struct samba_sockaddr
);
700 const char *prefix
= NULL
;
703 switch (bsda
->u
.sa
.sa_family
) {
705 return talloc_asprintf(mem_ctx
, "unix:%s",
706 bsda
->u
.un
.sun_path
);
720 addr_str
= tsocket_address_inet_addr_string(addr
, mem_ctx
);
725 port
= tsocket_address_inet_port(addr
);
727 str
= talloc_asprintf(mem_ctx
, "%s:%s:%u",
728 prefix
, addr_str
, port
);
729 talloc_free(addr_str
);
734 static struct tsocket_address
*tsocket_address_bsd_copy(const struct tsocket_address
*addr
,
736 const char *location
)
738 struct samba_sockaddr
*bsda
= talloc_get_type(addr
->private_data
,
739 struct samba_sockaddr
);
740 struct tsocket_address
*copy
;
743 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
755 static const struct tsocket_address_ops tsocket_address_bsd_ops
= {
757 .string
= tsocket_address_bsd_string
,
758 .copy
= tsocket_address_bsd_copy
,
765 struct tevent_fd
*fde
;
766 bool optimize_recvfrom
;
769 void *readable_private
;
770 void (*readable_handler
)(void *private_data
);
771 void *writeable_private
;
772 void (*writeable_handler
)(void *private_data
);
775 bool tdgram_bsd_optimize_recvfrom(struct tdgram_context
*dgram
,
778 struct tdgram_bsd
*bsds
=
779 talloc_get_type(_tdgram_context_data(dgram
),
784 /* not a bsd socket */
788 old
= bsds
->optimize_recvfrom
;
789 bsds
->optimize_recvfrom
= on
;
794 static void tdgram_bsd_fde_handler(struct tevent_context
*ev
,
795 struct tevent_fd
*fde
,
799 struct tdgram_bsd
*bsds
= talloc_get_type_abort(private_data
,
802 if (flags
& TEVENT_FD_WRITE
) {
803 bsds
->writeable_handler(bsds
->writeable_private
);
806 if (flags
& TEVENT_FD_READ
) {
807 if (!bsds
->readable_handler
) {
808 TEVENT_FD_NOT_READABLE(bsds
->fde
);
811 bsds
->readable_handler(bsds
->readable_private
);
816 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd
*bsds
,
817 struct tevent_context
*ev
,
818 void (*handler
)(void *private_data
),
826 if (!bsds
->readable_handler
) {
829 bsds
->readable_handler
= NULL
;
830 bsds
->readable_private
= NULL
;
835 /* read and write must use the same tevent_context */
836 if (bsds
->event_ptr
!= ev
) {
837 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
841 bsds
->event_ptr
= NULL
;
842 TALLOC_FREE(bsds
->fde
);
845 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
846 TALLOC_FREE(bsds
->fde
);
848 bsds
->fde
= tevent_add_fd(ev
, bsds
,
849 bsds
->fd
, TEVENT_FD_READ
,
850 tdgram_bsd_fde_handler
,
857 /* cache the event context we're running on */
858 bsds
->event_ptr
= ev
;
859 } else if (!bsds
->readable_handler
) {
860 TEVENT_FD_READABLE(bsds
->fde
);
863 bsds
->readable_handler
= handler
;
864 bsds
->readable_private
= private_data
;
869 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd
*bsds
,
870 struct tevent_context
*ev
,
871 void (*handler
)(void *private_data
),
879 if (!bsds
->writeable_handler
) {
882 bsds
->writeable_handler
= NULL
;
883 bsds
->writeable_private
= NULL
;
884 TEVENT_FD_NOT_WRITEABLE(bsds
->fde
);
889 /* read and write must use the same tevent_context */
890 if (bsds
->event_ptr
!= ev
) {
891 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
895 bsds
->event_ptr
= NULL
;
896 TALLOC_FREE(bsds
->fde
);
899 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
900 TALLOC_FREE(bsds
->fde
);
902 bsds
->fde
= tevent_add_fd(ev
, bsds
,
903 bsds
->fd
, TEVENT_FD_WRITE
,
904 tdgram_bsd_fde_handler
,
911 /* cache the event context we're running on */
912 bsds
->event_ptr
= ev
;
913 } else if (!bsds
->writeable_handler
) {
914 TEVENT_FD_WRITEABLE(bsds
->fde
);
917 bsds
->writeable_handler
= handler
;
918 bsds
->writeable_private
= private_data
;
923 struct tdgram_bsd_recvfrom_state
{
924 struct tdgram_context
*dgram
;
928 struct tsocket_address
*src
;
931 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state
*state
)
933 struct tdgram_bsd
*bsds
= tdgram_context_data(state
->dgram
,
936 tdgram_bsd_set_readable_handler(bsds
, NULL
, NULL
, NULL
);
941 static void tdgram_bsd_recvfrom_handler(void *private_data
);
943 static struct tevent_req
*tdgram_bsd_recvfrom_send(TALLOC_CTX
*mem_ctx
,
944 struct tevent_context
*ev
,
945 struct tdgram_context
*dgram
)
947 struct tevent_req
*req
;
948 struct tdgram_bsd_recvfrom_state
*state
;
949 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
952 req
= tevent_req_create(mem_ctx
, &state
,
953 struct tdgram_bsd_recvfrom_state
);
958 state
->dgram
= dgram
;
959 state
->first_try
= true;
964 talloc_set_destructor(state
, tdgram_bsd_recvfrom_destructor
);
966 if (bsds
->fd
== -1) {
967 tevent_req_error(req
, ENOTCONN
);
973 * this is a fast path, not waiting for the
974 * socket to become explicit readable gains
975 * about 10%-20% performance in benchmark tests.
977 if (bsds
->optimize_recvfrom
) {
979 * We only do the optimization on
980 * recvfrom if the caller asked for it.
982 * This is needed because in most cases
983 * we prefer to flush send buffers before
984 * receiving incoming requests.
986 tdgram_bsd_recvfrom_handler(req
);
987 if (!tevent_req_is_in_progress(req
)) {
992 ret
= tdgram_bsd_set_readable_handler(bsds
, ev
,
993 tdgram_bsd_recvfrom_handler
,
996 tevent_req_error(req
, errno
);
1003 tevent_req_post(req
, ev
);
1007 static void tdgram_bsd_recvfrom_handler(void *private_data
)
1009 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1011 struct tdgram_bsd_recvfrom_state
*state
= tevent_req_data(req
,
1012 struct tdgram_bsd_recvfrom_state
);
1013 struct tdgram_context
*dgram
= state
->dgram
;
1014 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1015 struct samba_sockaddr
*bsda
= NULL
;
1020 if (bsds
->netlink
) {
1021 ret
= tsocket_bsd_netlink_pending(bsds
->fd
);
1023 ret
= tsocket_bsd_pending(bsds
->fd
);
1026 if (state
->first_try
&& ret
== 0) {
1027 state
->first_try
= false;
1031 state
->first_try
= false;
1033 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1038 if (tevent_req_error(req
, err
)) {
1042 /* note that 'ret' can be 0 here */
1043 state
->buf
= talloc_array(state
, uint8_t, ret
);
1044 if (tevent_req_nomem(state
->buf
, req
)) {
1049 state
->src
= tsocket_address_create(state
,
1050 &tsocket_address_bsd_ops
,
1052 struct samba_sockaddr
,
1053 __location__
"bsd_recvfrom");
1054 if (tevent_req_nomem(state
->src
, req
)) {
1059 bsda
->sa_socklen
= sizeof(bsda
->u
.ss
);
1060 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1061 bsda
->u
.sa
.sa_len
= bsda
->sa_socklen
;
1064 ret
= recvfrom(bsds
->fd
, state
->buf
, state
->len
, 0,
1065 &bsda
->u
.sa
, &bsda
->sa_socklen
);
1066 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1071 if (tevent_req_error(req
, err
)) {
1076 * Some systems (FreeBSD, see bug #7115) return too much
1077 * bytes in tsocket_bsd_pending()/ioctl(fd, FIONREAD, ...),
1078 * the return value includes some IP/UDP header bytes,
1079 * while recvfrom() just returns the payload.
1081 state
->buf
= talloc_realloc(state
, state
->buf
, uint8_t, ret
);
1082 if (tevent_req_nomem(state
->buf
, req
)) {
1087 tevent_req_done(req
);
1090 static ssize_t
tdgram_bsd_recvfrom_recv(struct tevent_req
*req
,
1092 TALLOC_CTX
*mem_ctx
,
1094 struct tsocket_address
**src
)
1096 struct tdgram_bsd_recvfrom_state
*state
= tevent_req_data(req
,
1097 struct tdgram_bsd_recvfrom_state
);
1100 ret
= tsocket_simple_int_recv(req
, perrno
);
1102 *buf
= talloc_move(mem_ctx
, &state
->buf
);
1105 *src
= talloc_move(mem_ctx
, &state
->src
);
1109 tevent_req_received(req
);
1113 struct tdgram_bsd_sendto_state
{
1114 struct tdgram_context
*dgram
;
1118 const struct tsocket_address
*dst
;
1123 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state
*state
)
1125 struct tdgram_bsd
*bsds
= tdgram_context_data(state
->dgram
,
1128 tdgram_bsd_set_writeable_handler(bsds
, NULL
, NULL
, NULL
);
1133 static void tdgram_bsd_sendto_handler(void *private_data
);
1135 static struct tevent_req
*tdgram_bsd_sendto_send(TALLOC_CTX
*mem_ctx
,
1136 struct tevent_context
*ev
,
1137 struct tdgram_context
*dgram
,
1140 const struct tsocket_address
*dst
)
1142 struct tevent_req
*req
;
1143 struct tdgram_bsd_sendto_state
*state
;
1144 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1147 req
= tevent_req_create(mem_ctx
, &state
,
1148 struct tdgram_bsd_sendto_state
);
1153 state
->dgram
= dgram
;
1159 talloc_set_destructor(state
, tdgram_bsd_sendto_destructor
);
1161 if (bsds
->fd
== -1) {
1162 tevent_req_error(req
, ENOTCONN
);
1167 * this is a fast path, not waiting for the
1168 * socket to become explicit writeable gains
1169 * about 10%-20% performance in benchmark tests.
1171 tdgram_bsd_sendto_handler(req
);
1172 if (!tevent_req_is_in_progress(req
)) {
1176 ret
= tdgram_bsd_set_writeable_handler(bsds
, ev
,
1177 tdgram_bsd_sendto_handler
,
1180 tevent_req_error(req
, errno
);
1187 tevent_req_post(req
, ev
);
1191 static void tdgram_bsd_sendto_handler(void *private_data
)
1193 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1195 struct tdgram_bsd_sendto_state
*state
= tevent_req_data(req
,
1196 struct tdgram_bsd_sendto_state
);
1197 struct tdgram_context
*dgram
= state
->dgram
;
1198 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1199 struct sockaddr
*sa
= NULL
;
1200 socklen_t sa_socklen
= 0;
1206 struct samba_sockaddr
*bsda
=
1207 talloc_get_type(state
->dst
->private_data
,
1208 struct samba_sockaddr
);
1211 sa_socklen
= bsda
->sa_socklen
;
1214 ret
= sendto(bsds
->fd
, state
->buf
, state
->len
, 0, sa
, sa_socklen
);
1215 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1221 if (err
== EMSGSIZE
) {
1222 /* round up in 1K increments */
1223 int bufsize
= ((state
->len
+ 1023) & (~1023));
1225 ret
= setsockopt(bsds
->fd
, SOL_SOCKET
, SO_SNDBUF
, &bufsize
,
1229 * We do the retry here, rather then via the
1230 * handler, as we only want to retry once for
1231 * this condition, so if there is a mismatch
1232 * between what setsockopt() accepts and what can
1233 * actually be sent, we do not end up in a
1237 ret
= sendto(bsds
->fd
, state
->buf
, state
->len
,
1239 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1240 if (retry
) { /* retry later */
1246 if (tevent_req_error(req
, err
)) {
1252 tevent_req_done(req
);
1255 static ssize_t
tdgram_bsd_sendto_recv(struct tevent_req
*req
, int *perrno
)
1257 struct tdgram_bsd_sendto_state
*state
= tevent_req_data(req
,
1258 struct tdgram_bsd_sendto_state
);
1261 ret
= tsocket_simple_int_recv(req
, perrno
);
1266 tevent_req_received(req
);
1270 struct tdgram_bsd_disconnect_state
{
1274 static struct tevent_req
*tdgram_bsd_disconnect_send(TALLOC_CTX
*mem_ctx
,
1275 struct tevent_context
*ev
,
1276 struct tdgram_context
*dgram
)
1278 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1279 struct tevent_req
*req
;
1280 struct tdgram_bsd_disconnect_state
*state
;
1285 req
= tevent_req_create(mem_ctx
, &state
,
1286 struct tdgram_bsd_disconnect_state
);
1291 if (bsds
->fd
== -1) {
1292 tevent_req_error(req
, ENOTCONN
);
1296 TALLOC_FREE(bsds
->fde
);
1297 ret
= close(bsds
->fd
);
1299 err
= tsocket_bsd_error_from_errno(ret
, errno
, &dummy
);
1300 if (tevent_req_error(req
, err
)) {
1304 tevent_req_done(req
);
1306 tevent_req_post(req
, ev
);
1310 static int tdgram_bsd_disconnect_recv(struct tevent_req
*req
,
1315 ret
= tsocket_simple_int_recv(req
, perrno
);
1317 tevent_req_received(req
);
1321 static const struct tdgram_context_ops tdgram_bsd_ops
= {
1324 .recvfrom_send
= tdgram_bsd_recvfrom_send
,
1325 .recvfrom_recv
= tdgram_bsd_recvfrom_recv
,
1327 .sendto_send
= tdgram_bsd_sendto_send
,
1328 .sendto_recv
= tdgram_bsd_sendto_recv
,
1330 .disconnect_send
= tdgram_bsd_disconnect_send
,
1331 .disconnect_recv
= tdgram_bsd_disconnect_recv
,
1334 static int tdgram_bsd_destructor(struct tdgram_bsd
*bsds
)
1336 TALLOC_FREE(bsds
->fde
);
1337 if (bsds
->fd
!= -1) {
1344 static int tdgram_bsd_dgram_socket(const struct tsocket_address
*local
,
1345 const struct tsocket_address
*remote
,
1347 TALLOC_CTX
*mem_ctx
,
1348 struct tdgram_context
**_dgram
,
1349 const char *location
)
1351 struct samba_sockaddr
*lbsda
=
1352 talloc_get_type_abort(local
->private_data
,
1353 struct samba_sockaddr
);
1354 struct samba_sockaddr
*rbsda
= NULL
;
1355 struct tdgram_context
*dgram
;
1356 struct tdgram_bsd
*bsds
;
1359 bool do_bind
= false;
1360 bool do_reuseaddr
= false;
1361 bool do_ipv6only
= false;
1362 bool is_inet
= false;
1363 int sa_fam
= lbsda
->u
.sa
.sa_family
;
1366 rbsda
= talloc_get_type_abort(remote
->private_data
,
1367 struct samba_sockaddr
);
1370 switch (lbsda
->u
.sa
.sa_family
) {
1376 if (lbsda
->u
.un
.sun_path
[0] != 0) {
1377 do_reuseaddr
= true;
1382 if (lbsda
->u
.in
.sin_port
!= 0) {
1383 do_reuseaddr
= true;
1386 if (lbsda
->u
.in
.sin_addr
.s_addr
!= INADDR_ANY
) {
1393 if (lbsda
->u
.in6
.sin6_port
!= 0) {
1394 do_reuseaddr
= true;
1397 if (memcmp(&in6addr_any
,
1398 &lbsda
->u
.in6
.sin6_addr
,
1399 sizeof(in6addr_any
)) != 0) {
1411 if (!do_bind
&& is_inet
&& rbsda
) {
1412 sa_fam
= rbsda
->u
.sa
.sa_family
;
1415 do_ipv6only
= false;
1425 fd
= socket(sa_fam
, SOCK_DGRAM
, 0);
1430 fd
= tsocket_bsd_common_prepare_fd(fd
, true);
1435 dgram
= tdgram_context_create(mem_ctx
,
1441 int saved_errno
= errno
;
1443 errno
= saved_errno
;
1448 talloc_set_destructor(bsds
, tdgram_bsd_destructor
);
1454 ret
= setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
1455 (const void *)&val
, sizeof(val
));
1457 int saved_errno
= errno
;
1459 errno
= saved_errno
;
1468 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
,
1469 (const void *)&val
, sizeof(val
));
1471 int saved_errno
= errno
;
1473 errno
= saved_errno
;
1481 ret
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
1482 (const void *)&val
, sizeof(val
));
1484 int saved_errno
= errno
;
1486 errno
= saved_errno
;
1492 ret
= bind(fd
, &lbsda
->u
.sa
, lbsda
->sa_socklen
);
1494 int saved_errno
= errno
;
1496 errno
= saved_errno
;
1502 if (rbsda
->u
.sa
.sa_family
!= sa_fam
) {
1508 ret
= connect(fd
, &rbsda
->u
.sa
, rbsda
->sa_socklen
);
1510 int saved_errno
= errno
;
1512 errno
= saved_errno
;
1521 int _tdgram_bsd_existing_socket(TALLOC_CTX
*mem_ctx
,
1523 struct tdgram_context
**_dgram
,
1524 const char *location
)
1526 struct tdgram_context
*dgram
;
1527 struct tdgram_bsd
*bsds
;
1528 #ifdef HAVE_LINUX_RTNETLINK_H
1531 socklen_t sa_len
= sizeof(struct sockaddr
);
1534 dgram
= tdgram_context_create(mem_ctx
,
1544 talloc_set_destructor(bsds
, tdgram_bsd_destructor
);
1548 #ifdef HAVE_LINUX_RTNETLINK_H
1550 * Try to determine the protocol family and remember if it's
1551 * AF_NETLINK. We don't care if this fails.
1553 result
= getsockname(fd
, &sa
, &sa_len
);
1554 if (result
== 0 && sa
.sa_family
== AF_NETLINK
) {
1555 bsds
->netlink
= true;
1562 int _tdgram_inet_udp_socket(const struct tsocket_address
*local
,
1563 const struct tsocket_address
*remote
,
1564 TALLOC_CTX
*mem_ctx
,
1565 struct tdgram_context
**dgram
,
1566 const char *location
)
1568 struct samba_sockaddr
*lbsda
=
1569 talloc_get_type_abort(local
->private_data
,
1570 struct samba_sockaddr
);
1573 switch (lbsda
->u
.sa
.sa_family
) {
1585 ret
= tdgram_bsd_dgram_socket(local
, remote
, false,
1586 mem_ctx
, dgram
, location
);
1591 int _tdgram_inet_udp_broadcast_socket(const struct tsocket_address
*local
,
1592 TALLOC_CTX
*mem_ctx
,
1593 struct tdgram_context
**dgram
,
1594 const char *location
)
1596 struct samba_sockaddr
*lbsda
=
1597 talloc_get_type_abort(local
->private_data
,
1598 struct samba_sockaddr
);
1601 switch (lbsda
->u
.sa
.sa_family
) {
1615 ret
= tdgram_bsd_dgram_socket(local
, NULL
, true,
1616 mem_ctx
, dgram
, location
);
1621 int _tdgram_unix_socket(const struct tsocket_address
*local
,
1622 const struct tsocket_address
*remote
,
1623 TALLOC_CTX
*mem_ctx
,
1624 struct tdgram_context
**dgram
,
1625 const char *location
)
1627 struct samba_sockaddr
*lbsda
=
1628 talloc_get_type_abort(local
->private_data
,
1629 struct samba_sockaddr
);
1632 switch (lbsda
->u
.sa
.sa_family
) {
1640 ret
= tdgram_bsd_dgram_socket(local
, remote
, false,
1641 mem_ctx
, dgram
, location
);
1646 struct tstream_bsd
{
1651 struct tevent_fd
*fde
;
1652 bool optimize_readv
;
1653 bool fail_readv_first_error
;
1655 void *readable_private
;
1656 void (*readable_handler
)(void *private_data
);
1657 void *writeable_private
;
1658 void (*writeable_handler
)(void *private_data
);
1661 bool tstream_bsd_optimize_readv(struct tstream_context
*stream
,
1664 struct tstream_bsd
*bsds
=
1665 talloc_get_type(_tstream_context_data(stream
),
1666 struct tstream_bsd
);
1670 /* not a bsd socket */
1674 old
= bsds
->optimize_readv
;
1675 bsds
->optimize_readv
= on
;
1680 bool tstream_bsd_fail_readv_first_error(struct tstream_context
*stream
,
1683 struct tstream_bsd
*bsds
=
1684 talloc_get_type(_tstream_context_data(stream
),
1685 struct tstream_bsd
);
1689 /* not a bsd socket */
1693 old
= bsds
->fail_readv_first_error
;
1694 bsds
->fail_readv_first_error
= on
;
1699 static void tstream_bsd_fde_handler(struct tevent_context
*ev
,
1700 struct tevent_fd
*fde
,
1704 struct tstream_bsd
*bsds
= talloc_get_type_abort(private_data
,
1705 struct tstream_bsd
);
1707 if (flags
& TEVENT_FD_ERROR
) {
1709 * We lazily keep TEVENT_FD_READ alive
1710 * in tstream_bsd_set_readable_handler()
1712 * So we have to check TEVENT_FD_READ
1713 * as well as bsds->readable_handler
1715 * We only drain remaining data from the
1716 * the recv queue if available and desired.
1718 if ((flags
& TEVENT_FD_READ
) &&
1719 !bsds
->fail_readv_first_error
&&
1720 (bsds
->readable_handler
!= NULL
))
1723 * If there's still data to read
1724 * we allow it to be read until
1725 * we reach EOF (=> EPIPE).
1727 bsds
->readable_handler(bsds
->readable_private
);
1732 * If there's no data left to read,
1735 * It means we no longer call any readv or
1736 * writev, as bsds->error is checked first.
1738 if (bsds
->error
== 0) {
1739 int ret
= samba_socket_poll_or_sock_error(bsds
->fd
);
1742 bsds
->error
= errno
;
1744 /* fallback to EPIPE */
1745 if (bsds
->error
== 0) {
1746 bsds
->error
= EPIPE
;
1751 * Let write to fail early.
1753 * Note we only need to check TEVENT_FD_WRITE
1754 * as tstream_bsd_set_writeable_handler()
1755 * clear it together with the handler.
1757 if (flags
& TEVENT_FD_WRITE
) {
1758 bsds
->writeable_handler(bsds
->writeable_private
);
1762 /* We prefer the readable handler to fire first. */
1763 if (bsds
->readable_handler
!= NULL
) {
1764 bsds
->readable_handler(bsds
->readable_private
);
1768 /* As last resort we notify the writeable handler */
1769 if (bsds
->writeable_handler
!= NULL
) {
1770 bsds
->writeable_handler(bsds
->writeable_private
);
1775 * We may hit this because we don't clear TEVENT_FD_ERROR
1776 * in tstream_bsd_set_readable_handler() nor
1777 * tstream_bsd_set_writeable_handler().
1779 * As we already captured the error, we can remove
1780 * the fde completely.
1782 TALLOC_FREE(bsds
->fde
);
1785 if (flags
& TEVENT_FD_WRITE
) {
1786 bsds
->writeable_handler(bsds
->writeable_private
);
1789 if (flags
& TEVENT_FD_READ
) {
1790 if (!bsds
->readable_handler
) {
1792 * tstream_bsd_set_readable_handler
1793 * doesn't clear TEVENT_FD_READ.
1795 * In order to avoid cpu-spinning
1796 * we need to clear it here.
1798 TEVENT_FD_NOT_READABLE(bsds
->fde
);
1801 * Here we're lazy and keep TEVENT_FD_ERROR
1802 * alive. If it's triggered the next time
1803 * we'll handle it gracefully above
1804 * and end up with TALLOC_FREE(bsds->fde);
1805 * in order to spin on TEVENT_FD_ERROR.
1809 bsds
->readable_handler(bsds
->readable_private
);
1814 static int tstream_bsd_set_readable_handler(struct tstream_bsd
*bsds
,
1815 struct tevent_context
*ev
,
1816 void (*handler
)(void *private_data
),
1824 if (!bsds
->readable_handler
) {
1827 bsds
->readable_handler
= NULL
;
1828 bsds
->readable_private
= NULL
;
1831 * Here we are lazy as it's very likely that the next
1832 * tevent_readv_send() will come in shortly,
1833 * so we keep TEVENT_FD_READ alive.
1838 /* read and write must use the same tevent_context */
1839 if (bsds
->event_ptr
!= ev
) {
1840 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
1844 bsds
->event_ptr
= NULL
;
1845 TALLOC_FREE(bsds
->fde
);
1848 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
1849 TALLOC_FREE(bsds
->fde
);
1851 bsds
->fde
= tevent_add_fd(ev
, bsds
,
1853 TEVENT_FD_ERROR
| TEVENT_FD_READ
,
1854 tstream_bsd_fde_handler
,
1861 /* cache the event context we're running on */
1862 bsds
->event_ptr
= ev
;
1863 } else if (!bsds
->readable_handler
) {
1864 TEVENT_FD_READABLE(bsds
->fde
);
1866 * TEVENT_FD_ERROR is likely already set, so
1867 * TEVENT_FD_WANTERROR() is most likely a no-op.
1869 TEVENT_FD_WANTERROR(bsds
->fde
);
1872 bsds
->readable_handler
= handler
;
1873 bsds
->readable_private
= private_data
;
1878 static int tstream_bsd_set_writeable_handler(struct tstream_bsd
*bsds
,
1879 struct tevent_context
*ev
,
1880 void (*handler
)(void *private_data
),
1888 if (!bsds
->writeable_handler
) {
1891 bsds
->writeable_handler
= NULL
;
1892 bsds
->writeable_private
= NULL
;
1895 * The writeable handler is only
1896 * set if we got EAGAIN or a short
1897 * writev on the first try, so
1898 * this isn't the hot path.
1900 * Here we are lazy and leave TEVENT_FD_ERROR
1901 * alive as it's shared with the readable
1902 * handler. So we only clear TEVENT_FD_WRITE.
1904 TEVENT_FD_NOT_WRITEABLE(bsds
->fde
);
1908 /* read and write must use the same tevent_context */
1909 if (bsds
->event_ptr
!= ev
) {
1910 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
1914 bsds
->event_ptr
= NULL
;
1915 TALLOC_FREE(bsds
->fde
);
1918 if (tevent_fd_get_flags(bsds
->fde
) == 0) {
1919 TALLOC_FREE(bsds
->fde
);
1921 bsds
->fde
= tevent_add_fd(ev
, bsds
,
1923 TEVENT_FD_ERROR
| TEVENT_FD_WRITE
,
1924 tstream_bsd_fde_handler
,
1931 /* cache the event context we're running on */
1932 bsds
->event_ptr
= ev
;
1933 } else if (!bsds
->writeable_handler
) {
1934 TEVENT_FD_WRITEABLE(bsds
->fde
);
1936 * TEVENT_FD_ERROR is likely already set, so
1937 * TEVENT_FD_WANTERROR() is most likely a no-op.
1939 TEVENT_FD_WANTERROR(bsds
->fde
);
1942 bsds
->writeable_handler
= handler
;
1943 bsds
->writeable_private
= private_data
;
1948 static ssize_t
tstream_bsd_pending_bytes(struct tstream_context
*stream
)
1950 struct tstream_bsd
*bsds
= tstream_context_data(stream
,
1951 struct tstream_bsd
);
1954 if (bsds
->fd
== -1) {
1959 if (bsds
->error
!= 0) {
1960 errno
= bsds
->error
;
1964 ret
= tsocket_bsd_pending(bsds
->fd
);
1967 * remember the error and don't
1968 * allow further requests
1970 bsds
->error
= errno
;
1976 struct tstream_bsd_readv_state
{
1977 struct tstream_context
*stream
;
1979 struct iovec
*vector
;
1985 static int tstream_bsd_readv_destructor(struct tstream_bsd_readv_state
*state
)
1987 struct tstream_bsd
*bsds
= tstream_context_data(state
->stream
,
1988 struct tstream_bsd
);
1990 tstream_bsd_set_readable_handler(bsds
, NULL
, NULL
, NULL
);
1995 static void tstream_bsd_readv_handler(void *private_data
);
1997 static struct tevent_req
*tstream_bsd_readv_send(TALLOC_CTX
*mem_ctx
,
1998 struct tevent_context
*ev
,
1999 struct tstream_context
*stream
,
2000 struct iovec
*vector
,
2003 struct tevent_req
*req
;
2004 struct tstream_bsd_readv_state
*state
;
2005 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
2008 req
= tevent_req_create(mem_ctx
, &state
,
2009 struct tstream_bsd_readv_state
);
2014 state
->stream
= stream
;
2015 /* we make a copy of the vector so that we can modify it */
2016 state
->vector
= talloc_array(state
, struct iovec
, count
);
2017 if (tevent_req_nomem(state
->vector
, req
)) {
2020 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
2021 state
->count
= count
;
2024 talloc_set_destructor(state
, tstream_bsd_readv_destructor
);
2026 if (bsds
->fd
== -1) {
2027 tevent_req_error(req
, ENOTCONN
);
2032 * this is a fast path, not waiting for the
2033 * socket to become explicit readable gains
2034 * about 10%-20% performance in benchmark tests.
2036 if (bsds
->optimize_readv
) {
2038 * We only do the optimization on
2039 * readv if the caller asked for it.
2041 * This is needed because in most cases
2042 * we prefer to flush send buffers before
2043 * receiving incoming requests.
2045 tstream_bsd_readv_handler(req
);
2046 if (!tevent_req_is_in_progress(req
)) {
2051 ret
= tstream_bsd_set_readable_handler(bsds
, ev
,
2052 tstream_bsd_readv_handler
,
2055 tevent_req_error(req
, errno
);
2062 tevent_req_post(req
, ev
);
2066 static void tstream_bsd_readv_handler(void *private_data
)
2068 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
2070 struct tstream_bsd_readv_state
*state
= tevent_req_data(req
,
2071 struct tstream_bsd_readv_state
);
2072 struct tstream_context
*stream
= state
->stream
;
2073 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
2079 if (bsds
->error
!= 0) {
2080 tevent_req_error(req
, bsds
->error
);
2084 ret
= readv(bsds
->fd
, state
->vector
, state
->count
);
2086 /* propagate end of file */
2087 bsds
->error
= EPIPE
;
2088 tevent_req_error(req
, EPIPE
);
2091 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
2098 * remember the error and don't
2099 * allow further requests
2103 if (tevent_req_error(req
, err
)) {
2109 _count
= state
->count
; /* tstream has size_t count, readv has int */
2110 ok
= iov_advance(&state
->vector
, &_count
, ret
);
2111 state
->count
= _count
;
2114 tevent_req_error(req
, EINVAL
);
2118 if (state
->count
> 0) {
2119 /* we have more to read */
2123 tevent_req_done(req
);
2126 static int tstream_bsd_readv_recv(struct tevent_req
*req
,
2129 struct tstream_bsd_readv_state
*state
= tevent_req_data(req
,
2130 struct tstream_bsd_readv_state
);
2133 ret
= tsocket_simple_int_recv(req
, perrno
);
2138 tevent_req_received(req
);
2142 struct tstream_bsd_writev_state
{
2143 struct tstream_context
*stream
;
2145 struct iovec
*vector
;
2151 static int tstream_bsd_writev_destructor(struct tstream_bsd_writev_state
*state
)
2153 struct tstream_bsd
*bsds
= tstream_context_data(state
->stream
,
2154 struct tstream_bsd
);
2156 tstream_bsd_set_writeable_handler(bsds
, NULL
, NULL
, NULL
);
2161 static void tstream_bsd_writev_handler(void *private_data
);
2163 static struct tevent_req
*tstream_bsd_writev_send(TALLOC_CTX
*mem_ctx
,
2164 struct tevent_context
*ev
,
2165 struct tstream_context
*stream
,
2166 const struct iovec
*vector
,
2169 struct tevent_req
*req
;
2170 struct tstream_bsd_writev_state
*state
;
2171 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
2174 req
= tevent_req_create(mem_ctx
, &state
,
2175 struct tstream_bsd_writev_state
);
2180 state
->stream
= stream
;
2181 /* we make a copy of the vector so that we can modify it */
2182 state
->vector
= talloc_array(state
, struct iovec
, count
);
2183 if (tevent_req_nomem(state
->vector
, req
)) {
2186 memcpy(state
->vector
, vector
, sizeof(struct iovec
)*count
);
2187 state
->count
= count
;
2190 talloc_set_destructor(state
, tstream_bsd_writev_destructor
);
2192 if (bsds
->fd
== -1) {
2193 tevent_req_error(req
, ENOTCONN
);
2198 * this is a fast path, not waiting for the
2199 * socket to become explicit writeable gains
2200 * about 10%-20% performance in benchmark tests.
2202 tstream_bsd_writev_handler(req
);
2203 if (!tevent_req_is_in_progress(req
)) {
2207 ret
= tstream_bsd_set_writeable_handler(bsds
, ev
,
2208 tstream_bsd_writev_handler
,
2211 tevent_req_error(req
, errno
);
2218 tevent_req_post(req
, ev
);
2222 static void tstream_bsd_writev_handler(void *private_data
)
2224 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
2226 struct tstream_bsd_writev_state
*state
= tevent_req_data(req
,
2227 struct tstream_bsd_writev_state
);
2228 struct tstream_context
*stream
= state
->stream
;
2229 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
2235 if (bsds
->error
!= 0) {
2236 tevent_req_error(req
, bsds
->error
);
2240 ret
= writev(bsds
->fd
, state
->vector
, state
->count
);
2242 /* propagate end of file */
2243 bsds
->error
= EPIPE
;
2244 tevent_req_error(req
, EPIPE
);
2247 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
2256 * remember the error and don't
2257 * allow further requests
2261 if (tevent_req_error(req
, err
)) {
2267 _count
= state
->count
; /* tstream has size_t count, writev has int */
2268 ok
= iov_advance(&state
->vector
, &_count
, ret
);
2269 state
->count
= _count
;
2272 tevent_req_error(req
, EINVAL
);
2276 if (state
->count
> 0) {
2278 * we have more to write
2283 tevent_req_done(req
);
2286 static int tstream_bsd_writev_recv(struct tevent_req
*req
, int *perrno
)
2288 struct tstream_bsd_writev_state
*state
= tevent_req_data(req
,
2289 struct tstream_bsd_writev_state
);
2292 ret
= tsocket_simple_int_recv(req
, perrno
);
2297 tevent_req_received(req
);
2301 struct tstream_bsd_disconnect_state
{
2305 static struct tevent_req
*tstream_bsd_disconnect_send(TALLOC_CTX
*mem_ctx
,
2306 struct tevent_context
*ev
,
2307 struct tstream_context
*stream
)
2309 struct tstream_bsd
*bsds
= tstream_context_data(stream
, struct tstream_bsd
);
2310 struct tevent_req
*req
;
2311 struct tstream_bsd_disconnect_state
*state
;
2316 req
= tevent_req_create(mem_ctx
, &state
,
2317 struct tstream_bsd_disconnect_state
);
2322 if (bsds
->fd
== -1) {
2323 tevent_req_error(req
, ENOTCONN
);
2327 TALLOC_FREE(bsds
->fde
);
2328 ret
= close(bsds
->fd
);
2330 err
= tsocket_bsd_error_from_errno(ret
, errno
, &dummy
);
2331 if (tevent_req_error(req
, err
)) {
2335 tevent_req_done(req
);
2337 tevent_req_post(req
, ev
);
2341 static int tstream_bsd_disconnect_recv(struct tevent_req
*req
,
2346 ret
= tsocket_simple_int_recv(req
, perrno
);
2348 tevent_req_received(req
);
2352 static const struct tstream_context_ops tstream_bsd_ops
= {
2355 .pending_bytes
= tstream_bsd_pending_bytes
,
2357 .readv_send
= tstream_bsd_readv_send
,
2358 .readv_recv
= tstream_bsd_readv_recv
,
2360 .writev_send
= tstream_bsd_writev_send
,
2361 .writev_recv
= tstream_bsd_writev_recv
,
2363 .disconnect_send
= tstream_bsd_disconnect_send
,
2364 .disconnect_recv
= tstream_bsd_disconnect_recv
,
2367 static int tstream_bsd_destructor(struct tstream_bsd
*bsds
)
2369 TALLOC_FREE(bsds
->fde
);
2370 if (bsds
->fd
!= -1) {
2377 int _tstream_bsd_existing_socket(TALLOC_CTX
*mem_ctx
,
2379 struct tstream_context
**_stream
,
2380 const char *location
)
2382 struct tstream_context
*stream
;
2383 struct tstream_bsd
*bsds
;
2385 stream
= tstream_context_create(mem_ctx
,
2395 talloc_set_destructor(bsds
, tstream_bsd_destructor
);
2401 struct tstream_bsd_connect_state
{
2403 struct tevent_fd
*fde
;
2404 struct tstream_conext
*stream
;
2405 struct tsocket_address
*local
;
2408 static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state
*state
)
2410 TALLOC_FREE(state
->fde
);
2411 if (state
->fd
!= -1) {
2419 static void tstream_bsd_connect_fde_handler(struct tevent_context
*ev
,
2420 struct tevent_fd
*fde
,
2422 void *private_data
);
2424 static struct tevent_req
*tstream_bsd_connect_send(TALLOC_CTX
*mem_ctx
,
2425 struct tevent_context
*ev
,
2427 const struct tsocket_address
*local
,
2428 const struct tsocket_address
*remote
)
2430 struct tevent_req
*req
;
2431 struct tstream_bsd_connect_state
*state
;
2432 struct samba_sockaddr
*lbsda
=
2433 talloc_get_type_abort(local
->private_data
,
2434 struct samba_sockaddr
);
2435 struct samba_sockaddr
*lrbsda
= NULL
;
2436 struct samba_sockaddr
*rbsda
=
2437 talloc_get_type_abort(remote
->private_data
,
2438 struct samba_sockaddr
);
2440 bool do_bind
= false;
2441 bool do_reuseaddr
= false;
2442 bool do_ipv6only
= false;
2443 bool is_inet
= false;
2444 int sa_fam
= lbsda
->u
.sa
.sa_family
;
2446 req
= tevent_req_create(mem_ctx
, &state
,
2447 struct tstream_bsd_connect_state
);
2454 talloc_set_destructor(state
, tstream_bsd_connect_destructor
);
2456 /* give the wrappers a chance to report an error */
2457 if (sys_errno
!= 0) {
2458 tevent_req_error(req
, sys_errno
);
2462 switch (lbsda
->u
.sa
.sa_family
) {
2464 if (lbsda
->u
.un
.sun_path
[0] != 0) {
2465 do_reuseaddr
= true;
2470 if (lbsda
->u
.in
.sin_port
!= 0) {
2471 do_reuseaddr
= true;
2474 if (lbsda
->u
.in
.sin_addr
.s_addr
!= INADDR_ANY
) {
2481 if (lbsda
->u
.in6
.sin6_port
!= 0) {
2482 do_reuseaddr
= true;
2485 if (memcmp(&in6addr_any
,
2486 &lbsda
->u
.in6
.sin6_addr
,
2487 sizeof(in6addr_any
)) != 0) {
2495 tevent_req_error(req
, EINVAL
);
2499 if (!do_bind
&& is_inet
) {
2500 sa_fam
= rbsda
->u
.sa
.sa_family
;
2503 do_ipv6only
= false;
2514 state
->local
= tsocket_address_create(state
,
2515 &tsocket_address_bsd_ops
,
2517 struct samba_sockaddr
,
2518 __location__
"bsd_connect");
2519 if (tevent_req_nomem(state
->local
, req
)) {
2523 ZERO_STRUCTP(lrbsda
);
2524 lrbsda
->sa_socklen
= sizeof(lrbsda
->u
.ss
);
2525 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2526 lrbsda
->u
.sa
.sa_len
= lrbsda
->sa_socklen
;
2530 state
->fd
= socket(sa_fam
, SOCK_STREAM
, 0);
2531 if (state
->fd
== -1) {
2532 tevent_req_error(req
, errno
);
2536 state
->fd
= tsocket_bsd_common_prepare_fd(state
->fd
, true);
2537 if (state
->fd
== -1) {
2538 tevent_req_error(req
, errno
);
2546 ret
= setsockopt(state
->fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
2547 (const void *)&val
, sizeof(val
));
2549 tevent_req_error(req
, errno
);
2558 ret
= setsockopt(state
->fd
, SOL_SOCKET
, SO_REUSEADDR
,
2559 (const void *)&val
, sizeof(val
));
2561 tevent_req_error(req
, errno
);
2567 ret
= bind(state
->fd
, &lbsda
->u
.sa
, lbsda
->sa_socklen
);
2569 tevent_req_error(req
, errno
);
2574 if (rbsda
->u
.sa
.sa_family
!= sa_fam
) {
2575 tevent_req_error(req
, EINVAL
);
2579 ret
= connect(state
->fd
, &rbsda
->u
.sa
, rbsda
->sa_socklen
);
2581 if (errno
== EINPROGRESS
) {
2584 tevent_req_error(req
, errno
);
2588 if (!state
->local
) {
2589 tevent_req_done(req
);
2593 if (lrbsda
!= NULL
) {
2594 ret
= getsockname(state
->fd
,
2596 &lrbsda
->sa_socklen
);
2598 tevent_req_error(req
, errno
);
2603 tevent_req_done(req
);
2609 * Note for historic reasons TEVENT_FD_WRITE is not enough
2610 * to get notified for POLLERR or EPOLLHUP even if they
2611 * come together with POLLOUT. That means we need to
2612 * use TEVENT_FD_READ in addition until we have
2615 state
->fde
= tevent_add_fd(ev
, state
,
2617 TEVENT_FD_ERROR
| TEVENT_FD_WRITE
,
2618 tstream_bsd_connect_fde_handler
,
2620 if (tevent_req_nomem(state
->fde
, req
)) {
2627 tevent_req_post(req
, ev
);
2631 static void tstream_bsd_connect_fde_handler(struct tevent_context
*ev
,
2632 struct tevent_fd
*fde
,
2636 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
2638 struct tstream_bsd_connect_state
*state
= tevent_req_data(req
,
2639 struct tstream_bsd_connect_state
);
2640 struct samba_sockaddr
*lrbsda
= NULL
;
2645 ret
= samba_socket_sock_error(state
->fd
);
2646 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
2651 if (tevent_req_error(req
, err
)) {
2655 if (!state
->local
) {
2656 tevent_req_done(req
);
2660 lrbsda
= talloc_get_type_abort(state
->local
->private_data
,
2661 struct samba_sockaddr
);
2663 ret
= getsockname(state
->fd
, &lrbsda
->u
.sa
, &lrbsda
->sa_socklen
);
2665 tevent_req_error(req
, errno
);
2669 tevent_req_done(req
);
2672 static int tstream_bsd_connect_recv(struct tevent_req
*req
,
2674 TALLOC_CTX
*mem_ctx
,
2675 struct tstream_context
**stream
,
2676 struct tsocket_address
**local
,
2677 const char *location
)
2679 struct tstream_bsd_connect_state
*state
= tevent_req_data(req
,
2680 struct tstream_bsd_connect_state
);
2683 ret
= tsocket_simple_int_recv(req
, perrno
);
2685 ret
= _tstream_bsd_existing_socket(mem_ctx
,
2693 TALLOC_FREE(state
->fde
);
2697 *local
= talloc_move(mem_ctx
, &state
->local
);
2702 tevent_req_received(req
);
2706 struct tevent_req
* tstream_inet_tcp_connect_send(TALLOC_CTX
*mem_ctx
,
2707 struct tevent_context
*ev
,
2708 const struct tsocket_address
*local
,
2709 const struct tsocket_address
*remote
)
2711 struct samba_sockaddr
*lbsda
=
2712 talloc_get_type_abort(local
->private_data
,
2713 struct samba_sockaddr
);
2714 struct tevent_req
*req
;
2717 switch (lbsda
->u
.sa
.sa_family
) {
2729 req
= tstream_bsd_connect_send(mem_ctx
, ev
, sys_errno
, local
, remote
);
2734 int _tstream_inet_tcp_connect_recv(struct tevent_req
*req
,
2736 TALLOC_CTX
*mem_ctx
,
2737 struct tstream_context
**stream
,
2738 struct tsocket_address
**local
,
2739 const char *location
)
2741 return tstream_bsd_connect_recv(req
, perrno
,
2742 mem_ctx
, stream
, local
,
2746 struct tevent_req
* tstream_unix_connect_send(TALLOC_CTX
*mem_ctx
,
2747 struct tevent_context
*ev
,
2748 const struct tsocket_address
*local
,
2749 const struct tsocket_address
*remote
)
2751 struct samba_sockaddr
*lbsda
=
2752 talloc_get_type_abort(local
->private_data
,
2753 struct samba_sockaddr
);
2754 struct tevent_req
*req
;
2757 switch (lbsda
->u
.sa
.sa_family
) {
2765 req
= tstream_bsd_connect_send(mem_ctx
, ev
, sys_errno
, local
, remote
);
2770 int _tstream_unix_connect_recv(struct tevent_req
*req
,
2772 TALLOC_CTX
*mem_ctx
,
2773 struct tstream_context
**stream
,
2774 const char *location
)
2776 return tstream_bsd_connect_recv(req
, perrno
,
2777 mem_ctx
, stream
, NULL
,
2781 int _tstream_unix_socketpair(TALLOC_CTX
*mem_ctx1
,
2782 struct tstream_context
**_stream1
,
2783 TALLOC_CTX
*mem_ctx2
,
2784 struct tstream_context
**_stream2
,
2785 const char *location
)
2791 struct tstream_context
*stream1
= NULL
;
2792 struct tstream_context
*stream2
= NULL
;
2794 ret
= socketpair(AF_UNIX
, SOCK_STREAM
, 0, fds
);
2801 fd1
= tsocket_bsd_common_prepare_fd(fd1
, true);
2803 int sys_errno
= errno
;
2809 fd2
= tsocket_bsd_common_prepare_fd(fd2
, true);
2811 int sys_errno
= errno
;
2817 ret
= _tstream_bsd_existing_socket(mem_ctx1
,
2822 int sys_errno
= errno
;
2829 ret
= _tstream_bsd_existing_socket(mem_ctx2
,
2834 int sys_errno
= errno
;
2835 talloc_free(stream1
);
2841 *_stream1
= stream1
;
2842 *_stream2
= stream2
;