2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tevent
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"
27 #include "system/filesys.h"
29 #include "tsocket_internal.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
) {
65 if (sys_errno
== EWOULDBLOCK
) {
74 static int tsocket_bsd_common_prepare_fd(int fd
, bool high_fd
)
87 /* first make a fd >= 3 */
97 for (i
=0; i
<num_fds
; i
++) {
106 /* fd should be nonblocking. */
109 #define FLAG_TO_SET O_NONBLOCK
112 #define FLAG_TO_SET O_NDELAY
114 #define FLAG_TO_SET FNDELAY
118 if ((flags
= fcntl(fd
, F_GETFL
)) == -1) {
122 flags
|= FLAG_TO_SET
;
123 if (fcntl(fd
, F_SETFL
, flags
) == -1) {
129 /* fd should be closed on exec() */
131 result
= flags
= fcntl(fd
, F_GETFD
, 0);
134 result
= fcntl(fd
, F_SETFD
, flags
);
151 static ssize_t
tsocket_bsd_pending(int fd
)
156 ret
= ioctl(fd
, FIONREAD
, &value
);
164 socklen_t len
= sizeof(error
);
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.
171 ret
= getsockopt(fd
, SOL_SOCKET
, SO_ERROR
,
184 /* this should not be reached */
189 static const struct tsocket_context_ops tsocket_context_bsd_ops
;
190 static const struct tsocket_address_ops tsocket_address_bsd_ops
;
192 static int tsocket_context_bsd_set_option(const struct tsocket_context
*sock
,
197 struct tsocket_context_bsd
{
198 bool close_on_disconnect
;
200 struct tevent_fd
*fde
;
203 struct tsocket_address_bsd
{
207 struct sockaddr_in in
;
209 struct sockaddr_in6 in6
;
211 struct sockaddr_un un
;
212 struct sockaddr_storage ss
;
216 static int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX
*mem_ctx
,
219 struct tsocket_address
**_addr
,
220 const char *location
)
222 struct tsocket_address
*addr
;
223 struct tsocket_address_bsd
*bsda
;
225 switch (sa
->sa_family
) {
227 if (sa_len
< sizeof(struct sockaddr_un
)) {
233 if (sa_len
< sizeof(struct sockaddr_in
)) {
240 if (sa_len
< sizeof(struct sockaddr_in6
)) {
247 errno
= EAFNOSUPPORT
;
251 if (sa_len
> sizeof(struct sockaddr_storage
)) {
256 addr
= tsocket_address_create(mem_ctx
,
257 &tsocket_address_bsd_ops
,
259 struct tsocket_address_bsd
,
268 memcpy(&bsda
->u
.ss
, sa
, sa_len
);
274 int _tsocket_address_inet_from_strings(TALLOC_CTX
*mem_ctx
,
278 struct tsocket_address
**_addr
,
279 const char *location
)
281 struct addrinfo hints
;
282 struct addrinfo
*result
= NULL
;
288 * we use SOCKET_STREAM here to get just one result
289 * back from getaddrinfo().
291 hints
.ai_socktype
= SOCK_STREAM
;
292 hints
.ai_flags
= AI_NUMERICHOST
| AI_NUMERICSERV
;
294 if (strcasecmp(fam
, "ip") == 0) {
295 hints
.ai_family
= AF_UNSPEC
;
303 } else if (strcasecmp(fam
, "ipv4") == 0) {
304 hints
.ai_family
= AF_INET
;
309 } else if (strcasecmp(fam
, "ipv6") == 0) {
310 hints
.ai_family
= AF_INET6
;
316 errno
= EAFNOSUPPORT
;
320 snprintf(port_str
, sizeof(port_str
) - 1, "%u", port
);
322 ret
= getaddrinfo(addr
, port_str
, &hints
, &result
);
333 if (result
->ai_socktype
!= SOCK_STREAM
) {
339 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
347 freeaddrinfo(result
);
352 char *tsocket_address_inet_addr_string(const struct tsocket_address
*addr
,
355 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
356 struct tsocket_address_bsd
);
357 char addr_str
[INET6_ADDRSTRLEN
+1];
365 switch (bsda
->u
.sa
.sa_family
) {
367 str
= inet_ntop(bsda
->u
.in
.sin_family
,
368 &bsda
->u
.in
.sin_addr
,
369 addr_str
, sizeof(addr_str
));
373 str
= inet_ntop(bsda
->u
.in6
.sin6_family
,
374 &bsda
->u
.in6
.sin6_addr
,
375 addr_str
, sizeof(addr_str
));
387 return talloc_strdup(mem_ctx
, str
);
390 uint16_t tsocket_address_inet_port(const struct tsocket_address
*addr
)
392 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
393 struct tsocket_address_bsd
);
401 switch (bsda
->u
.sa
.sa_family
) {
403 port
= ntohs(bsda
->u
.in
.sin_port
);
407 port
= ntohs(bsda
->u
.in6
.sin6_port
);
418 int tsocket_address_inet_set_port(struct tsocket_address
*addr
,
421 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
422 struct tsocket_address_bsd
);
429 switch (bsda
->u
.sa
.sa_family
) {
431 bsda
->u
.in
.sin_port
= htons(port
);
435 bsda
->u
.in6
.sin6_port
= htons(port
);
446 void tsocket_address_inet_set_broadcast(struct tsocket_address
*addr
,
449 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
450 struct tsocket_address_bsd
);
456 bsda
->broadcast
= broadcast
;
459 int _tsocket_address_unix_from_path(TALLOC_CTX
*mem_ctx
,
461 struct tsocket_address
**_addr
,
462 const char *location
)
464 struct sockaddr_un un
;
473 un
.sun_family
= AF_UNIX
;
474 strncpy(un
.sun_path
, path
, sizeof(un
.sun_path
));
476 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
477 (struct sockaddr
*)p
,
485 char *tsocket_address_unix_path(const struct tsocket_address
*addr
,
488 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
489 struct tsocket_address_bsd
);
497 switch (bsda
->u
.sa
.sa_family
) {
499 str
= bsda
->u
.un
.sun_path
;
506 return talloc_strdup(mem_ctx
, str
);
509 static char *tsocket_address_bsd_string(const struct tsocket_address
*addr
,
512 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
513 struct tsocket_address_bsd
);
516 const char *prefix
= NULL
;
519 switch (bsda
->u
.sa
.sa_family
) {
521 return talloc_asprintf(mem_ctx
, "unix:%s",
522 bsda
->u
.un
.sun_path
);
536 addr_str
= tsocket_address_inet_addr_string(addr
, mem_ctx
);
541 port
= tsocket_address_inet_port(addr
);
543 str
= talloc_asprintf(mem_ctx
, "%s:%s:%u",
544 prefix
, addr_str
, port
);
545 talloc_free(addr_str
);
550 static struct tsocket_address
*tsocket_address_bsd_copy(const struct tsocket_address
*addr
,
552 const char *location
)
554 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
555 struct tsocket_address_bsd
);
556 struct tsocket_address
*copy
;
559 ret
= _tsocket_address_bsd_from_sockaddr(mem_ctx
,
568 tsocket_address_inet_set_broadcast(copy
, bsda
->broadcast
);
572 int _tsocket_context_bsd_wrap_existing(TALLOC_CTX
*mem_ctx
,
573 int fd
, bool close_on_disconnect
,
574 struct tsocket_context
**_sock
,
575 const char *location
)
577 struct tsocket_context
*sock
;
578 struct tsocket_context_bsd
*bsds
;
580 sock
= tsocket_context_create(mem_ctx
,
581 &tsocket_context_bsd_ops
,
583 struct tsocket_context_bsd
,
589 bsds
->close_on_disconnect
= close_on_disconnect
;
597 static int tsocket_address_bsd_create_socket(const struct tsocket_address
*addr
,
598 enum tsocket_type type
,
600 struct tsocket_context
**_sock
,
601 const char *location
)
603 struct tsocket_address_bsd
*bsda
= talloc_get_type(addr
->private_data
,
604 struct tsocket_address_bsd
);
605 struct tsocket_context
*sock
;
609 bool do_bind
= false;
610 bool do_reuseaddr
= false;
613 case TSOCKET_TYPE_STREAM
:
614 if (bsda
->broadcast
) {
618 bsd_type
= SOCK_STREAM
;
621 errno
= EPROTONOSUPPORT
;
625 switch (bsda
->u
.sa
.sa_family
) {
627 if (bsda
->broadcast
) {
631 if (bsda
->u
.un
.sun_path
[0] != 0) {
636 if (bsda
->u
.in
.sin_port
!= 0) {
640 if (bsda
->u
.in
.sin_addr
.s_addr
== INADDR_ANY
) {
646 if (bsda
->u
.in6
.sin6_port
!= 0) {
650 if (memcmp(&in6addr_any
,
651 &bsda
->u
.in6
.sin6_addr
,
652 sizeof(in6addr_any
)) != 0) {
662 fd
= socket(bsda
->u
.sa
.sa_family
, bsd_type
, 0);
667 fd
= tsocket_common_prepare_fd(fd
, true);
672 ret
= _tsocket_context_bsd_wrap_existing(mem_ctx
, fd
, true,
675 int saved_errno
= errno
;
681 if (bsda
->broadcast
) {
682 ret
= tsocket_context_bsd_set_option(sock
, "SO_BROADCAST", true, "1");
684 int saved_errno
= errno
;
692 ret
= tsocket_context_bsd_set_option(sock
, "SO_REUSEADDR", true, "1");
694 int saved_errno
= errno
;
702 ret
= bind(fd
, &bsda
->u
.sa
, sizeof(bsda
->u
.ss
));
704 int saved_errno
= errno
;
715 static const struct tsocket_address_ops tsocket_address_bsd_ops
= {
717 .string
= tsocket_address_bsd_string
,
718 .copy
= tsocket_address_bsd_copy
,
719 .create_socket
= tsocket_address_bsd_create_socket
722 static void tsocket_context_bsd_fde_handler(struct tevent_context
*ev
,
723 struct tevent_fd
*fde
,
727 struct tsocket_context
*sock
= talloc_get_type(private_data
,
728 struct tsocket_context
);
730 if (flags
& TEVENT_FD_WRITE
) {
731 sock
->event
.write_handler(sock
, sock
->event
.write_private
);
734 if (flags
& TEVENT_FD_READ
) {
735 sock
->event
.read_handler(sock
, sock
->event
.read_private
);
740 static int tsocket_context_bsd_set_event_context(struct tsocket_context
*sock
,
741 struct tevent_context
*ev
)
743 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
744 struct tsocket_context_bsd
);
746 talloc_free(bsds
->fde
);
748 ZERO_STRUCT(sock
->event
);
754 bsds
->fde
= tevent_add_fd(ev
, bsds
,
757 tsocket_context_bsd_fde_handler
,
766 sock
->event
.ctx
= ev
;
771 static int tsocket_context_bsd_set_read_handler(struct tsocket_context
*sock
,
772 tsocket_event_handler_t handler
,
775 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
776 struct tsocket_context_bsd
);
778 if (sock
->event
.read_handler
&& !handler
) {
779 TEVENT_FD_NOT_READABLE(bsds
->fde
);
780 } else if (!sock
->event
.read_handler
&& handler
) {
781 TEVENT_FD_READABLE(bsds
->fde
);
784 sock
->event
.read_handler
= handler
;
785 sock
->event
.read_private
= private_data
;
790 static int tsocket_context_bsd_set_write_handler(struct tsocket_context
*sock
,
791 tsocket_event_handler_t handler
,
794 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
795 struct tsocket_context_bsd
);
797 if (sock
->event
.write_handler
&& !handler
) {
798 TEVENT_FD_NOT_WRITEABLE(bsds
->fde
);
799 } else if (!sock
->event
.write_handler
&& handler
) {
800 TEVENT_FD_WRITEABLE(bsds
->fde
);
803 sock
->event
.write_handler
= handler
;
804 sock
->event
.write_private
= private_data
;
809 static int tsocket_context_bsd_connect_to(struct tsocket_context
*sock
,
810 const struct tsocket_address
*remote
)
812 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
813 struct tsocket_context_bsd
);
814 struct tsocket_address_bsd
*bsda
= talloc_get_type(remote
->private_data
,
815 struct tsocket_address_bsd
);
818 ret
= connect(bsds
->fd
, &bsda
->u
.sa
,
824 static int tsocket_context_bsd_listen_on(struct tsocket_context
*sock
,
827 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
828 struct tsocket_context_bsd
);
831 ret
= listen(bsds
->fd
, queue_size
);
836 static int tsocket_context_bsd_accept_new(struct tsocket_context
*sock
,
838 struct tsocket_context
**_new_sock
,
839 const char *location
)
841 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
842 struct tsocket_context_bsd
);
844 struct tsocket_context
*new_sock
;
845 struct tsocket_context_bsd
*new_bsds
;
846 struct sockaddr_storage ss
;
848 socklen_t ss_len
= sizeof(ss
);
850 new_fd
= accept(bsds
->fd
, (struct sockaddr
*)p
, &ss_len
);
855 new_fd
= tsocket_common_prepare_fd(new_fd
, true);
860 new_sock
= tsocket_context_create(mem_ctx
,
861 &tsocket_context_bsd_ops
,
863 struct tsocket_context_bsd
,
866 int saved_errno
= errno
;
872 new_bsds
->close_on_disconnect
= true;
873 new_bsds
->fd
= new_fd
;
874 new_bsds
->fde
= NULL
;
876 *_new_sock
= new_sock
;
880 static ssize_t
tsocket_context_bsd_pending_data(struct tsocket_context
*sock
)
882 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
883 struct tsocket_context_bsd
);
887 ret
= ioctl(bsds
->fd
, FIONREAD
, &value
);
895 socklen_t len
= sizeof(error
);
897 * if no data is available check if the socket
898 * is in error state. For dgram sockets
899 * it's the way to return ICMP error messages
900 * of connected sockets to the caller.
902 ret
= getsockopt(bsds
->fd
, SOL_SOCKET
, SO_ERROR
,
915 /* this should not be reached */
920 static int tsocket_context_bsd_readv_data(struct tsocket_context
*sock
,
921 const struct iovec
*vector
,
924 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
925 struct tsocket_context_bsd
);
928 ret
= readv(bsds
->fd
, vector
, count
);
933 static int tsocket_context_bsd_writev_data(struct tsocket_context
*sock
,
934 const struct iovec
*vector
,
937 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
938 struct tsocket_context_bsd
);
941 ret
= writev(bsds
->fd
, vector
, count
);
946 static int tsocket_context_bsd_get_status(const struct tsocket_context
*sock
)
948 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
949 struct tsocket_context_bsd
);
952 socklen_t len
= sizeof(error
);
954 if (bsds
->fd
== -1) {
959 ret
= getsockopt(bsds
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
);
971 static int tsocket_context_bsd_get_local_address(const struct tsocket_context
*sock
,
973 struct tsocket_address
**_addr
,
974 const char *location
)
976 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
977 struct tsocket_context_bsd
);
978 struct tsocket_address
*addr
;
979 struct tsocket_address_bsd
*bsda
;
983 addr
= tsocket_address_create(mem_ctx
,
984 &tsocket_address_bsd_ops
,
986 struct tsocket_address_bsd
,
994 sa_len
= sizeof(bsda
->u
.ss
);
995 ret
= getsockname(bsds
->fd
, &bsda
->u
.sa
, &sa_len
);
997 int saved_errno
= errno
;
1007 static int tsocket_context_bsd_get_remote_address(const struct tsocket_context
*sock
,
1008 TALLOC_CTX
*mem_ctx
,
1009 struct tsocket_address
**_addr
,
1010 const char *location
)
1012 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
1013 struct tsocket_context_bsd
);
1014 struct tsocket_address
*addr
;
1015 struct tsocket_address_bsd
*bsda
;
1019 addr
= tsocket_address_create(mem_ctx
,
1020 &tsocket_address_bsd_ops
,
1022 struct tsocket_address_bsd
,
1030 sa_len
= sizeof(bsda
->u
.ss
);
1031 ret
= getpeername(bsds
->fd
, &bsda
->u
.sa
, &sa_len
);
1033 int saved_errno
= errno
;
1035 errno
= saved_errno
;
1043 static const struct tsocket_context_bsd_option
{
1048 } tsocket_context_bsd_options
[] = {
1049 #define TSOCKET_OPTION(_level, _optnum, _optval) { \
1052 .optnum = _optnum, \
1055 TSOCKET_OPTION(SOL_SOCKET
, SO_REUSEADDR
, 0),
1056 TSOCKET_OPTION(SOL_SOCKET
, SO_BROADCAST
, 0)
1059 static int tsocket_context_bsd_get_option(const struct tsocket_context
*sock
,
1061 TALLOC_CTX
*mem_ctx
,
1064 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
1065 struct tsocket_context_bsd
);
1066 const struct tsocket_context_bsd_option
*opt
= NULL
;
1069 socklen_t optval_len
= sizeof(optval
);
1073 for (i
=0; i
< ARRAY_SIZE(tsocket_context_bsd_options
); i
++) {
1074 if (strcmp(option
, tsocket_context_bsd_options
[i
].name
) != 0) {
1078 opt
= &tsocket_context_bsd_options
[i
];
1086 ret
= getsockopt(bsds
->fd
, opt
->level
, opt
->optnum
,
1087 (void *)&optval
, &optval_len
);
1092 if (optval_len
!= sizeof(optval
)) {
1094 } if (opt
->optval
!= 0) {
1095 if (optval
== opt
->optval
) {
1096 value
= talloc_strdup(mem_ctx
, "1");
1098 value
= talloc_strdup(mem_ctx
, "0");
1104 value
= talloc_asprintf(mem_ctx
, "%d", optval
);
1121 static int tsocket_context_bsd_set_option(const struct tsocket_context
*sock
,
1126 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
1127 struct tsocket_context_bsd
);
1128 const struct tsocket_context_bsd_option
*opt
= NULL
;
1133 for (i
=0; i
< ARRAY_SIZE(tsocket_context_bsd_options
); i
++) {
1134 if (strcmp(option
, tsocket_context_bsd_options
[i
].name
) != 0) {
1138 opt
= &tsocket_context_bsd_options
[i
];
1147 if (opt
->optval
!= 0) {
1152 optval
= atoi(value
);
1154 optval
= opt
->optval
;
1157 ret
= setsockopt(bsds
->fd
, opt
->level
, opt
->optnum
,
1158 (const void *)&optval
, sizeof(optval
));
1178 static void tsocket_context_bsd_disconnect(struct tsocket_context
*sock
)
1180 struct tsocket_context_bsd
*bsds
= talloc_get_type(sock
->private_data
,
1181 struct tsocket_context_bsd
);
1183 tsocket_context_bsd_set_event_context(sock
, NULL
);
1185 if (bsds
->fd
!= -1) {
1186 if (bsds
->close_on_disconnect
) {
1193 static const struct tsocket_context_ops tsocket_context_bsd_ops
= {
1196 .set_event_context
= tsocket_context_bsd_set_event_context
,
1197 .set_read_handler
= tsocket_context_bsd_set_read_handler
,
1198 .set_write_handler
= tsocket_context_bsd_set_write_handler
,
1200 .connect_to
= tsocket_context_bsd_connect_to
,
1201 .listen_on
= tsocket_context_bsd_listen_on
,
1202 .accept_new
= tsocket_context_bsd_accept_new
,
1204 .pending_data
= tsocket_context_bsd_pending_data
,
1205 .readv_data
= tsocket_context_bsd_readv_data
,
1206 .writev_data
= tsocket_context_bsd_writev_data
,
1208 .get_status
= tsocket_context_bsd_get_status
,
1209 .get_local_address
= tsocket_context_bsd_get_local_address
,
1210 .get_remote_address
= tsocket_context_bsd_get_remote_address
,
1212 .get_option
= tsocket_context_bsd_get_option
,
1213 .set_option
= tsocket_context_bsd_set_option
,
1215 .disconnect
= tsocket_context_bsd_disconnect
1222 struct tevent_fd
*fde
;
1224 void *readable_private
;
1225 void (*readable_handler
)(void *private_data
);
1226 void *writeable_private
;
1227 void (*writeable_handler
)(void *private_data
);
1229 struct tevent_req
*read_req
;
1230 struct tevent_req
*write_req
;
1233 static void tdgram_bsd_fde_handler(struct tevent_context
*ev
,
1234 struct tevent_fd
*fde
,
1238 struct tdgram_bsd
*bsds
= talloc_get_type_abort(private_data
,
1241 if (flags
& TEVENT_FD_WRITE
) {
1242 bsds
->writeable_handler(bsds
->writeable_private
);
1245 if (flags
& TEVENT_FD_READ
) {
1246 if (!bsds
->readable_handler
) {
1247 TEVENT_FD_NOT_READABLE(bsds
->fde
);
1250 bsds
->readable_handler(bsds
->readable_private
);
1255 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd
*bsds
,
1256 struct tevent_context
*ev
,
1257 void (*handler
)(void *private_data
),
1265 if (!bsds
->readable_handler
) {
1268 bsds
->readable_handler
= NULL
;
1269 bsds
->readable_private
= NULL
;
1274 /* read and write must use the same tevent_context */
1275 if (bsds
->event_ptr
!= ev
) {
1276 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
1280 bsds
->event_ptr
= NULL
;
1281 TALLOC_FREE(bsds
->fde
);
1284 if (bsds
->fde
== NULL
) {
1285 bsds
->fde
= tevent_add_fd(ev
, bsds
,
1286 bsds
->fd
, TEVENT_FD_READ
,
1287 tdgram_bsd_fde_handler
,
1293 /* cache the event context we're running on */
1294 bsds
->event_ptr
= ev
;
1295 } else if (!bsds
->readable_handler
) {
1296 TEVENT_FD_READABLE(bsds
->fde
);
1299 bsds
->readable_handler
= handler
;
1300 bsds
->readable_private
= private_data
;
1305 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd
*bsds
,
1306 struct tevent_context
*ev
,
1307 void (*handler
)(void *private_data
),
1315 if (!bsds
->writeable_handler
) {
1318 bsds
->writeable_handler
= NULL
;
1319 bsds
->writeable_private
= NULL
;
1320 TEVENT_FD_NOT_WRITEABLE(bsds
->fde
);
1325 /* read and write must use the same tevent_context */
1326 if (bsds
->event_ptr
!= ev
) {
1327 if (bsds
->readable_handler
|| bsds
->writeable_handler
) {
1331 bsds
->event_ptr
= NULL
;
1332 TALLOC_FREE(bsds
->fde
);
1335 if (bsds
->fde
== NULL
) {
1336 bsds
->fde
= tevent_add_fd(ev
, bsds
,
1337 bsds
->fd
, TEVENT_FD_WRITE
,
1338 tdgram_bsd_fde_handler
,
1344 /* cache the event context we're running on */
1345 bsds
->event_ptr
= ev
;
1346 } else if (!bsds
->writeable_handler
) {
1347 TEVENT_FD_WRITEABLE(bsds
->fde
);
1350 bsds
->writeable_handler
= handler
;
1351 bsds
->writeable_private
= private_data
;
1356 struct tdgram_bsd_recvfrom_state
{
1357 struct tdgram_context
*dgram
;
1361 struct tsocket_address
*src
;
1364 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state
*state
)
1366 struct tdgram_bsd
*bsds
= tdgram_context_data(state
->dgram
,
1369 bsds
->read_req
= NULL
;
1370 tdgram_bsd_set_readable_handler(bsds
, NULL
, NULL
, NULL
);
1375 static void tdgram_bsd_recvfrom_handler(void *private_data
);
1377 static struct tevent_req
*tdgram_bsd_recvfrom_send(TALLOC_CTX
*mem_ctx
,
1378 struct tevent_context
*ev
,
1379 struct tdgram_context
*dgram
)
1381 struct tevent_req
*req
;
1382 struct tdgram_bsd_recvfrom_state
*state
;
1383 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1386 req
= tevent_req_create(mem_ctx
, &state
,
1387 struct tdgram_bsd_recvfrom_state
);
1392 state
->dgram
= dgram
;
1397 if (bsds
->read_req
) {
1398 tevent_req_error(req
, EBUSY
);
1401 bsds
->read_req
= req
;
1403 talloc_set_destructor(state
, tdgram_bsd_recvfrom_destructor
);
1405 if (bsds
->fd
== -1) {
1406 tevent_req_error(req
, ENOTCONN
);
1411 * this is a fast path, not waiting for the
1412 * socket to become explicit readable gains
1413 * about 10%-20% performance in benchmark tests.
1415 tdgram_bsd_recvfrom_handler(req
);
1416 if (!tevent_req_is_in_progress(req
)) {
1420 ret
= tdgram_bsd_set_readable_handler(bsds
, ev
,
1421 tdgram_bsd_recvfrom_handler
,
1424 tevent_req_error(req
, errno
);
1431 tevent_req_post(req
, ev
);
1435 static void tdgram_bsd_recvfrom_handler(void *private_data
)
1437 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1439 struct tdgram_bsd_recvfrom_state
*state
= tevent_req_data(req
,
1440 struct tdgram_bsd_recvfrom_state
);
1441 struct tdgram_context
*dgram
= state
->dgram
;
1442 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1443 struct tsocket_address_bsd
*bsda
;
1445 struct sockaddr
*sa
= NULL
;
1446 socklen_t sa_len
= 0;
1450 ret
= tsocket_bsd_pending(bsds
->fd
);
1455 err
= tsocket_bsd_error_from_errno(ret
, errno
, &retry
);
1460 if (tevent_req_error(req
, err
)) {
1464 state
->buf
= talloc_array(state
, uint8_t, ret
);
1465 if (tevent_req_nomem(state
->buf
, req
)) {
1470 state
->src
= tsocket_address_create(state
,
1471 &tsocket_address_bsd_ops
,
1473 struct tsocket_address_bsd
,
1474 __location__
"bsd_recvfrom");
1475 if (tevent_req_nomem(state
->src
, req
)) {
1482 sa_len
= sizeof(bsda
->u
.ss
);
1484 ret
= recvfrom(bsds
->fd
, state
->buf
, state
->len
, 0, sa
, &sa_len
);
1485 err
= tsocket_error_from_errno(ret
, errno
, &retry
);
1490 if (tevent_req_error(req
, err
)) {
1494 if (ret
!= state
->len
) {
1495 tevent_req_error(req
, EIO
);
1499 tevent_req_done(req
);
1502 static ssize_t
tdgram_bsd_recvfrom_recv(struct tevent_req
*req
,
1504 TALLOC_CTX
*mem_ctx
,
1506 struct tsocket_address
**src
)
1508 struct tdgram_bsd_recvfrom_state
*state
= tevent_req_data(req
,
1509 struct tdgram_bsd_recvfrom_state
);
1512 ret
= tsocket_simple_int_recv(req
, perrno
);
1514 *buf
= talloc_move(mem_ctx
, &state
->buf
);
1517 *src
= talloc_move(mem_ctx
, &state
->src
);
1521 tevent_req_received(req
);
1525 struct tdgram_bsd_sendto_state
{
1526 struct tdgram_context
*dgram
;
1530 const struct tsocket_address
*dst
;
1535 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state
*state
)
1537 struct tdgram_bsd
*bsds
= tdgram_context_data(state
->dgram
,
1540 bsds
->write_req
= NULL
;
1541 tdgram_bsd_set_writeable_handler(bsds
, NULL
, NULL
, NULL
);
1545 static void tdgram_bsd_sendto_handler(void *private_data
);
1547 static struct tevent_req
*tdgram_bsd_sendto_send(TALLOC_CTX
*mem_ctx
,
1548 struct tevent_context
*ev
,
1549 struct tdgram_context
*dgram
,
1552 const struct tsocket_address
*dst
)
1554 struct tevent_req
*req
;
1555 struct tdgram_bsd_sendto_state
*state
;
1556 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1559 req
= tevent_req_create(mem_ctx
, &state
,
1560 struct tdgram_bsd_sendto_state
);
1565 state
->dgram
= dgram
;
1571 if (bsds
->write_req
) {
1572 tevent_req_error(req
, EBUSY
);
1575 bsds
->write_req
= req
;
1577 talloc_set_destructor(state
, tdgram_bsd_sendto_destructor
);
1579 if (bsds
->fd
== -1) {
1580 tevent_req_error(req
, ENOTCONN
);
1585 * this is a fast path, not waiting for the
1586 * socket to become explicit writeable gains
1587 * about 10%-20% performance in benchmark tests.
1589 tdgram_bsd_sendto_handler(req
);
1590 if (!tevent_req_is_in_progress(req
)) {
1594 ret
= tdgram_bsd_set_writeable_handler(bsds
, ev
,
1595 tdgram_bsd_sendto_handler
,
1598 tevent_req_error(req
, errno
);
1605 tevent_req_post(req
, ev
);
1609 static void tdgram_bsd_sendto_handler(void *private_data
)
1611 struct tevent_req
*req
= talloc_get_type_abort(private_data
,
1613 struct tdgram_bsd_sendto_state
*state
= tevent_req_data(req
,
1614 struct tdgram_bsd_sendto_state
);
1615 struct tdgram_context
*dgram
= state
->dgram
;
1616 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1617 struct sockaddr
*sa
= NULL
;
1618 socklen_t sa_len
= 0;
1624 struct tsocket_address_bsd
*bsda
=
1625 talloc_get_type(state
->dst
->private_data
,
1626 struct tsocket_address_bsd
);
1629 sa_len
= sizeof(bsda
->u
.ss
);
1632 ret
= sendto(bsds
->fd
, state
->buf
, state
->len
, 0, sa
, sa_len
);
1633 err
= tsocket_error_from_errno(ret
, errno
, &retry
);
1638 if (tevent_req_error(req
, err
)) {
1644 tevent_req_done(req
);
1647 static ssize_t
tdgram_bsd_sendto_recv(struct tevent_req
*req
, int *perrno
)
1649 struct tdgram_bsd_sendto_state
*state
= tevent_req_data(req
,
1650 struct tdgram_bsd_sendto_state
);
1653 ret
= tsocket_simple_int_recv(req
, perrno
);
1658 tevent_req_received(req
);
1662 struct tdgram_bsd_disconnect_state
{
1666 static struct tevent_req
*tdgram_bsd_disconnect_send(TALLOC_CTX
*mem_ctx
,
1667 struct tevent_context
*ev
,
1668 struct tdgram_context
*dgram
)
1670 struct tdgram_bsd
*bsds
= tdgram_context_data(dgram
, struct tdgram_bsd
);
1671 struct tevent_req
*req
;
1672 struct tdgram_bsd_disconnect_state
*state
;
1677 req
= tevent_req_create(mem_ctx
, &state
,
1678 struct tdgram_bsd_disconnect_state
);
1683 if (bsds
->read_req
|| bsds
->write_req
) {
1684 tevent_req_error(req
, EBUSY
);
1688 if (bsds
->fd
== -1) {
1689 tevent_req_error(req
, ENOTCONN
);
1693 ret
= close(bsds
->fd
);
1695 err
= tsocket_error_from_errno(ret
, errno
, &dummy
);
1696 if (tevent_req_error(req
, err
)) {
1700 tevent_req_done(req
);
1702 tevent_req_post(req
, ev
);
1706 static int tdgram_bsd_disconnect_recv(struct tevent_req
*req
,
1711 ret
= tsocket_simple_int_recv(req
, perrno
);
1713 tevent_req_received(req
);
1717 static const struct tdgram_context_ops tdgram_bsd_ops
= {
1720 .recvfrom_send
= tdgram_bsd_recvfrom_send
,
1721 .recvfrom_recv
= tdgram_bsd_recvfrom_recv
,
1723 .sendto_send
= tdgram_bsd_sendto_send
,
1724 .sendto_recv
= tdgram_bsd_sendto_recv
,
1726 .disconnect_send
= tdgram_bsd_disconnect_send
,
1727 .disconnect_recv
= tdgram_bsd_disconnect_recv
,
1730 static int tdgram_bsd_destructor(struct tdgram_bsd
*bsds
)
1732 TALLOC_FREE(bsds
->fde
);
1733 if (bsds
->fd
!= -1) {
1740 static int tdgram_bsd_dgram_socket(const struct tsocket_address
*local
,
1741 const struct tsocket_address
*remote
,
1742 TALLOC_CTX
*mem_ctx
,
1743 struct tdgram_context
**_dgram
,
1744 const char *location
)
1746 struct tsocket_address_bsd
*lbsda
=
1747 talloc_get_type_abort(local
->private_data
,
1748 struct tsocket_address_bsd
);
1749 struct tsocket_address_bsd
*rbsda
= NULL
;
1750 struct tdgram_context
*dgram
;
1751 struct tdgram_bsd
*bsds
;
1754 bool do_bind
= false;
1755 bool do_reuseaddr
= false;
1758 rbsda
= talloc_get_type_abort(remote
->private_data
,
1759 struct tsocket_address_bsd
);
1762 switch (lbsda
->u
.sa
.sa_family
) {
1764 if (lbsda
->u
.un
.sun_path
[0] != 0) {
1765 do_reuseaddr
= true;
1770 if (lbsda
->u
.in
.sin_port
!= 0) {
1771 do_reuseaddr
= true;
1774 if (lbsda
->u
.in
.sin_addr
.s_addr
== INADDR_ANY
) {
1780 if (lbsda
->u
.in6
.sin6_port
!= 0) {
1781 do_reuseaddr
= true;
1784 if (memcmp(&in6addr_any
,
1785 &lbsda
->u
.in6
.sin6_addr
,
1786 sizeof(in6addr_any
)) != 0) {
1796 fd
= socket(lbsda
->u
.sa
.sa_family
, SOCK_DGRAM
, 0);
1801 fd
= tsocket_bsd_common_prepare_fd(fd
, true);
1806 dgram
= tdgram_context_create(mem_ctx
,
1812 int saved_errno
= errno
;
1814 errno
= saved_errno
;
1819 talloc_set_destructor(bsds
, tdgram_bsd_destructor
);
1821 if (lbsda
->broadcast
) {
1824 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
,
1825 (const void *)&val
, sizeof(val
));
1827 int saved_errno
= errno
;
1829 errno
= saved_errno
;
1837 ret
= setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
,
1838 (const void *)&val
, sizeof(val
));
1840 int saved_errno
= errno
;
1842 errno
= saved_errno
;
1848 ret
= bind(fd
, &lbsda
->u
.sa
, sizeof(lbsda
->u
.ss
));
1850 int saved_errno
= errno
;
1852 errno
= saved_errno
;
1858 ret
= connect(fd
, &rbsda
->u
.sa
, sizeof(rbsda
->u
.ss
));
1860 int saved_errno
= errno
;
1862 errno
= saved_errno
;
1871 int _tdgram_inet_udp_socket(const struct tsocket_address
*local
,
1872 const struct tsocket_address
*remote
,
1873 TALLOC_CTX
*mem_ctx
,
1874 struct tdgram_context
**dgram
,
1875 const char *location
)
1877 struct tsocket_address_bsd
*lbsda
=
1878 talloc_get_type_abort(local
->private_data
,
1879 struct tsocket_address_bsd
);
1882 switch (lbsda
->u
.sa
.sa_family
) {
1894 ret
= tdgram_bsd_dgram_socket(local
, remote
, mem_ctx
, dgram
, location
);
1899 int _tdgram_unix_dgram_socket(const struct tsocket_address
*local
,
1900 const struct tsocket_address
*remote
,
1901 TALLOC_CTX
*mem_ctx
,
1902 struct tdgram_context
**dgram
,
1903 const char *location
)
1905 struct tsocket_address_bsd
*lbsda
=
1906 talloc_get_type_abort(local
->private_data
,
1907 struct tsocket_address_bsd
);
1910 switch (lbsda
->u
.sa
.sa_family
) {
1918 ret
= tdgram_bsd_dgram_socket(local
, remote
, mem_ctx
, dgram
, location
);