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"
28 #include "tsocket_internal.h"
30 static int tsocket_bsd_error_from_errno(int ret,
48 if (sys_errno == EINTR) {
53 if (sys_errno == EINPROGRESS) {
58 if (sys_errno == EAGAIN) {
64 if (sys_errno == EWOULDBLOCK) {
73 static int tsocket_bsd_common_prepare_fd(int fd, bool high_fd)
86 /* first make a fd >= 3 */
96 for (i=0; i<num_fds; i++) {
105 /* fd should be nonblocking. */
108 #define FLAG_TO_SET O_NONBLOCK
111 #define FLAG_TO_SET O_NDELAY
113 #define FLAG_TO_SET FNDELAY
117 if ((flags = fcntl(fd, F_GETFL)) == -1) {
121 flags |= FLAG_TO_SET;
122 if (fcntl(fd, F_SETFL, flags) == -1) {
128 /* fd should be closed on exec() */
130 result = flags = fcntl(fd, F_GETFD, 0);
133 result = fcntl(fd, F_SETFD, flags);
150 static ssize_t tsocket_bsd_pending(int fd)
156 ret = ioctl(fd, FIONREAD, &value);
162 /* this should not be reached */
175 * if no data is available check if the socket is in error state. For
176 * dgram sockets it's the way to return ICMP error messages of
177 * connected sockets to the caller.
179 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len);
190 static const struct tsocket_address_ops tsocket_address_bsd_ops;
192 struct tsocket_address_bsd {
195 struct sockaddr_in in;
197 struct sockaddr_in6 in6;
199 struct sockaddr_un un;
200 struct sockaddr_storage ss;
204 static int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
206 socklen_t sa_socklen,
207 struct tsocket_address **_addr,
208 const char *location)
210 struct tsocket_address *addr;
211 struct tsocket_address_bsd *bsda;
213 switch (sa->sa_family) {
215 if (sa_socklen < sizeof(struct sockaddr_un)) {
221 if (sa_socklen < sizeof(struct sockaddr_in)) {
228 if (sa_socklen < sizeof(struct sockaddr_in6)) {
235 errno = EAFNOSUPPORT;
239 if (sa_socklen > sizeof(struct sockaddr_storage)) {
244 addr = tsocket_address_create(mem_ctx,
245 &tsocket_address_bsd_ops,
247 struct tsocket_address_bsd,
256 memcpy(&bsda->u.ss, sa, sa_socklen);
262 int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
266 struct tsocket_address **_addr,
267 const char *location)
269 struct addrinfo hints;
270 struct addrinfo *result = NULL;
276 * we use SOCKET_STREAM here to get just one result
277 * back from getaddrinfo().
279 hints.ai_socktype = SOCK_STREAM;
280 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
282 if (strcasecmp(fam, "ip") == 0) {
283 hints.ai_family = AF_UNSPEC;
291 } else if (strcasecmp(fam, "ipv4") == 0) {
292 hints.ai_family = AF_INET;
297 } else if (strcasecmp(fam, "ipv6") == 0) {
298 hints.ai_family = AF_INET6;
304 errno = EAFNOSUPPORT;
308 snprintf(port_str, sizeof(port_str) - 1, "%u", port);
310 ret = getaddrinfo(addr, port_str, &hints, &result);
321 if (result->ai_socktype != SOCK_STREAM) {
327 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
335 freeaddrinfo(result);
340 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
343 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
344 struct tsocket_address_bsd);
345 char addr_str[INET6_ADDRSTRLEN+1];
353 switch (bsda->u.sa.sa_family) {
355 str = inet_ntop(bsda->u.in.sin_family,
356 &bsda->u.in.sin_addr,
357 addr_str, sizeof(addr_str));
361 str = inet_ntop(bsda->u.in6.sin6_family,
362 &bsda->u.in6.sin6_addr,
363 addr_str, sizeof(addr_str));
375 return talloc_strdup(mem_ctx, str);
378 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
380 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
381 struct tsocket_address_bsd);
389 switch (bsda->u.sa.sa_family) {
391 port = ntohs(bsda->u.in.sin_port);
395 port = ntohs(bsda->u.in6.sin6_port);
406 int tsocket_address_inet_set_port(struct tsocket_address *addr,
409 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
410 struct tsocket_address_bsd);
417 switch (bsda->u.sa.sa_family) {
419 bsda->u.in.sin_port = htons(port);
423 bsda->u.in6.sin6_port = htons(port);
434 int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
436 struct tsocket_address **_addr,
437 const char *location)
439 struct sockaddr_un un;
447 if (strlen(path) > sizeof(un.sun_path)-1) {
448 errno = ENAMETOOLONG;
453 un.sun_family = AF_UNIX;
454 strncpy(un.sun_path, path, sizeof(un.sun_path)-1);
456 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
457 (struct sockaddr *)p,
465 char *tsocket_address_unix_path(const struct tsocket_address *addr,
468 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
469 struct tsocket_address_bsd);
477 switch (bsda->u.sa.sa_family) {
479 str = bsda->u.un.sun_path;
486 return talloc_strdup(mem_ctx, str);
489 static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
492 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
493 struct tsocket_address_bsd);
496 const char *prefix = NULL;
499 switch (bsda->u.sa.sa_family) {
501 return talloc_asprintf(mem_ctx, "unix:%s",
502 bsda->u.un.sun_path);
516 addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
521 port = tsocket_address_inet_port(addr);
523 str = talloc_asprintf(mem_ctx, "%s:%s:%u",
524 prefix, addr_str, port);
525 talloc_free(addr_str);
530 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
532 const char *location)
534 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
535 struct tsocket_address_bsd);
536 struct tsocket_address *copy;
539 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
551 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
553 .string = tsocket_address_bsd_string,
554 .copy = tsocket_address_bsd_copy,
561 struct tevent_fd *fde;
563 void *readable_private;
564 void (*readable_handler)(void *private_data);
565 void *writeable_private;
566 void (*writeable_handler)(void *private_data);
569 static void tdgram_bsd_fde_handler(struct tevent_context *ev,
570 struct tevent_fd *fde,
574 struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
577 if (flags & TEVENT_FD_WRITE) {
578 bsds->writeable_handler(bsds->writeable_private);
581 if (flags & TEVENT_FD_READ) {
582 if (!bsds->readable_handler) {
583 TEVENT_FD_NOT_READABLE(bsds->fde);
586 bsds->readable_handler(bsds->readable_private);
591 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
592 struct tevent_context *ev,
593 void (*handler)(void *private_data),
601 if (!bsds->readable_handler) {
604 bsds->readable_handler = NULL;
605 bsds->readable_private = NULL;
610 /* read and write must use the same tevent_context */
611 if (bsds->event_ptr != ev) {
612 if (bsds->readable_handler || bsds->writeable_handler) {
616 bsds->event_ptr = NULL;
617 TALLOC_FREE(bsds->fde);
620 if (tevent_fd_get_flags(bsds->fde) == 0) {
621 TALLOC_FREE(bsds->fde);
623 bsds->fde = tevent_add_fd(ev, bsds,
624 bsds->fd, TEVENT_FD_READ,
625 tdgram_bsd_fde_handler,
632 /* cache the event context we're running on */
633 bsds->event_ptr = ev;
634 } else if (!bsds->readable_handler) {
635 TEVENT_FD_READABLE(bsds->fde);
638 bsds->readable_handler = handler;
639 bsds->readable_private = private_data;
644 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
645 struct tevent_context *ev,
646 void (*handler)(void *private_data),
654 if (!bsds->writeable_handler) {
657 bsds->writeable_handler = NULL;
658 bsds->writeable_private = NULL;
659 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
664 /* read and write must use the same tevent_context */
665 if (bsds->event_ptr != ev) {
666 if (bsds->readable_handler || bsds->writeable_handler) {
670 bsds->event_ptr = NULL;
671 TALLOC_FREE(bsds->fde);
674 if (tevent_fd_get_flags(bsds->fde) == 0) {
675 TALLOC_FREE(bsds->fde);
677 bsds->fde = tevent_add_fd(ev, bsds,
678 bsds->fd, TEVENT_FD_WRITE,
679 tdgram_bsd_fde_handler,
686 /* cache the event context we're running on */
687 bsds->event_ptr = ev;
688 } else if (!bsds->writeable_handler) {
689 TEVENT_FD_WRITEABLE(bsds->fde);
692 bsds->writeable_handler = handler;
693 bsds->writeable_private = private_data;
698 struct tdgram_bsd_recvfrom_state {
699 struct tdgram_context *dgram;
703 struct tsocket_address *src;
706 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
708 struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
711 tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
716 static void tdgram_bsd_recvfrom_handler(void *private_data);
718 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
719 struct tevent_context *ev,
720 struct tdgram_context *dgram)
722 struct tevent_req *req;
723 struct tdgram_bsd_recvfrom_state *state;
724 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
727 req = tevent_req_create(mem_ctx, &state,
728 struct tdgram_bsd_recvfrom_state);
733 state->dgram = dgram;
738 talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
740 if (bsds->fd == -1) {
741 tevent_req_error(req, ENOTCONN);
746 * this is a fast path, not waiting for the
747 * socket to become explicit readable gains
748 * about 10%-20% performance in benchmark tests.
750 tdgram_bsd_recvfrom_handler(req);
751 if (!tevent_req_is_in_progress(req)) {
755 ret = tdgram_bsd_set_readable_handler(bsds, ev,
756 tdgram_bsd_recvfrom_handler,
759 tevent_req_error(req, errno);
766 tevent_req_post(req, ev);
770 static void tdgram_bsd_recvfrom_handler(void *private_data)
772 struct tevent_req *req = talloc_get_type_abort(private_data,
774 struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
775 struct tdgram_bsd_recvfrom_state);
776 struct tdgram_context *dgram = state->dgram;
777 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
778 struct tsocket_address_bsd *bsda;
780 struct sockaddr *sa = NULL;
781 socklen_t sa_socklen = 0;
785 ret = tsocket_bsd_pending(bsds->fd);
790 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
795 if (tevent_req_error(req, err)) {
799 state->buf = talloc_array(state, uint8_t, ret);
800 if (tevent_req_nomem(state->buf, req)) {
805 state->src = tsocket_address_create(state,
806 &tsocket_address_bsd_ops,
808 struct tsocket_address_bsd,
809 __location__ "bsd_recvfrom");
810 if (tevent_req_nomem(state->src, req)) {
817 sa_socklen = sizeof(bsda->u.ss);
819 * for unix sockets we can't use the size of sockaddr_storage
820 * we would get EINVAL
822 if (bsda->u.sa.sa_family == AF_UNIX) {
823 sa_socklen = sizeof(bsda->u.un);
826 ret = recvfrom(bsds->fd, state->buf, state->len, 0, sa, &sa_socklen);
827 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
832 if (tevent_req_error(req, err)) {
836 if (ret != state->len) {
837 tevent_req_error(req, EIO);
841 tevent_req_done(req);
844 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
848 struct tsocket_address **src)
850 struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
851 struct tdgram_bsd_recvfrom_state);
854 ret = tsocket_simple_int_recv(req, perrno);
856 *buf = talloc_move(mem_ctx, &state->buf);
859 *src = talloc_move(mem_ctx, &state->src);
863 tevent_req_received(req);
867 struct tdgram_bsd_sendto_state {
868 struct tdgram_context *dgram;
872 const struct tsocket_address *dst;
877 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
879 struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
882 tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
887 static void tdgram_bsd_sendto_handler(void *private_data);
889 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
890 struct tevent_context *ev,
891 struct tdgram_context *dgram,
894 const struct tsocket_address *dst)
896 struct tevent_req *req;
897 struct tdgram_bsd_sendto_state *state;
898 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
901 req = tevent_req_create(mem_ctx, &state,
902 struct tdgram_bsd_sendto_state);
907 state->dgram = dgram;
913 talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
915 if (bsds->fd == -1) {
916 tevent_req_error(req, ENOTCONN);
921 * this is a fast path, not waiting for the
922 * socket to become explicit writeable gains
923 * about 10%-20% performance in benchmark tests.
925 tdgram_bsd_sendto_handler(req);
926 if (!tevent_req_is_in_progress(req)) {
930 ret = tdgram_bsd_set_writeable_handler(bsds, ev,
931 tdgram_bsd_sendto_handler,
934 tevent_req_error(req, errno);
941 tevent_req_post(req, ev);
945 static void tdgram_bsd_sendto_handler(void *private_data)
947 struct tevent_req *req = talloc_get_type_abort(private_data,
949 struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
950 struct tdgram_bsd_sendto_state);
951 struct tdgram_context *dgram = state->dgram;
952 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
953 struct sockaddr *sa = NULL;
954 socklen_t sa_socklen = 0;
960 struct tsocket_address_bsd *bsda =
961 talloc_get_type(state->dst->private_data,
962 struct tsocket_address_bsd);
965 sa_socklen = sizeof(bsda->u.ss);
967 * for unix sockets we can't use the size of sockaddr_storage
968 * we would get EINVAL
970 if (bsda->u.sa.sa_family == AF_UNIX) {
971 sa_socklen = sizeof(bsda->u.un);
975 ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_socklen);
976 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
981 if (tevent_req_error(req, err)) {
987 tevent_req_done(req);
990 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
992 struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
993 struct tdgram_bsd_sendto_state);
996 ret = tsocket_simple_int_recv(req, perrno);
1001 tevent_req_received(req);
1005 struct tdgram_bsd_disconnect_state {
1009 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1010 struct tevent_context *ev,
1011 struct tdgram_context *dgram)
1013 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1014 struct tevent_req *req;
1015 struct tdgram_bsd_disconnect_state *state;
1020 req = tevent_req_create(mem_ctx, &state,
1021 struct tdgram_bsd_disconnect_state);
1026 if (bsds->fd == -1) {
1027 tevent_req_error(req, ENOTCONN);
1031 ret = close(bsds->fd);
1033 err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1034 if (tevent_req_error(req, err)) {
1038 tevent_req_done(req);
1040 tevent_req_post(req, ev);
1044 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1049 ret = tsocket_simple_int_recv(req, perrno);
1051 tevent_req_received(req);
1055 static const struct tdgram_context_ops tdgram_bsd_ops = {
1058 .recvfrom_send = tdgram_bsd_recvfrom_send,
1059 .recvfrom_recv = tdgram_bsd_recvfrom_recv,
1061 .sendto_send = tdgram_bsd_sendto_send,
1062 .sendto_recv = tdgram_bsd_sendto_recv,
1064 .disconnect_send = tdgram_bsd_disconnect_send,
1065 .disconnect_recv = tdgram_bsd_disconnect_recv,
1068 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1070 TALLOC_FREE(bsds->fde);
1071 if (bsds->fd != -1) {
1078 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1079 const struct tsocket_address *remote,
1081 TALLOC_CTX *mem_ctx,
1082 struct tdgram_context **_dgram,
1083 const char *location)
1085 struct tsocket_address_bsd *lbsda =
1086 talloc_get_type_abort(local->private_data,
1087 struct tsocket_address_bsd);
1088 struct tsocket_address_bsd *rbsda = NULL;
1089 struct tdgram_context *dgram;
1090 struct tdgram_bsd *bsds;
1093 bool do_bind = false;
1094 bool do_reuseaddr = false;
1095 socklen_t sa_socklen = sizeof(lbsda->u.ss);
1098 rbsda = talloc_get_type_abort(remote->private_data,
1099 struct tsocket_address_bsd);
1102 switch (lbsda->u.sa.sa_family) {
1108 if (lbsda->u.un.sun_path[0] != 0) {
1109 do_reuseaddr = true;
1113 * for unix sockets we can't use the size of sockaddr_storage
1114 * we would get EINVAL
1116 sa_socklen = sizeof(lbsda->u.un);
1119 if (lbsda->u.in.sin_port != 0) {
1120 do_reuseaddr = true;
1123 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1129 if (lbsda->u.in6.sin6_port != 0) {
1130 do_reuseaddr = true;
1133 if (memcmp(&in6addr_any,
1134 &lbsda->u.in6.sin6_addr,
1135 sizeof(in6addr_any)) != 0) {
1145 fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
1150 fd = tsocket_bsd_common_prepare_fd(fd, true);
1155 dgram = tdgram_context_create(mem_ctx,
1161 int saved_errno = errno;
1163 errno = saved_errno;
1168 talloc_set_destructor(bsds, tdgram_bsd_destructor);
1173 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1174 (const void *)&val, sizeof(val));
1176 int saved_errno = errno;
1178 errno = saved_errno;
1186 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1187 (const void *)&val, sizeof(val));
1189 int saved_errno = errno;
1191 errno = saved_errno;
1197 ret = bind(fd, &lbsda->u.sa, sa_socklen);
1199 int saved_errno = errno;
1201 errno = saved_errno;
1207 ret = connect(fd, &rbsda->u.sa, sa_socklen);
1209 int saved_errno = errno;
1211 errno = saved_errno;
1220 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1221 const struct tsocket_address *remote,
1222 TALLOC_CTX *mem_ctx,
1223 struct tdgram_context **dgram,
1224 const char *location)
1226 struct tsocket_address_bsd *lbsda =
1227 talloc_get_type_abort(local->private_data,
1228 struct tsocket_address_bsd);
1231 switch (lbsda->u.sa.sa_family) {
1243 ret = tdgram_bsd_dgram_socket(local, remote, false,
1244 mem_ctx, dgram, location);
1249 int _tdgram_unix_socket(const struct tsocket_address *local,
1250 const struct tsocket_address *remote,
1251 TALLOC_CTX *mem_ctx,
1252 struct tdgram_context **dgram,
1253 const char *location)
1255 struct tsocket_address_bsd *lbsda =
1256 talloc_get_type_abort(local->private_data,
1257 struct tsocket_address_bsd);
1260 switch (lbsda->u.sa.sa_family) {
1268 ret = tdgram_bsd_dgram_socket(local, remote, false,
1269 mem_ctx, dgram, location);
1274 struct tstream_bsd {
1278 struct tevent_fd *fde;
1280 void *readable_private;
1281 void (*readable_handler)(void *private_data);
1282 void *writeable_private;
1283 void (*writeable_handler)(void *private_data);
1286 static void tstream_bsd_fde_handler(struct tevent_context *ev,
1287 struct tevent_fd *fde,
1291 struct tstream_bsd *bsds = talloc_get_type_abort(private_data,
1292 struct tstream_bsd);
1294 if (flags & TEVENT_FD_WRITE) {
1295 bsds->writeable_handler(bsds->writeable_private);
1298 if (flags & TEVENT_FD_READ) {
1299 if (!bsds->readable_handler) {
1300 if (bsds->writeable_handler) {
1301 bsds->writeable_handler(bsds->writeable_private);
1304 TEVENT_FD_NOT_READABLE(bsds->fde);
1307 bsds->readable_handler(bsds->readable_private);
1312 static int tstream_bsd_set_readable_handler(struct tstream_bsd *bsds,
1313 struct tevent_context *ev,
1314 void (*handler)(void *private_data),
1322 if (!bsds->readable_handler) {
1325 bsds->readable_handler = NULL;
1326 bsds->readable_private = NULL;
1331 /* read and write must use the same tevent_context */
1332 if (bsds->event_ptr != ev) {
1333 if (bsds->readable_handler || bsds->writeable_handler) {
1337 bsds->event_ptr = NULL;
1338 TALLOC_FREE(bsds->fde);
1341 if (tevent_fd_get_flags(bsds->fde) == 0) {
1342 TALLOC_FREE(bsds->fde);
1344 bsds->fde = tevent_add_fd(ev, bsds,
1345 bsds->fd, TEVENT_FD_READ,
1346 tstream_bsd_fde_handler,
1353 /* cache the event context we're running on */
1354 bsds->event_ptr = ev;
1355 } else if (!bsds->readable_handler) {
1356 TEVENT_FD_READABLE(bsds->fde);
1359 bsds->readable_handler = handler;
1360 bsds->readable_private = private_data;
1365 static int tstream_bsd_set_writeable_handler(struct tstream_bsd *bsds,
1366 struct tevent_context *ev,
1367 void (*handler)(void *private_data),
1375 if (!bsds->writeable_handler) {
1378 bsds->writeable_handler = NULL;
1379 bsds->writeable_private = NULL;
1380 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1385 /* read and write must use the same tevent_context */
1386 if (bsds->event_ptr != ev) {
1387 if (bsds->readable_handler || bsds->writeable_handler) {
1391 bsds->event_ptr = NULL;
1392 TALLOC_FREE(bsds->fde);
1395 if (tevent_fd_get_flags(bsds->fde) == 0) {
1396 TALLOC_FREE(bsds->fde);
1398 bsds->fde = tevent_add_fd(ev, bsds,
1400 TEVENT_FD_READ | TEVENT_FD_WRITE,
1401 tstream_bsd_fde_handler,
1408 /* cache the event context we're running on */
1409 bsds->event_ptr = ev;
1410 } else if (!bsds->writeable_handler) {
1411 uint16_t flags = tevent_fd_get_flags(bsds->fde);
1412 flags |= TEVENT_FD_READ | TEVENT_FD_WRITE;
1413 tevent_fd_set_flags(bsds->fde, flags);
1416 bsds->writeable_handler = handler;
1417 bsds->writeable_private = private_data;
1422 static ssize_t tstream_bsd_pending_bytes(struct tstream_context *stream)
1424 struct tstream_bsd *bsds = tstream_context_data(stream,
1425 struct tstream_bsd);
1428 if (bsds->fd == -1) {
1433 ret = tsocket_bsd_pending(bsds->fd);
1438 struct tstream_bsd_readv_state {
1439 struct tstream_context *stream;
1441 struct iovec *vector;
1447 static int tstream_bsd_readv_destructor(struct tstream_bsd_readv_state *state)
1449 struct tstream_bsd *bsds = tstream_context_data(state->stream,
1450 struct tstream_bsd);
1452 tstream_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1457 static void tstream_bsd_readv_handler(void *private_data);
1459 static struct tevent_req *tstream_bsd_readv_send(TALLOC_CTX *mem_ctx,
1460 struct tevent_context *ev,
1461 struct tstream_context *stream,
1462 struct iovec *vector,
1465 struct tevent_req *req;
1466 struct tstream_bsd_readv_state *state;
1467 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1470 req = tevent_req_create(mem_ctx, &state,
1471 struct tstream_bsd_readv_state);
1476 state->stream = stream;
1477 /* we make a copy of the vector so that we can modify it */
1478 state->vector = talloc_array(state, struct iovec, count);
1479 if (tevent_req_nomem(state->vector, req)) {
1482 memcpy(state->vector, vector, sizeof(struct iovec)*count);
1483 state->count = count;
1486 talloc_set_destructor(state, tstream_bsd_readv_destructor);
1488 if (bsds->fd == -1) {
1489 tevent_req_error(req, ENOTCONN);
1494 * this is a fast path, not waiting for the
1495 * socket to become explicit readable gains
1496 * about 10%-20% performance in benchmark tests.
1498 tstream_bsd_readv_handler(req);
1499 if (!tevent_req_is_in_progress(req)) {
1503 ret = tstream_bsd_set_readable_handler(bsds, ev,
1504 tstream_bsd_readv_handler,
1507 tevent_req_error(req, errno);
1514 tevent_req_post(req, ev);
1518 static void tstream_bsd_readv_handler(void *private_data)
1520 struct tevent_req *req = talloc_get_type_abort(private_data,
1522 struct tstream_bsd_readv_state *state = tevent_req_data(req,
1523 struct tstream_bsd_readv_state);
1524 struct tstream_context *stream = state->stream;
1525 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1530 ret = readv(bsds->fd, state->vector, state->count);
1532 /* propagate end of file */
1533 tevent_req_error(req, EPIPE);
1536 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1541 if (tevent_req_error(req, err)) {
1548 if (ret < state->vector[0].iov_len) {
1550 base = (uint8_t *)state->vector[0].iov_base;
1552 state->vector[0].iov_base = base;
1553 state->vector[0].iov_len -= ret;
1556 ret -= state->vector[0].iov_len;
1562 * there're maybe some empty vectors at the end
1563 * which we need to skip, otherwise we would get
1564 * ret == 0 from the readv() call and return EPIPE
1566 while (state->count > 0) {
1567 if (state->vector[0].iov_len > 0) {
1574 if (state->count > 0) {
1575 /* we have more to read */
1579 tevent_req_done(req);
1582 static int tstream_bsd_readv_recv(struct tevent_req *req,
1585 struct tstream_bsd_readv_state *state = tevent_req_data(req,
1586 struct tstream_bsd_readv_state);
1589 ret = tsocket_simple_int_recv(req, perrno);
1594 tevent_req_received(req);
1598 struct tstream_bsd_writev_state {
1599 struct tstream_context *stream;
1601 struct iovec *vector;
1607 static int tstream_bsd_writev_destructor(struct tstream_bsd_writev_state *state)
1609 struct tstream_bsd *bsds = tstream_context_data(state->stream,
1610 struct tstream_bsd);
1612 tstream_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1617 static void tstream_bsd_writev_handler(void *private_data);
1619 static struct tevent_req *tstream_bsd_writev_send(TALLOC_CTX *mem_ctx,
1620 struct tevent_context *ev,
1621 struct tstream_context *stream,
1622 const struct iovec *vector,
1625 struct tevent_req *req;
1626 struct tstream_bsd_writev_state *state;
1627 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1630 req = tevent_req_create(mem_ctx, &state,
1631 struct tstream_bsd_writev_state);
1636 state->stream = stream;
1637 /* we make a copy of the vector so that we can modify it */
1638 state->vector = talloc_array(state, struct iovec, count);
1639 if (tevent_req_nomem(state->vector, req)) {
1642 memcpy(state->vector, vector, sizeof(struct iovec)*count);
1643 state->count = count;
1646 talloc_set_destructor(state, tstream_bsd_writev_destructor);
1648 if (bsds->fd == -1) {
1649 tevent_req_error(req, ENOTCONN);
1654 * this is a fast path, not waiting for the
1655 * socket to become explicit writeable gains
1656 * about 10%-20% performance in benchmark tests.
1658 tstream_bsd_writev_handler(req);
1659 if (!tevent_req_is_in_progress(req)) {
1663 ret = tstream_bsd_set_writeable_handler(bsds, ev,
1664 tstream_bsd_writev_handler,
1667 tevent_req_error(req, errno);
1674 tevent_req_post(req, ev);
1678 static void tstream_bsd_writev_handler(void *private_data)
1680 struct tevent_req *req = talloc_get_type_abort(private_data,
1682 struct tstream_bsd_writev_state *state = tevent_req_data(req,
1683 struct tstream_bsd_writev_state);
1684 struct tstream_context *stream = state->stream;
1685 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1690 ret = writev(bsds->fd, state->vector, state->count);
1692 /* propagate end of file */
1693 tevent_req_error(req, EPIPE);
1696 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1701 if (tevent_req_error(req, err)) {
1708 if (ret < state->vector[0].iov_len) {
1710 base = (uint8_t *)state->vector[0].iov_base;
1712 state->vector[0].iov_base = base;
1713 state->vector[0].iov_len -= ret;
1716 ret -= state->vector[0].iov_len;
1722 * there're maybe some empty vectors at the end
1723 * which we need to skip, otherwise we would get
1724 * ret == 0 from the writev() call and return EPIPE
1726 while (state->count > 0) {
1727 if (state->vector[0].iov_len > 0) {
1734 if (state->count > 0) {
1735 /* we have more to read */
1739 tevent_req_done(req);
1742 static int tstream_bsd_writev_recv(struct tevent_req *req, int *perrno)
1744 struct tstream_bsd_writev_state *state = tevent_req_data(req,
1745 struct tstream_bsd_writev_state);
1748 ret = tsocket_simple_int_recv(req, perrno);
1753 tevent_req_received(req);
1757 struct tstream_bsd_disconnect_state {
1761 static struct tevent_req *tstream_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1762 struct tevent_context *ev,
1763 struct tstream_context *stream)
1765 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1766 struct tevent_req *req;
1767 struct tstream_bsd_disconnect_state *state;
1772 req = tevent_req_create(mem_ctx, &state,
1773 struct tstream_bsd_disconnect_state);
1778 if (bsds->fd == -1) {
1779 tevent_req_error(req, ENOTCONN);
1783 ret = close(bsds->fd);
1785 err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1786 if (tevent_req_error(req, err)) {
1790 tevent_req_done(req);
1792 tevent_req_post(req, ev);
1796 static int tstream_bsd_disconnect_recv(struct tevent_req *req,
1801 ret = tsocket_simple_int_recv(req, perrno);
1803 tevent_req_received(req);
1807 static const struct tstream_context_ops tstream_bsd_ops = {
1810 .pending_bytes = tstream_bsd_pending_bytes,
1812 .readv_send = tstream_bsd_readv_send,
1813 .readv_recv = tstream_bsd_readv_recv,
1815 .writev_send = tstream_bsd_writev_send,
1816 .writev_recv = tstream_bsd_writev_recv,
1818 .disconnect_send = tstream_bsd_disconnect_send,
1819 .disconnect_recv = tstream_bsd_disconnect_recv,
1822 static int tstream_bsd_destructor(struct tstream_bsd *bsds)
1824 TALLOC_FREE(bsds->fde);
1825 if (bsds->fd != -1) {
1832 int _tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
1834 struct tstream_context **_stream,
1835 const char *location)
1837 struct tstream_context *stream;
1838 struct tstream_bsd *bsds;
1840 stream = tstream_context_create(mem_ctx,
1850 talloc_set_destructor(bsds, tstream_bsd_destructor);
1856 struct tstream_bsd_connect_state {
1858 struct tevent_fd *fde;
1859 struct tstream_conext *stream;
1862 static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state *state)
1864 TALLOC_FREE(state->fde);
1865 if (state->fd != -1) {
1873 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
1874 struct tevent_fd *fde,
1876 void *private_data);
1878 static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
1879 struct tevent_context *ev,
1881 const struct tsocket_address *local,
1882 const struct tsocket_address *remote)
1884 struct tevent_req *req;
1885 struct tstream_bsd_connect_state *state;
1886 struct tsocket_address_bsd *lbsda =
1887 talloc_get_type_abort(local->private_data,
1888 struct tsocket_address_bsd);
1889 struct tsocket_address_bsd *rbsda =
1890 talloc_get_type_abort(remote->private_data,
1891 struct tsocket_address_bsd);
1895 bool do_bind = false;
1896 bool do_reuseaddr = false;
1897 socklen_t sa_socklen = sizeof(rbsda->u.ss);
1899 req = tevent_req_create(mem_ctx, &state,
1900 struct tstream_bsd_connect_state);
1907 talloc_set_destructor(state, tstream_bsd_connect_destructor);
1909 /* give the wrappers a chance to report an error */
1910 if (sys_errno != 0) {
1911 tevent_req_error(req, sys_errno);
1915 switch (lbsda->u.sa.sa_family) {
1917 if (lbsda->u.un.sun_path[0] != 0) {
1918 do_reuseaddr = true;
1922 * for unix sockets we can't use the size of sockaddr_storage
1923 * we would get EINVAL
1925 sa_socklen = sizeof(rbsda->u.un);
1928 if (lbsda->u.in.sin_port != 0) {
1929 do_reuseaddr = true;
1932 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1938 if (lbsda->u.in6.sin6_port != 0) {
1939 do_reuseaddr = true;
1942 if (memcmp(&in6addr_any,
1943 &lbsda->u.in6.sin6_addr,
1944 sizeof(in6addr_any)) != 0) {
1950 tevent_req_error(req, EINVAL);
1954 state->fd = socket(lbsda->u.sa.sa_family, SOCK_STREAM, 0);
1955 if (state->fd == -1) {
1956 tevent_req_error(req, errno);
1960 state->fd = tsocket_bsd_common_prepare_fd(state->fd, true);
1961 if (state->fd == -1) {
1962 tevent_req_error(req, errno);
1969 ret = setsockopt(state->fd, SOL_SOCKET, SO_REUSEADDR,
1970 (const void *)&val, sizeof(val));
1972 tevent_req_error(req, errno);
1978 ret = bind(state->fd, &lbsda->u.sa, sizeof(lbsda->u.ss));
1980 tevent_req_error(req, errno);
1985 ret = connect(state->fd, &rbsda->u.sa, sa_socklen);
1986 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1991 if (tevent_req_error(req, err)) {
1995 tevent_req_done(req);
1999 state->fde = tevent_add_fd(ev, state,
2001 TEVENT_FD_READ | TEVENT_FD_WRITE,
2002 tstream_bsd_connect_fde_handler,
2004 if (tevent_req_nomem(state->fde, req)) {
2011 tevent_req_post(req, ev);
2015 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
2016 struct tevent_fd *fde,
2020 struct tevent_req *req = talloc_get_type_abort(private_data,
2022 struct tstream_bsd_connect_state *state = tevent_req_data(req,
2023 struct tstream_bsd_connect_state);
2026 socklen_t len = sizeof(error);
2030 ret = getsockopt(state->fd, SOL_SOCKET, SO_ERROR, &error, &len);
2037 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2042 if (tevent_req_error(req, err)) {
2046 tevent_req_done(req);
2049 static int tstream_bsd_connect_recv(struct tevent_req *req,
2051 TALLOC_CTX *mem_ctx,
2052 struct tstream_context **stream,
2053 const char *location)
2055 struct tstream_bsd_connect_state *state = tevent_req_data(req,
2056 struct tstream_bsd_connect_state);
2059 ret = tsocket_simple_int_recv(req, perrno);
2061 ret = _tstream_bsd_existing_socket(mem_ctx,
2069 TALLOC_FREE(state->fde);
2074 tevent_req_received(req);
2078 struct tevent_req * tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
2079 struct tevent_context *ev,
2080 const struct tsocket_address *local,
2081 const struct tsocket_address *remote)
2083 struct tsocket_address_bsd *lbsda =
2084 talloc_get_type_abort(local->private_data,
2085 struct tsocket_address_bsd);
2086 struct tevent_req *req;
2089 switch (lbsda->u.sa.sa_family) {
2101 req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2106 int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
2108 TALLOC_CTX *mem_ctx,
2109 struct tstream_context **stream,
2110 const char *location)
2112 return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
2115 struct tevent_req * tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
2116 struct tevent_context *ev,
2117 const struct tsocket_address *local,
2118 const struct tsocket_address *remote)
2120 struct tsocket_address_bsd *lbsda =
2121 talloc_get_type_abort(local->private_data,
2122 struct tsocket_address_bsd);
2123 struct tevent_req *req;
2126 switch (lbsda->u.sa.sa_family) {
2134 req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2139 int _tstream_unix_connect_recv(struct tevent_req *req,
2141 TALLOC_CTX *mem_ctx,
2142 struct tstream_context **stream,
2143 const char *location)
2145 return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
2148 int _tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
2149 struct tstream_context **_stream1,
2150 TALLOC_CTX *mem_ctx2,
2151 struct tstream_context **_stream2,
2152 const char *location)
2158 struct tstream_context *stream1 = NULL;
2159 struct tstream_context *stream2 = NULL;
2161 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
2168 fd1 = tsocket_bsd_common_prepare_fd(fd1, true);
2170 int sys_errno = errno;
2176 fd2 = tsocket_bsd_common_prepare_fd(fd2, true);
2178 int sys_errno = errno;
2184 ret = _tstream_bsd_existing_socket(mem_ctx1,
2189 int sys_errno = errno;
2196 ret = _tstream_bsd_existing_socket(mem_ctx2,
2201 int sys_errno = errno;
2202 talloc_free(stream1);
2208 *_stream1 = stream1;
2209 *_stream2 = stream2;