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);
534 addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
539 port = tsocket_address_inet_port(addr);
541 str = talloc_asprintf(mem_ctx, "%s:%s:%u",
542 prefix, addr_str, port);
543 talloc_free(addr_str);
548 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
550 const char *location)
552 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
553 struct tsocket_address_bsd);
554 struct tsocket_address *copy;
557 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
566 tsocket_address_inet_set_broadcast(copy, bsda->broadcast);
570 int _tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
571 int fd, bool close_on_disconnect,
572 struct tsocket_context **_sock,
573 const char *location)
575 struct tsocket_context *sock;
576 struct tsocket_context_bsd *bsds;
578 sock = tsocket_context_create(mem_ctx,
579 &tsocket_context_bsd_ops,
581 struct tsocket_context_bsd,
587 bsds->close_on_disconnect = close_on_disconnect;
595 static int tsocket_address_bsd_create_socket(const struct tsocket_address *addr,
596 enum tsocket_type type,
598 struct tsocket_context **_sock,
599 const char *location)
601 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
602 struct tsocket_address_bsd);
603 struct tsocket_context *sock;
607 bool do_bind = false;
608 bool do_reuseaddr = false;
611 case TSOCKET_TYPE_STREAM:
612 if (bsda->broadcast) {
616 bsd_type = SOCK_STREAM;
619 errno = EPROTONOSUPPORT;
623 switch (bsda->u.sa.sa_family) {
625 if (bsda->broadcast) {
629 if (bsda->u.un.sun_path[0] != 0) {
634 if (bsda->u.in.sin_port != 0) {
638 if (bsda->u.in.sin_addr.s_addr == INADDR_ANY) {
644 if (bsda->u.in6.sin6_port != 0) {
648 if (memcmp(&in6addr_any,
649 &bsda->u.in6.sin6_addr,
650 sizeof(in6addr_any)) != 0) {
660 fd = socket(bsda->u.sa.sa_family, bsd_type, 0);
665 fd = tsocket_common_prepare_fd(fd, true);
670 ret = _tsocket_context_bsd_wrap_existing(mem_ctx, fd, true,
673 int saved_errno = errno;
679 if (bsda->broadcast) {
680 ret = tsocket_context_bsd_set_option(sock, "SO_BROADCAST", true, "1");
682 int saved_errno = errno;
690 ret = tsocket_context_bsd_set_option(sock, "SO_REUSEADDR", true, "1");
692 int saved_errno = errno;
700 ret = bind(fd, &bsda->u.sa, sizeof(bsda->u.ss));
702 int saved_errno = errno;
713 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
715 .string = tsocket_address_bsd_string,
716 .copy = tsocket_address_bsd_copy,
717 .create_socket = tsocket_address_bsd_create_socket
720 static void tsocket_context_bsd_fde_handler(struct tevent_context *ev,
721 struct tevent_fd *fde,
725 struct tsocket_context *sock = talloc_get_type(private_data,
726 struct tsocket_context);
728 if (flags & TEVENT_FD_WRITE) {
729 sock->event.write_handler(sock, sock->event.write_private);
732 if (flags & TEVENT_FD_READ) {
733 sock->event.read_handler(sock, sock->event.read_private);
738 static int tsocket_context_bsd_set_event_context(struct tsocket_context *sock,
739 struct tevent_context *ev)
741 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
742 struct tsocket_context_bsd);
744 talloc_free(bsds->fde);
746 ZERO_STRUCT(sock->event);
752 bsds->fde = tevent_add_fd(ev, bsds,
755 tsocket_context_bsd_fde_handler,
764 sock->event.ctx = ev;
769 static int tsocket_context_bsd_set_read_handler(struct tsocket_context *sock,
770 tsocket_event_handler_t handler,
773 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
774 struct tsocket_context_bsd);
776 if (sock->event.read_handler && !handler) {
777 TEVENT_FD_NOT_READABLE(bsds->fde);
778 } else if (!sock->event.read_handler && handler) {
779 TEVENT_FD_READABLE(bsds->fde);
782 sock->event.read_handler = handler;
783 sock->event.read_private = private_data;
788 static int tsocket_context_bsd_set_write_handler(struct tsocket_context *sock,
789 tsocket_event_handler_t handler,
792 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
793 struct tsocket_context_bsd);
795 if (sock->event.write_handler && !handler) {
796 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
797 } else if (!sock->event.write_handler && handler) {
798 TEVENT_FD_WRITEABLE(bsds->fde);
801 sock->event.write_handler = handler;
802 sock->event.write_private = private_data;
807 static int tsocket_context_bsd_connect_to(struct tsocket_context *sock,
808 const struct tsocket_address *remote)
810 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
811 struct tsocket_context_bsd);
812 struct tsocket_address_bsd *bsda = talloc_get_type(remote->private_data,
813 struct tsocket_address_bsd);
816 ret = connect(bsds->fd, &bsda->u.sa,
822 static int tsocket_context_bsd_listen_on(struct tsocket_context *sock,
825 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
826 struct tsocket_context_bsd);
829 ret = listen(bsds->fd, queue_size);
834 static int tsocket_context_bsd_accept_new(struct tsocket_context *sock,
836 struct tsocket_context **_new_sock,
837 const char *location)
839 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
840 struct tsocket_context_bsd);
842 struct tsocket_context *new_sock;
843 struct tsocket_context_bsd *new_bsds;
844 struct sockaddr_storage ss;
846 socklen_t ss_len = sizeof(ss);
848 new_fd = accept(bsds->fd, (struct sockaddr *)p, &ss_len);
853 new_fd = tsocket_common_prepare_fd(new_fd, true);
858 new_sock = tsocket_context_create(mem_ctx,
859 &tsocket_context_bsd_ops,
861 struct tsocket_context_bsd,
864 int saved_errno = errno;
870 new_bsds->close_on_disconnect = true;
871 new_bsds->fd = new_fd;
872 new_bsds->fde = NULL;
874 *_new_sock = new_sock;
878 static ssize_t tsocket_context_bsd_pending_data(struct tsocket_context *sock)
880 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
881 struct tsocket_context_bsd);
885 ret = ioctl(bsds->fd, FIONREAD, &value);
893 socklen_t len = sizeof(error);
895 * if no data is available check if the socket
896 * is in error state. For dgram sockets
897 * it's the way to return ICMP error messages
898 * of connected sockets to the caller.
900 ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR,
913 /* this should not be reached */
918 static int tsocket_context_bsd_readv_data(struct tsocket_context *sock,
919 const struct iovec *vector,
922 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
923 struct tsocket_context_bsd);
926 ret = readv(bsds->fd, vector, count);
931 static int tsocket_context_bsd_writev_data(struct tsocket_context *sock,
932 const struct iovec *vector,
935 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
936 struct tsocket_context_bsd);
939 ret = writev(bsds->fd, vector, count);
944 static int tsocket_context_bsd_get_status(const struct tsocket_context *sock)
946 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
947 struct tsocket_context_bsd);
950 socklen_t len = sizeof(error);
952 if (bsds->fd == -1) {
957 ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR, &error, &len);
969 static int tsocket_context_bsd_get_local_address(const struct tsocket_context *sock,
971 struct tsocket_address **_addr,
972 const char *location)
974 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
975 struct tsocket_context_bsd);
976 struct tsocket_address *addr;
977 struct tsocket_address_bsd *bsda;
981 addr = tsocket_address_create(mem_ctx,
982 &tsocket_address_bsd_ops,
984 struct tsocket_address_bsd,
992 sa_len = sizeof(bsda->u.ss);
993 ret = getsockname(bsds->fd, &bsda->u.sa, &sa_len);
995 int saved_errno = errno;
1005 static int tsocket_context_bsd_get_remote_address(const struct tsocket_context *sock,
1006 TALLOC_CTX *mem_ctx,
1007 struct tsocket_address **_addr,
1008 const char *location)
1010 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1011 struct tsocket_context_bsd);
1012 struct tsocket_address *addr;
1013 struct tsocket_address_bsd *bsda;
1017 addr = tsocket_address_create(mem_ctx,
1018 &tsocket_address_bsd_ops,
1020 struct tsocket_address_bsd,
1028 sa_len = sizeof(bsda->u.ss);
1029 ret = getpeername(bsds->fd, &bsda->u.sa, &sa_len);
1031 int saved_errno = errno;
1033 errno = saved_errno;
1041 static const struct tsocket_context_bsd_option {
1046 } tsocket_context_bsd_options[] = {
1047 #define TSOCKET_OPTION(_level, _optnum, _optval) { \
1050 .optnum = _optnum, \
1053 TSOCKET_OPTION(SOL_SOCKET, SO_REUSEADDR, 0),
1054 TSOCKET_OPTION(SOL_SOCKET, SO_BROADCAST, 0)
1057 static int tsocket_context_bsd_get_option(const struct tsocket_context *sock,
1059 TALLOC_CTX *mem_ctx,
1062 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1063 struct tsocket_context_bsd);
1064 const struct tsocket_context_bsd_option *opt = NULL;
1067 socklen_t optval_len = sizeof(optval);
1071 for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
1072 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
1076 opt = &tsocket_context_bsd_options[i];
1084 ret = getsockopt(bsds->fd, opt->level, opt->optnum,
1085 (void *)&optval, &optval_len);
1090 if (optval_len != sizeof(optval)) {
1092 } if (opt->optval != 0) {
1093 if (optval == opt->optval) {
1094 value = talloc_strdup(mem_ctx, "1");
1096 value = talloc_strdup(mem_ctx, "0");
1102 value = talloc_asprintf(mem_ctx, "%d", optval);
1119 static int tsocket_context_bsd_set_option(const struct tsocket_context *sock,
1124 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1125 struct tsocket_context_bsd);
1126 const struct tsocket_context_bsd_option *opt = NULL;
1131 for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
1132 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
1136 opt = &tsocket_context_bsd_options[i];
1145 if (opt->optval != 0) {
1150 optval = atoi(value);
1152 optval = opt->optval;
1155 ret = setsockopt(bsds->fd, opt->level, opt->optnum,
1156 (const void *)&optval, sizeof(optval));
1176 static void tsocket_context_bsd_disconnect(struct tsocket_context *sock)
1178 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1179 struct tsocket_context_bsd);
1181 tsocket_context_bsd_set_event_context(sock, NULL);
1183 if (bsds->fd != -1) {
1184 if (bsds->close_on_disconnect) {
1191 static const struct tsocket_context_ops tsocket_context_bsd_ops = {
1194 .set_event_context = tsocket_context_bsd_set_event_context,
1195 .set_read_handler = tsocket_context_bsd_set_read_handler,
1196 .set_write_handler = tsocket_context_bsd_set_write_handler,
1198 .connect_to = tsocket_context_bsd_connect_to,
1199 .listen_on = tsocket_context_bsd_listen_on,
1200 .accept_new = tsocket_context_bsd_accept_new,
1202 .pending_data = tsocket_context_bsd_pending_data,
1203 .readv_data = tsocket_context_bsd_readv_data,
1204 .writev_data = tsocket_context_bsd_writev_data,
1206 .get_status = tsocket_context_bsd_get_status,
1207 .get_local_address = tsocket_context_bsd_get_local_address,
1208 .get_remote_address = tsocket_context_bsd_get_remote_address,
1210 .get_option = tsocket_context_bsd_get_option,
1211 .set_option = tsocket_context_bsd_set_option,
1213 .disconnect = tsocket_context_bsd_disconnect
1220 struct tevent_fd *fde;
1222 void *readable_private;
1223 void (*readable_handler)(void *private_data);
1224 void *writeable_private;
1225 void (*writeable_handler)(void *private_data);
1227 struct tevent_req *read_req;
1228 struct tevent_req *write_req;
1231 static void tdgram_bsd_fde_handler(struct tevent_context *ev,
1232 struct tevent_fd *fde,
1236 struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
1239 if (flags & TEVENT_FD_WRITE) {
1240 bsds->writeable_handler(bsds->writeable_private);
1243 if (flags & TEVENT_FD_READ) {
1244 if (!bsds->readable_handler) {
1245 TEVENT_FD_NOT_READABLE(bsds->fde);
1248 bsds->readable_handler(bsds->readable_private);
1253 static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
1254 struct tevent_context *ev,
1255 void (*handler)(void *private_data),
1263 if (!bsds->readable_handler) {
1266 bsds->readable_handler = NULL;
1267 bsds->readable_private = NULL;
1272 /* read and write must use the same tevent_context */
1273 if (bsds->event_ptr != ev) {
1274 if (bsds->readable_handler || bsds->writeable_handler) {
1278 bsds->event_ptr = NULL;
1279 TALLOC_FREE(bsds->fde);
1282 if (bsds->fde == NULL) {
1283 bsds->fde = tevent_add_fd(ev, bsds,
1284 bsds->fd, TEVENT_FD_READ,
1285 tdgram_bsd_fde_handler,
1291 /* cache the event context we're running on */
1292 bsds->event_ptr = ev;
1293 } else if (!bsds->readable_handler) {
1294 TEVENT_FD_READABLE(bsds->fde);
1297 bsds->readable_handler = handler;
1298 bsds->readable_private = private_data;
1303 static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
1304 struct tevent_context *ev,
1305 void (*handler)(void *private_data),
1313 if (!bsds->writeable_handler) {
1316 bsds->writeable_handler = NULL;
1317 bsds->writeable_private = NULL;
1318 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
1323 /* read and write must use the same tevent_context */
1324 if (bsds->event_ptr != ev) {
1325 if (bsds->readable_handler || bsds->writeable_handler) {
1329 bsds->event_ptr = NULL;
1330 TALLOC_FREE(bsds->fde);
1333 if (bsds->fde == NULL) {
1334 bsds->fde = tevent_add_fd(ev, bsds,
1335 bsds->fd, TEVENT_FD_WRITE,
1336 tdgram_bsd_fde_handler,
1342 /* cache the event context we're running on */
1343 bsds->event_ptr = ev;
1344 } else if (!bsds->writeable_handler) {
1345 TEVENT_FD_WRITEABLE(bsds->fde);
1348 bsds->writeable_handler = handler;
1349 bsds->writeable_private = private_data;
1354 struct tdgram_bsd_recvfrom_state {
1355 struct tdgram_context *dgram;
1359 struct tsocket_address *src;
1362 static int tdgram_bsd_recvfrom_destructor(struct tdgram_bsd_recvfrom_state *state)
1364 struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1367 bsds->read_req = NULL;
1368 tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
1373 static void tdgram_bsd_recvfrom_handler(void *private_data);
1375 static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
1376 struct tevent_context *ev,
1377 struct tdgram_context *dgram)
1379 struct tevent_req *req;
1380 struct tdgram_bsd_recvfrom_state *state;
1381 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1384 req = tevent_req_create(mem_ctx, &state,
1385 struct tdgram_bsd_recvfrom_state);
1390 state->dgram = dgram;
1395 if (bsds->read_req) {
1396 tevent_req_error(req, EBUSY);
1399 bsds->read_req = req;
1401 talloc_set_destructor(state, tdgram_bsd_recvfrom_destructor);
1403 if (bsds->fd == -1) {
1404 tevent_req_error(req, ENOTCONN);
1409 * this is a fast path, not waiting for the
1410 * socket to become explicit readable gains
1411 * about 10%-20% performance in benchmark tests.
1413 tdgram_bsd_recvfrom_handler(req);
1414 if (!tevent_req_is_in_progress(req)) {
1418 ret = tdgram_bsd_set_readable_handler(bsds, ev,
1419 tdgram_bsd_recvfrom_handler,
1422 tevent_req_error(req, errno);
1429 tevent_req_post(req, ev);
1433 static void tdgram_bsd_recvfrom_handler(void *private_data)
1435 struct tevent_req *req = talloc_get_type_abort(private_data,
1437 struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1438 struct tdgram_bsd_recvfrom_state);
1439 struct tdgram_context *dgram = state->dgram;
1440 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1441 struct tsocket_address_bsd *bsda;
1443 struct sockaddr *sa = NULL;
1444 socklen_t sa_len = 0;
1448 ret = tsocket_bsd_pending(bsds->fd);
1453 err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1458 if (tevent_req_error(req, err)) {
1462 state->buf = talloc_array(state, uint8_t, ret);
1463 if (tevent_req_nomem(state->buf, req)) {
1468 state->src = tsocket_address_create(state,
1469 &tsocket_address_bsd_ops,
1471 struct tsocket_address_bsd,
1472 __location__ "bsd_recvfrom");
1473 if (tevent_req_nomem(state->src, req)) {
1480 sa_len = sizeof(bsda->u.ss);
1482 ret = recvfrom(bsds->fd, state->buf, state->len, 0, sa, &sa_len);
1483 err = tsocket_error_from_errno(ret, errno, &retry);
1488 if (tevent_req_error(req, err)) {
1492 if (ret != state->len) {
1493 tevent_req_error(req, EIO);
1497 tevent_req_done(req);
1500 static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
1502 TALLOC_CTX *mem_ctx,
1504 struct tsocket_address **src)
1506 struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1507 struct tdgram_bsd_recvfrom_state);
1510 ret = tsocket_simple_int_recv(req, perrno);
1512 *buf = talloc_move(mem_ctx, &state->buf);
1515 *src = talloc_move(mem_ctx, &state->src);
1519 tevent_req_received(req);
1523 struct tdgram_bsd_sendto_state {
1524 struct tdgram_context *dgram;
1528 const struct tsocket_address *dst;
1533 static int tdgram_bsd_sendto_destructor(struct tdgram_bsd_sendto_state *state)
1535 struct tdgram_bsd *bsds = tdgram_context_data(state->dgram,
1538 bsds->write_req = NULL;
1539 tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1543 static void tdgram_bsd_sendto_handler(void *private_data);
1545 static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
1546 struct tevent_context *ev,
1547 struct tdgram_context *dgram,
1550 const struct tsocket_address *dst)
1552 struct tevent_req *req;
1553 struct tdgram_bsd_sendto_state *state;
1554 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1557 req = tevent_req_create(mem_ctx, &state,
1558 struct tdgram_bsd_sendto_state);
1563 state->dgram = dgram;
1569 if (bsds->write_req) {
1570 tevent_req_error(req, EBUSY);
1573 bsds->write_req = req;
1575 talloc_set_destructor(state, tdgram_bsd_sendto_destructor);
1577 if (bsds->fd == -1) {
1578 tevent_req_error(req, ENOTCONN);
1583 * this is a fast path, not waiting for the
1584 * socket to become explicit writeable gains
1585 * about 10%-20% performance in benchmark tests.
1587 tdgram_bsd_sendto_handler(req);
1588 if (!tevent_req_is_in_progress(req)) {
1592 ret = tdgram_bsd_set_writeable_handler(bsds, ev,
1593 tdgram_bsd_sendto_handler,
1596 tevent_req_error(req, errno);
1603 tevent_req_post(req, ev);
1607 static void tdgram_bsd_sendto_handler(void *private_data)
1609 struct tevent_req *req = talloc_get_type_abort(private_data,
1611 struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1612 struct tdgram_bsd_sendto_state);
1613 struct tdgram_context *dgram = state->dgram;
1614 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1615 struct sockaddr *sa = NULL;
1616 socklen_t sa_len = 0;
1622 struct tsocket_address_bsd *bsda =
1623 talloc_get_type(state->dst->private_data,
1624 struct tsocket_address_bsd);
1627 sa_len = sizeof(bsda->u.ss);
1630 ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_len);
1631 err = tsocket_error_from_errno(ret, errno, &retry);
1636 if (tevent_req_error(req, err)) {
1642 tevent_req_done(req);
1645 static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
1647 struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1648 struct tdgram_bsd_sendto_state);
1651 ret = tsocket_simple_int_recv(req, perrno);
1656 tevent_req_received(req);
1660 struct tdgram_bsd_disconnect_state {
1664 static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1665 struct tevent_context *ev,
1666 struct tdgram_context *dgram)
1668 struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1669 struct tevent_req *req;
1670 struct tdgram_bsd_disconnect_state *state;
1675 req = tevent_req_create(mem_ctx, &state,
1676 struct tdgram_bsd_disconnect_state);
1681 if (bsds->read_req || bsds->write_req) {
1682 tevent_req_error(req, EBUSY);
1686 if (bsds->fd == -1) {
1687 tevent_req_error(req, ENOTCONN);
1691 ret = close(bsds->fd);
1693 err = tsocket_error_from_errno(ret, errno, &dummy);
1694 if (tevent_req_error(req, err)) {
1698 tevent_req_done(req);
1700 tevent_req_post(req, ev);
1704 static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1709 ret = tsocket_simple_int_recv(req, perrno);
1711 tevent_req_received(req);
1715 static const struct tdgram_context_ops tdgram_bsd_ops = {
1718 .recvfrom_send = tdgram_bsd_recvfrom_send,
1719 .recvfrom_recv = tdgram_bsd_recvfrom_recv,
1721 .sendto_send = tdgram_bsd_sendto_send,
1722 .sendto_recv = tdgram_bsd_sendto_recv,
1724 .disconnect_send = tdgram_bsd_disconnect_send,
1725 .disconnect_recv = tdgram_bsd_disconnect_recv,
1728 static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1730 TALLOC_FREE(bsds->fde);
1731 if (bsds->fd != -1) {
1738 static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1739 const struct tsocket_address *remote,
1740 TALLOC_CTX *mem_ctx,
1741 struct tdgram_context **_dgram,
1742 const char *location)
1744 struct tsocket_address_bsd *lbsda =
1745 talloc_get_type_abort(local->private_data,
1746 struct tsocket_address_bsd);
1747 struct tsocket_address_bsd *rbsda = NULL;
1748 struct tdgram_context *dgram;
1749 struct tdgram_bsd *bsds;
1752 bool do_bind = false;
1753 bool do_reuseaddr = false;
1756 rbsda = talloc_get_type_abort(remote->private_data,
1757 struct tsocket_address_bsd);
1760 switch (lbsda->u.sa.sa_family) {
1762 if (lbsda->u.un.sun_path[0] != 0) {
1763 do_reuseaddr = true;
1768 if (lbsda->u.in.sin_port != 0) {
1769 do_reuseaddr = true;
1772 if (lbsda->u.in.sin_addr.s_addr == INADDR_ANY) {
1778 if (lbsda->u.in6.sin6_port != 0) {
1779 do_reuseaddr = true;
1782 if (memcmp(&in6addr_any,
1783 &lbsda->u.in6.sin6_addr,
1784 sizeof(in6addr_any)) != 0) {
1794 fd = socket(lbsda->u.sa.sa_family, SOCK_DGRAM, 0);
1799 fd = tsocket_bsd_common_prepare_fd(fd, true);
1804 dgram = tdgram_context_create(mem_ctx,
1810 int saved_errno = errno;
1812 errno = saved_errno;
1817 talloc_set_destructor(bsds, tdgram_bsd_destructor);
1819 if (lbsda->broadcast) {
1822 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1823 (const void *)&val, sizeof(val));
1825 int saved_errno = errno;
1827 errno = saved_errno;
1835 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1836 (const void *)&val, sizeof(val));
1838 int saved_errno = errno;
1840 errno = saved_errno;
1846 ret = bind(fd, &lbsda->u.sa, sizeof(lbsda->u.ss));
1848 int saved_errno = errno;
1850 errno = saved_errno;
1856 ret = connect(fd, &rbsda->u.sa, sizeof(rbsda->u.ss));
1858 int saved_errno = errno;
1860 errno = saved_errno;
1869 int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1870 const struct tsocket_address *remote,
1871 TALLOC_CTX *mem_ctx,
1872 struct tdgram_context **dgram,
1873 const char *location)
1875 struct tsocket_address_bsd *lbsda =
1876 talloc_get_type_abort(local->private_data,
1877 struct tsocket_address_bsd);
1880 switch (lbsda->u.sa.sa_family) {
1892 ret = tdgram_bsd_dgram_socket(local, remote, mem_ctx, dgram, location);
1897 int _tdgram_unix_dgram_socket(const struct tsocket_address *local,
1898 const struct tsocket_address *remote,
1899 TALLOC_CTX *mem_ctx,
1900 struct tdgram_context **dgram,
1901 const char *location)
1903 struct tsocket_address_bsd *lbsda =
1904 talloc_get_type_abort(local->private_data,
1905 struct tsocket_address_bsd);
1908 switch (lbsda->u.sa.sa_family) {
1916 ret = tdgram_bsd_dgram_socket(local, remote, mem_ctx, dgram, location);