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"
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 int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
207 struct tsocket_address **_addr,
208 const char *location)
210 struct tsocket_address *addr;
211 struct tsocket_address_bsd *bsda;
213 if (sa_socklen < sizeof(sa->sa_family)) {
218 switch (sa->sa_family) {
222 if (sa_socklen < sizeof(struct sockaddr_in)) {
229 if (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 tsocket_address_bsd,
257 memcpy(&bsda->u.ss, sa, sa_socklen);
263 ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
267 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
268 struct tsocket_address_bsd);
276 switch (bsda->u.sa.sa_family) {
278 rlen = sizeof(struct sockaddr_un);
281 rlen = sizeof(struct sockaddr_in);
285 rlen = sizeof(struct sockaddr_in6);
289 errno = EAFNOSUPPORT;
293 if (sa_socklen < rlen) {
298 if (sa_socklen > sizeof(struct sockaddr_storage)) {
299 memset(sa, 0, sa_socklen);
300 sa_socklen = sizeof(struct sockaddr_storage);
303 memcpy(sa, &bsda->u.ss, sa_socklen);
307 int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
311 struct tsocket_address **_addr,
312 const char *location)
314 struct addrinfo hints;
315 struct addrinfo *result = NULL;
321 * we use SOCKET_STREAM here to get just one result
322 * back from getaddrinfo().
324 hints.ai_socktype = SOCK_STREAM;
325 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
327 if (strcasecmp(fam, "ip") == 0) {
328 hints.ai_family = AF_UNSPEC;
336 } else if (strcasecmp(fam, "ipv4") == 0) {
337 hints.ai_family = AF_INET;
342 } else if (strcasecmp(fam, "ipv6") == 0) {
343 hints.ai_family = AF_INET6;
349 errno = EAFNOSUPPORT;
353 snprintf(port_str, sizeof(port_str) - 1, "%u", port);
355 ret = getaddrinfo(addr, port_str, &hints, &result);
366 if (result->ai_socktype != SOCK_STREAM) {
372 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
380 freeaddrinfo(result);
385 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
388 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
389 struct tsocket_address_bsd);
390 char addr_str[INET6_ADDRSTRLEN+1];
398 switch (bsda->u.sa.sa_family) {
400 str = inet_ntop(bsda->u.in.sin_family,
401 &bsda->u.in.sin_addr,
402 addr_str, sizeof(addr_str));
406 str = inet_ntop(bsda->u.in6.sin6_family,
407 &bsda->u.in6.sin6_addr,
408 addr_str, sizeof(addr_str));
420 return talloc_strdup(mem_ctx, str);
423 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
425 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
426 struct tsocket_address_bsd);
434 switch (bsda->u.sa.sa_family) {
436 port = ntohs(bsda->u.in.sin_port);
440 port = ntohs(bsda->u.in6.sin6_port);
451 int tsocket_address_inet_set_port(struct tsocket_address *addr,
454 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
455 struct tsocket_address_bsd);
462 switch (bsda->u.sa.sa_family) {
464 bsda->u.in.sin_port = htons(port);
468 bsda->u.in6.sin6_port = htons(port);
479 int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
481 struct tsocket_address **_addr,
482 const char *location)
484 struct sockaddr_un un;
492 if (strlen(path) > sizeof(un.sun_path)-1) {
493 errno = ENAMETOOLONG;
498 un.sun_family = AF_UNIX;
499 strncpy(un.sun_path, path, sizeof(un.sun_path)-1);
501 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
502 (struct sockaddr *)p,
510 char *tsocket_address_unix_path(const struct tsocket_address *addr,
513 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
514 struct tsocket_address_bsd);
522 switch (bsda->u.sa.sa_family) {
524 str = bsda->u.un.sun_path;
531 return talloc_strdup(mem_ctx, str);
534 static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
537 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
538 struct tsocket_address_bsd);
541 const char *prefix = NULL;
544 switch (bsda->u.sa.sa_family) {
546 return talloc_asprintf(mem_ctx, "unix:%s",
547 bsda->u.un.sun_path);
561 addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
566 port = tsocket_address_inet_port(addr);
568 str = talloc_asprintf(mem_ctx, "%s:%s:%u",
569 prefix, addr_str, port);
570 talloc_free(addr_str);
575 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
577 const char *location)
579 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
580 struct tsocket_address_bsd);
581 struct tsocket_address *copy;
584 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
596 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
598 .string = tsocket_address_bsd_string,
599 .copy = tsocket_address_bsd_copy,
606 struct tevent_fd *fde;
608 void *readable_private;
609 void (*readable_handler)(void *private_data);
610 void *writeable_private;
611 void (*writeable_handler)(void *private_data);
614 static void tdgram_bsd_fde_handler(struct tevent_context *ev,
615 struct tevent_fd *fde,
619 struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
622 if (flags & TEVENT_FD_WRITE) {
623 bsds->writeable_handler(bsds->writeable_private);
626 if (flags & TEVENT_FD_READ) {
627 if (!bsds->readable_handler) {
628 TEVENT_FD_NOT_READABLE(bsds->fde);
631 bsds->readable_handler(bsds->readable_private);
636 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
637 struct tevent_context *ev,
638 void (*handler)(void *private_data),
646 if (!bsds->readable_handler) {
649 bsds->readable_handler = NULL;
650 bsds->readable_private = NULL;
655 /* read and write must use the same tevent_context */
656 if (bsds->event_ptr != ev) {
657 if (bsds->readable_handler || bsds->writeable_handler) {
661 bsds->event_ptr = NULL;
662 TALLOC_FREE(bsds->fde);
665 if (tevent_fd_get_flags(bsds->fde) == 0) {
666 TALLOC_FREE(bsds->fde);
668 bsds->fde = tevent_add_fd(ev, bsds,
669 bsds->fd, TEVENT_FD_READ,
670 tdgram_bsd_fde_handler,
677 /* cache the event context we're running on */
678 bsds->event_ptr = ev;
679 } else if (!bsds->readable_handler) {
680 TEVENT_FD_READABLE(bsds->fde);
683 bsds->readable_handler = handler;
684 bsds->readable_private = private_data;
689 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
690 struct tevent_context *ev,
691 void (*handler)(void *private_data),
699 if (!bsds->writeable_handler) {
702 bsds->writeable_handler = NULL;
703 bsds->writeable_private = NULL;
704 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
709 /* read and write must use the same tevent_context */
710 if (bsds->event_ptr != ev) {
711 if (bsds->readable_handler || bsds->writeable_handler) {
715 bsds->event_ptr = NULL;
716 TALLOC_FREE(bsds->fde);
719 if (tevent_fd_get_flags(bsds->fde) == 0) {
720 TALLOC_FREE(bsds->fde);
722 bsds->fde = tevent_add_fd(ev, bsds,
723 bsds->fd, TEVENT_FD_WRITE,
724 tdgram_bsd_fde_handler,
731 /* cache the event context we're running on */
732 bsds->event_ptr = ev;
733 } else if (!bsds->writeable_handler) {
734 TEVENT_FD_WRITEABLE(bsds->fde);
737 bsds->writeable_handler = handler;
738 bsds->writeable_private = private_data;
743 struct tdgram_bsd_recvfrom_state {
744 struct tdgram_context *dgram;
748 struct tsocket_address *src;
751 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
753 struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
756 tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
761 static void tdgram_bsd_recvfrom_handler(void *private_data);
763 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
764 struct tevent_context *ev,
765 struct tdgram_context *dgram)
767 struct tevent_req *req;
768 struct tdgram_bsd_recvfrom_state *state;
769 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
772 req = tevent_req_create(mem_ctx, &state,
773 struct tdgram_bsd_recvfrom_state);
778 state->dgram = dgram;
783 talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
785 if (bsds->fd == -1) {
786 tevent_req_error(req, ENOTCONN);
791 * this is a fast path, not waiting for the
792 * socket to become explicit readable gains
793 * about 10%-20% performance in benchmark tests.
795 tdgram_bsd_recvfrom_handler(req);
796 if (!tevent_req_is_in_progress(req)) {
800 ret = tdgram_bsd_set_readable_handler(bsds, ev,
801 tdgram_bsd_recvfrom_handler,
804 tevent_req_error(req, errno);
811 tevent_req_post(req, ev);
815 static void tdgram_bsd_recvfrom_handler(void *private_data)
817 struct tevent_req *req = talloc_get_type_abort(private_data,
819 struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
820 struct tdgram_bsd_recvfrom_state);
821 struct tdgram_context *dgram = state->dgram;
822 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
823 struct tsocket_address_bsd *bsda;
825 struct sockaddr *sa = NULL;
826 socklen_t sa_socklen = 0;
830 ret = tsocket_bsd_pending(bsds->fd);
835 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
840 if (tevent_req_error(req, err)) {
844 state->buf = talloc_array(state, uint8_t, ret);
845 if (tevent_req_nomem(state->buf, req)) {
850 state->src = tsocket_address_create(state,
851 &tsocket_address_bsd_ops,
853 struct tsocket_address_bsd,
854 __location__ "bsd_recvfrom");
855 if (tevent_req_nomem(state->src, req)) {
862 sa_socklen = sizeof(bsda->u.ss);
864 * for unix sockets we can't use the size of sockaddr_storage
865 * we would get EINVAL
867 if (bsda->u.sa.sa_family == AF_UNIX) {
868 sa_socklen = sizeof(bsda->u.un);
871 ret = recvfrom(bsds->fd, state->buf, state->len, 0, sa, &sa_socklen);
872 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
877 if (tevent_req_error(req, err)) {
881 if (ret != state->len) {
882 tevent_req_error(req, EIO);
886 tevent_req_done(req);
889 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
893 struct tsocket_address **src)
895 struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
896 struct tdgram_bsd_recvfrom_state);
899 ret = tsocket_simple_int_recv(req, perrno);
901 *buf = talloc_move(mem_ctx, &state->buf);
904 *src = talloc_move(mem_ctx, &state->src);
908 tevent_req_received(req);
912 struct tdgram_bsd_sendto_state {
913 struct tdgram_context *dgram;
917 const struct tsocket_address *dst;
922 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
924 struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
927 tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
932 static void tdgram_bsd_sendto_handler(void *private_data);
934 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
935 struct tevent_context *ev,
936 struct tdgram_context *dgram,
939 const struct tsocket_address *dst)
941 struct tevent_req *req;
942 struct tdgram_bsd_sendto_state *state;
943 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
946 req = tevent_req_create(mem_ctx, &state,
947 struct tdgram_bsd_sendto_state);
952 state->dgram = dgram;
958 talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
960 if (bsds->fd == -1) {
961 tevent_req_error(req, ENOTCONN);
966 * this is a fast path, not waiting for the
967 * socket to become explicit writeable gains
968 * about 10%-20% performance in benchmark tests.
970 tdgram_bsd_sendto_handler(req);
971 if (!tevent_req_is_in_progress(req)) {
975 ret = tdgram_bsd_set_writeable_handler(bsds, ev,
976 tdgram_bsd_sendto_handler,
979 tevent_req_error(req, errno);
986 tevent_req_post(req, ev);
990 static void tdgram_bsd_sendto_handler(void *private_data)
992 struct tevent_req *req = talloc_get_type_abort(private_data,
994 struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
995 struct tdgram_bsd_sendto_state);
996 struct tdgram_context *dgram = state->dgram;
997 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
998 struct sockaddr *sa = NULL;
999 socklen_t sa_socklen = 0;
1005 struct tsocket_address_bsd *bsda =
1006 talloc_get_type(state->dst->private_data,
1007 struct tsocket_address_bsd);
1010 sa_socklen = sizeof(bsda->u.ss);
1012 * for unix sockets we can't use the size of sockaddr_storage
1013 * we would get EINVAL
1015 if (bsda->u.sa.sa_family == AF_UNIX) {
1016 sa_socklen = sizeof(bsda->u.un);
1020 ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_socklen);
1021 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1026 if (tevent_req_error(req, err)) {
1032 tevent_req_done(req);
1035 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
1037 struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1038 struct tdgram_bsd_sendto_state);
1041 ret = tsocket_simple_int_recv(req, perrno);
1046 tevent_req_received(req);
1050 struct tdgram_bsd_disconnect_state {
1054 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1055 struct tevent_context *ev,
1056 struct tdgram_context *dgram)
1058 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1059 struct tevent_req *req;
1060 struct tdgram_bsd_disconnect_state *state;
1065 req = tevent_req_create(mem_ctx, &state,
1066 struct tdgram_bsd_disconnect_state);
1071 if (bsds->fd == -1) {
1072 tevent_req_error(req, ENOTCONN);
1076 ret = close(bsds->fd);
1078 err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1079 if (tevent_req_error(req, err)) {
1083 tevent_req_done(req);
1085 tevent_req_post(req, ev);
1089 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1094 ret = tsocket_simple_int_recv(req, perrno);
1096 tevent_req_received(req);
1100 static const struct tdgram_context_ops tdgram_bsd_ops = {
1103 .recvfrom_send = tdgram_bsd_recvfrom_send,
1104 .recvfrom_recv = tdgram_bsd_recvfrom_recv,
1106 .sendto_send = tdgram_bsd_sendto_send,
1107 .sendto_recv = tdgram_bsd_sendto_recv,
1109 .disconnect_send = tdgram_bsd_disconnect_send,
1110 .disconnect_recv = tdgram_bsd_disconnect_recv,
1113 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1115 TALLOC_FREE(bsds->fde);
1116 if (bsds->fd != -1) {
1123 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1124 const struct tsocket_address *remote,
1126 TALLOC_CTX *mem_ctx,
1127 struct tdgram_context **_dgram,
1128 const char *location)
1130 struct tsocket_address_bsd *lbsda =
1131 talloc_get_type_abort(local->private_data,
1132 struct tsocket_address_bsd);
1133 struct tsocket_address_bsd *rbsda = NULL;
1134 struct tdgram_context *dgram;
1135 struct tdgram_bsd *bsds;
1138 bool do_bind = false;
1139 bool do_reuseaddr = false;
1140 socklen_t sa_socklen = sizeof(lbsda->u.ss);
1143 rbsda = talloc_get_type_abort(remote->private_data,
1144 struct tsocket_address_bsd);
1147 switch (lbsda->u.sa.sa_family) {
1153 if (lbsda->u.un.sun_path[0] != 0) {
1154 do_reuseaddr = true;
1158 * for unix sockets we can't use the size of sockaddr_storage
1159 * we would get EINVAL
1161 sa_socklen = sizeof(lbsda->u.un);
1164 if (lbsda->u.in.sin_port != 0) {
1165 do_reuseaddr = true;
1168 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1174 if (lbsda->u.in6.sin6_port != 0) {
1175 do_reuseaddr = true;
1178 if (memcmp(&in6addr_any,
1179 &lbsda->u.in6.sin6_addr,
1180 sizeof(in6addr_any)) != 0) {
1190 fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
1195 fd = tsocket_bsd_common_prepare_fd(fd, true);
1200 dgram = tdgram_context_create(mem_ctx,
1206 int saved_errno = errno;
1208 errno = saved_errno;
1213 talloc_set_destructor(bsds, tdgram_bsd_destructor);
1218 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1219 (const void *)&val, sizeof(val));
1221 int saved_errno = errno;
1223 errno = saved_errno;
1231 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1232 (const void *)&val, sizeof(val));
1234 int saved_errno = errno;
1236 errno = saved_errno;
1242 ret = bind(fd, &lbsda->u.sa, sa_socklen);
1244 int saved_errno = errno;
1246 errno = saved_errno;
1252 ret = connect(fd, &rbsda->u.sa, sa_socklen);
1254 int saved_errno = errno;
1256 errno = saved_errno;
1265 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1266 const struct tsocket_address *remote,
1267 TALLOC_CTX *mem_ctx,
1268 struct tdgram_context **dgram,
1269 const char *location)
1271 struct tsocket_address_bsd *lbsda =
1272 talloc_get_type_abort(local->private_data,
1273 struct tsocket_address_bsd);
1276 switch (lbsda->u.sa.sa_family) {
1288 ret = tdgram_bsd_dgram_socket(local, remote, false,
1289 mem_ctx, dgram, location);
1294 int _tdgram_unix_socket(const struct tsocket_address *local,
1295 const struct tsocket_address *remote,
1296 TALLOC_CTX *mem_ctx,
1297 struct tdgram_context **dgram,
1298 const char *location)
1300 struct tsocket_address_bsd *lbsda =
1301 talloc_get_type_abort(local->private_data,
1302 struct tsocket_address_bsd);
1305 switch (lbsda->u.sa.sa_family) {
1313 ret = tdgram_bsd_dgram_socket(local, remote, false,
1314 mem_ctx, dgram, location);
1319 struct tstream_bsd {
1323 struct tevent_fd *fde;
1325 void *readable_private;
1326 void (*readable_handler)(void *private_data);
1327 void *writeable_private;
1328 void (*writeable_handler)(void *private_data);
1331 static void tstream_bsd_fde_handler(struct tevent_context *ev,
1332 struct tevent_fd *fde,
1336 struct tstream_bsd *bsds = talloc_get_type_abort(private_data,
1337 struct tstream_bsd);
1339 if (flags & TEVENT_FD_WRITE) {
1340 bsds->writeable_handler(bsds->writeable_private);
1343 if (flags & TEVENT_FD_READ) {
1344 if (!bsds->readable_handler) {
1345 if (bsds->writeable_handler) {
1346 bsds->writeable_handler(bsds->writeable_private);
1349 TEVENT_FD_NOT_READABLE(bsds->fde);
1352 bsds->readable_handler(bsds->readable_private);
1357 static int tstream_bsd_set_readable_handler(struct tstream_bsd *bsds,
1358 struct tevent_context *ev,
1359 void (*handler)(void *private_data),
1367 if (!bsds->readable_handler) {
1370 bsds->readable_handler = NULL;
1371 bsds->readable_private = NULL;
1376 /* read and write must use the same tevent_context */
1377 if (bsds->event_ptr != ev) {
1378 if (bsds->readable_handler || bsds->writeable_handler) {
1382 bsds->event_ptr = NULL;
1383 TALLOC_FREE(bsds->fde);
1386 if (tevent_fd_get_flags(bsds->fde) == 0) {
1387 TALLOC_FREE(bsds->fde);
1389 bsds->fde = tevent_add_fd(ev, bsds,
1390 bsds->fd, TEVENT_FD_READ,
1391 tstream_bsd_fde_handler,
1398 /* cache the event context we're running on */
1399 bsds->event_ptr = ev;
1400 } else if (!bsds->readable_handler) {
1401 TEVENT_FD_READABLE(bsds->fde);
1404 bsds->readable_handler = handler;
1405 bsds->readable_private = private_data;
1410 static int tstream_bsd_set_writeable_handler(struct tstream_bsd *bsds,
1411 struct tevent_context *ev,
1412 void (*handler)(void *private_data),
1420 if (!bsds->writeable_handler) {
1423 bsds->writeable_handler = NULL;
1424 bsds->writeable_private = NULL;
1425 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1430 /* read and write must use the same tevent_context */
1431 if (bsds->event_ptr != ev) {
1432 if (bsds->readable_handler || bsds->writeable_handler) {
1436 bsds->event_ptr = NULL;
1437 TALLOC_FREE(bsds->fde);
1440 if (tevent_fd_get_flags(bsds->fde) == 0) {
1441 TALLOC_FREE(bsds->fde);
1443 bsds->fde = tevent_add_fd(ev, bsds,
1445 TEVENT_FD_READ | TEVENT_FD_WRITE,
1446 tstream_bsd_fde_handler,
1453 /* cache the event context we're running on */
1454 bsds->event_ptr = ev;
1455 } else if (!bsds->writeable_handler) {
1456 uint16_t flags = tevent_fd_get_flags(bsds->fde);
1457 flags |= TEVENT_FD_READ | TEVENT_FD_WRITE;
1458 tevent_fd_set_flags(bsds->fde, flags);
1461 bsds->writeable_handler = handler;
1462 bsds->writeable_private = private_data;
1467 static ssize_t tstream_bsd_pending_bytes(struct tstream_context *stream)
1469 struct tstream_bsd *bsds = tstream_context_data(stream,
1470 struct tstream_bsd);
1473 if (bsds->fd == -1) {
1478 ret = tsocket_bsd_pending(bsds->fd);
1483 struct tstream_bsd_readv_state {
1484 struct tstream_context *stream;
1486 struct iovec *vector;
1492 static int tstream_bsd_readv_destructor(struct tstream_bsd_readv_state *state)
1494 struct tstream_bsd *bsds = tstream_context_data(state->stream,
1495 struct tstream_bsd);
1497 tstream_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1502 static void tstream_bsd_readv_handler(void *private_data);
1504 static struct tevent_req *tstream_bsd_readv_send(TALLOC_CTX *mem_ctx,
1505 struct tevent_context *ev,
1506 struct tstream_context *stream,
1507 struct iovec *vector,
1510 struct tevent_req *req;
1511 struct tstream_bsd_readv_state *state;
1512 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1515 req = tevent_req_create(mem_ctx, &state,
1516 struct tstream_bsd_readv_state);
1521 state->stream = stream;
1522 /* we make a copy of the vector so that we can modify it */
1523 state->vector = talloc_array(state, struct iovec, count);
1524 if (tevent_req_nomem(state->vector, req)) {
1527 memcpy(state->vector, vector, sizeof(struct iovec)*count);
1528 state->count = count;
1531 talloc_set_destructor(state, tstream_bsd_readv_destructor);
1533 if (bsds->fd == -1) {
1534 tevent_req_error(req, ENOTCONN);
1539 * this is a fast path, not waiting for the
1540 * socket to become explicit readable gains
1541 * about 10%-20% performance in benchmark tests.
1543 tstream_bsd_readv_handler(req);
1544 if (!tevent_req_is_in_progress(req)) {
1548 ret = tstream_bsd_set_readable_handler(bsds, ev,
1549 tstream_bsd_readv_handler,
1552 tevent_req_error(req, errno);
1559 tevent_req_post(req, ev);
1563 static void tstream_bsd_readv_handler(void *private_data)
1565 struct tevent_req *req = talloc_get_type_abort(private_data,
1567 struct tstream_bsd_readv_state *state = tevent_req_data(req,
1568 struct tstream_bsd_readv_state);
1569 struct tstream_context *stream = state->stream;
1570 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1575 ret = readv(bsds->fd, state->vector, state->count);
1577 /* propagate end of file */
1578 tevent_req_error(req, EPIPE);
1581 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1586 if (tevent_req_error(req, err)) {
1593 if (ret < state->vector[0].iov_len) {
1595 base = (uint8_t *)state->vector[0].iov_base;
1597 state->vector[0].iov_base = base;
1598 state->vector[0].iov_len -= ret;
1601 ret -= state->vector[0].iov_len;
1607 * there're maybe some empty vectors at the end
1608 * which we need to skip, otherwise we would get
1609 * ret == 0 from the readv() call and return EPIPE
1611 while (state->count > 0) {
1612 if (state->vector[0].iov_len > 0) {
1619 if (state->count > 0) {
1620 /* we have more to read */
1624 tevent_req_done(req);
1627 static int tstream_bsd_readv_recv(struct tevent_req *req,
1630 struct tstream_bsd_readv_state *state = tevent_req_data(req,
1631 struct tstream_bsd_readv_state);
1634 ret = tsocket_simple_int_recv(req, perrno);
1639 tevent_req_received(req);
1643 struct tstream_bsd_writev_state {
1644 struct tstream_context *stream;
1646 struct iovec *vector;
1652 static int tstream_bsd_writev_destructor(struct tstream_bsd_writev_state *state)
1654 struct tstream_bsd *bsds = tstream_context_data(state->stream,
1655 struct tstream_bsd);
1657 tstream_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1662 static void tstream_bsd_writev_handler(void *private_data);
1664 static struct tevent_req *tstream_bsd_writev_send(TALLOC_CTX *mem_ctx,
1665 struct tevent_context *ev,
1666 struct tstream_context *stream,
1667 const struct iovec *vector,
1670 struct tevent_req *req;
1671 struct tstream_bsd_writev_state *state;
1672 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1675 req = tevent_req_create(mem_ctx, &state,
1676 struct tstream_bsd_writev_state);
1681 state->stream = stream;
1682 /* we make a copy of the vector so that we can modify it */
1683 state->vector = talloc_array(state, struct iovec, count);
1684 if (tevent_req_nomem(state->vector, req)) {
1687 memcpy(state->vector, vector, sizeof(struct iovec)*count);
1688 state->count = count;
1691 talloc_set_destructor(state, tstream_bsd_writev_destructor);
1693 if (bsds->fd == -1) {
1694 tevent_req_error(req, ENOTCONN);
1699 * this is a fast path, not waiting for the
1700 * socket to become explicit writeable gains
1701 * about 10%-20% performance in benchmark tests.
1703 tstream_bsd_writev_handler(req);
1704 if (!tevent_req_is_in_progress(req)) {
1708 ret = tstream_bsd_set_writeable_handler(bsds, ev,
1709 tstream_bsd_writev_handler,
1712 tevent_req_error(req, errno);
1719 tevent_req_post(req, ev);
1723 static void tstream_bsd_writev_handler(void *private_data)
1725 struct tevent_req *req = talloc_get_type_abort(private_data,
1727 struct tstream_bsd_writev_state *state = tevent_req_data(req,
1728 struct tstream_bsd_writev_state);
1729 struct tstream_context *stream = state->stream;
1730 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1735 ret = writev(bsds->fd, state->vector, state->count);
1737 /* propagate end of file */
1738 tevent_req_error(req, EPIPE);
1741 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1746 if (tevent_req_error(req, err)) {
1753 if (ret < state->vector[0].iov_len) {
1755 base = (uint8_t *)state->vector[0].iov_base;
1757 state->vector[0].iov_base = base;
1758 state->vector[0].iov_len -= ret;
1761 ret -= state->vector[0].iov_len;
1767 * there're maybe some empty vectors at the end
1768 * which we need to skip, otherwise we would get
1769 * ret == 0 from the writev() call and return EPIPE
1771 while (state->count > 0) {
1772 if (state->vector[0].iov_len > 0) {
1779 if (state->count > 0) {
1780 /* we have more to read */
1784 tevent_req_done(req);
1787 static int tstream_bsd_writev_recv(struct tevent_req *req, int *perrno)
1789 struct tstream_bsd_writev_state *state = tevent_req_data(req,
1790 struct tstream_bsd_writev_state);
1793 ret = tsocket_simple_int_recv(req, perrno);
1798 tevent_req_received(req);
1802 struct tstream_bsd_disconnect_state {
1806 static struct tevent_req *tstream_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1807 struct tevent_context *ev,
1808 struct tstream_context *stream)
1810 struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
1811 struct tevent_req *req;
1812 struct tstream_bsd_disconnect_state *state;
1817 req = tevent_req_create(mem_ctx, &state,
1818 struct tstream_bsd_disconnect_state);
1823 if (bsds->fd == -1) {
1824 tevent_req_error(req, ENOTCONN);
1828 ret = close(bsds->fd);
1830 err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1831 if (tevent_req_error(req, err)) {
1835 tevent_req_done(req);
1837 tevent_req_post(req, ev);
1841 static int tstream_bsd_disconnect_recv(struct tevent_req *req,
1846 ret = tsocket_simple_int_recv(req, perrno);
1848 tevent_req_received(req);
1852 static const struct tstream_context_ops tstream_bsd_ops = {
1855 .pending_bytes = tstream_bsd_pending_bytes,
1857 .readv_send = tstream_bsd_readv_send,
1858 .readv_recv = tstream_bsd_readv_recv,
1860 .writev_send = tstream_bsd_writev_send,
1861 .writev_recv = tstream_bsd_writev_recv,
1863 .disconnect_send = tstream_bsd_disconnect_send,
1864 .disconnect_recv = tstream_bsd_disconnect_recv,
1867 static int tstream_bsd_destructor(struct tstream_bsd *bsds)
1869 TALLOC_FREE(bsds->fde);
1870 if (bsds->fd != -1) {
1877 int _tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
1879 struct tstream_context **_stream,
1880 const char *location)
1882 struct tstream_context *stream;
1883 struct tstream_bsd *bsds;
1885 stream = tstream_context_create(mem_ctx,
1895 talloc_set_destructor(bsds, tstream_bsd_destructor);
1901 struct tstream_bsd_connect_state {
1903 struct tevent_fd *fde;
1904 struct tstream_conext *stream;
1907 static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state *state)
1909 TALLOC_FREE(state->fde);
1910 if (state->fd != -1) {
1918 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
1919 struct tevent_fd *fde,
1921 void *private_data);
1923 static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
1924 struct tevent_context *ev,
1926 const struct tsocket_address *local,
1927 const struct tsocket_address *remote)
1929 struct tevent_req *req;
1930 struct tstream_bsd_connect_state *state;
1931 struct tsocket_address_bsd *lbsda =
1932 talloc_get_type_abort(local->private_data,
1933 struct tsocket_address_bsd);
1934 struct tsocket_address_bsd *rbsda =
1935 talloc_get_type_abort(remote->private_data,
1936 struct tsocket_address_bsd);
1940 bool do_bind = false;
1941 bool do_reuseaddr = false;
1942 socklen_t sa_socklen = sizeof(rbsda->u.ss);
1944 req = tevent_req_create(mem_ctx, &state,
1945 struct tstream_bsd_connect_state);
1952 talloc_set_destructor(state, tstream_bsd_connect_destructor);
1954 /* give the wrappers a chance to report an error */
1955 if (sys_errno != 0) {
1956 tevent_req_error(req, sys_errno);
1960 switch (lbsda->u.sa.sa_family) {
1962 if (lbsda->u.un.sun_path[0] != 0) {
1963 do_reuseaddr = true;
1967 * for unix sockets we can't use the size of sockaddr_storage
1968 * we would get EINVAL
1970 sa_socklen = sizeof(rbsda->u.un);
1973 if (lbsda->u.in.sin_port != 0) {
1974 do_reuseaddr = true;
1977 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1983 if (lbsda->u.in6.sin6_port != 0) {
1984 do_reuseaddr = true;
1987 if (memcmp(&in6addr_any,
1988 &lbsda->u.in6.sin6_addr,
1989 sizeof(in6addr_any)) != 0) {
1995 tevent_req_error(req, EINVAL);
1999 state->fd = socket(lbsda->u.sa.sa_family, SOCK_STREAM, 0);
2000 if (state->fd == -1) {
2001 tevent_req_error(req, errno);
2005 state->fd = tsocket_bsd_common_prepare_fd(state->fd, true);
2006 if (state->fd == -1) {
2007 tevent_req_error(req, errno);
2014 ret = setsockopt(state->fd, SOL_SOCKET, SO_REUSEADDR,
2015 (const void *)&val, sizeof(val));
2017 tevent_req_error(req, errno);
2023 ret = bind(state->fd, &lbsda->u.sa, sizeof(lbsda->u.ss));
2025 tevent_req_error(req, errno);
2030 ret = connect(state->fd, &rbsda->u.sa, sa_socklen);
2031 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2036 if (tevent_req_error(req, err)) {
2040 tevent_req_done(req);
2044 state->fde = tevent_add_fd(ev, state,
2046 TEVENT_FD_READ | TEVENT_FD_WRITE,
2047 tstream_bsd_connect_fde_handler,
2049 if (tevent_req_nomem(state->fde, req)) {
2056 tevent_req_post(req, ev);
2060 static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
2061 struct tevent_fd *fde,
2065 struct tevent_req *req = talloc_get_type_abort(private_data,
2067 struct tstream_bsd_connect_state *state = tevent_req_data(req,
2068 struct tstream_bsd_connect_state);
2071 socklen_t len = sizeof(error);
2075 ret = getsockopt(state->fd, SOL_SOCKET, SO_ERROR, &error, &len);
2082 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2087 if (tevent_req_error(req, err)) {
2091 tevent_req_done(req);
2094 static int tstream_bsd_connect_recv(struct tevent_req *req,
2096 TALLOC_CTX *mem_ctx,
2097 struct tstream_context **stream,
2098 const char *location)
2100 struct tstream_bsd_connect_state *state = tevent_req_data(req,
2101 struct tstream_bsd_connect_state);
2104 ret = tsocket_simple_int_recv(req, perrno);
2106 ret = _tstream_bsd_existing_socket(mem_ctx,
2114 TALLOC_FREE(state->fde);
2119 tevent_req_received(req);
2123 struct tevent_req * tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
2124 struct tevent_context *ev,
2125 const struct tsocket_address *local,
2126 const struct tsocket_address *remote)
2128 struct tsocket_address_bsd *lbsda =
2129 talloc_get_type_abort(local->private_data,
2130 struct tsocket_address_bsd);
2131 struct tevent_req *req;
2134 switch (lbsda->u.sa.sa_family) {
2146 req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2151 int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
2153 TALLOC_CTX *mem_ctx,
2154 struct tstream_context **stream,
2155 const char *location)
2157 return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
2160 struct tevent_req * tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
2161 struct tevent_context *ev,
2162 const struct tsocket_address *local,
2163 const struct tsocket_address *remote)
2165 struct tsocket_address_bsd *lbsda =
2166 talloc_get_type_abort(local->private_data,
2167 struct tsocket_address_bsd);
2168 struct tevent_req *req;
2171 switch (lbsda->u.sa.sa_family) {
2179 req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2184 int _tstream_unix_connect_recv(struct tevent_req *req,
2186 TALLOC_CTX *mem_ctx,
2187 struct tstream_context **stream,
2188 const char *location)
2190 return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
2193 int _tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
2194 struct tstream_context **_stream1,
2195 TALLOC_CTX *mem_ctx2,
2196 struct tstream_context **_stream2,
2197 const char *location)
2203 struct tstream_context *stream1 = NULL;
2204 struct tstream_context *stream2 = NULL;
2206 ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
2213 fd1 = tsocket_bsd_common_prepare_fd(fd1, true);
2215 int sys_errno = errno;
2221 fd2 = tsocket_bsd_common_prepare_fd(fd2, true);
2223 int sys_errno = errno;
2229 ret = _tstream_bsd_existing_socket(mem_ctx1,
2234 int sys_errno = errno;
2241 ret = _tstream_bsd_existing_socket(mem_ctx2,
2246 int sys_errno = errno;
2247 talloc_free(stream1);
2253 *_stream1 = stream1;
2254 *_stream2 = stream2;