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/network.h"
27 #include "tsocket_internal.h"
29 static const struct tsocket_context_ops tsocket_context_bsd_ops;
30 static const struct tsocket_address_ops tsocket_address_bsd_ops;
32 static int tsocket_context_bsd_set_option(const struct tsocket_context *sock,
37 struct tsocket_context_bsd {
38 bool close_on_disconnect;
40 struct tevent_fd *fde;
43 struct tsocket_address_bsd {
47 struct sockaddr_in sin;
49 struct sockaddr_in6 sin6;
51 struct sockaddr_un sun;
52 struct sockaddr_storage ss;
56 static int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
59 struct tsocket_address **_addr,
62 struct tsocket_address *addr;
63 struct tsocket_address_bsd *bsda;
65 switch (sa->sa_family) {
67 if (sa_len < sizeof(struct sockaddr_un)) {
73 if (sa_len < sizeof(struct sockaddr_in)) {
80 if (sa_len < sizeof(struct sockaddr_in6)) {
91 if (sa_len > sizeof(struct sockaddr_storage)) {
96 addr = tsocket_address_create(mem_ctx,
97 &tsocket_address_bsd_ops,
99 struct tsocket_address_bsd,
108 memcpy(&bsda->u.ss, sa, sa_len);
114 int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
118 struct tsocket_address **_addr,
119 const char *location)
121 struct addrinfo hints;
122 struct addrinfo *result = NULL;
128 * we use SOCKET_STREAM here to get just one result
129 * back from getaddrinfo().
131 hints.ai_socktype = SOCK_STREAM;
132 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
134 if (strcasecmp(fam, "ip") == 0) {
135 hints.ai_family = AF_UNSPEC;
143 } else if (strcasecmp(fam, "ipv4") == 0) {
144 hints.ai_family = AF_INET;
149 } else if (strcasecmp(fam, "ipv6") == 0) {
150 hints.ai_family = AF_INET6;
156 errno = EAFNOSUPPORT;
160 snprintf(port_str, sizeof(port_str) - 1, "%u", port);
162 ret = getaddrinfo(addr, port_str, &hints, &result);
173 if (result->ai_socktype != SOCK_STREAM) {
179 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
187 freeaddrinfo(result);
192 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
195 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
196 struct tsocket_address_bsd);
197 char addr_str[INET6_ADDRSTRLEN+1];
205 switch (bsda->u.sa.sa_family) {
207 str = inet_ntop(bsda->u.sin.sin_family,
208 &bsda->u.sin.sin_addr,
209 addr_str, sizeof(addr_str));
213 str = inet_ntop(bsda->u.sin6.sin6_family,
214 &bsda->u.sin6.sin6_addr,
215 addr_str, sizeof(addr_str));
227 return talloc_strdup(mem_ctx, str);
230 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
232 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
233 struct tsocket_address_bsd);
241 switch (bsda->u.sa.sa_family) {
243 port = ntohs(bsda->u.sin.sin_port);
247 port = ntohs(bsda->u.sin6.sin6_port);
258 int tsocket_address_inet_set_port(struct tsocket_address *addr,
261 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
262 struct tsocket_address_bsd);
269 switch (bsda->u.sa.sa_family) {
271 bsda->u.sin.sin_port = htons(port);
275 bsda->u.sin6.sin6_port = htons(port);
286 void tsocket_address_inet_set_broadcast(struct tsocket_address *addr,
289 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
290 struct tsocket_address_bsd);
296 bsda->broadcast = broadcast;
299 int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
301 struct tsocket_address **_addr,
302 const char *location)
304 struct sockaddr_un sun;
313 sun.sun_family = AF_UNIX;
314 strncpy(sun.sun_path, path, sizeof(sun.sun_path));
316 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
317 (struct sockaddr *)p,
325 char *tsocket_address_unix_path(const struct tsocket_address *addr,
328 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
329 struct tsocket_address_bsd);
337 switch (bsda->u.sa.sa_family) {
339 str = bsda->u.sun.sun_path;
346 return talloc_strdup(mem_ctx, str);
349 static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
352 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
353 struct tsocket_address_bsd);
356 const char *prefix = NULL;
359 switch (bsda->u.sa.sa_family) {
361 return talloc_asprintf(mem_ctx, "unix:%s",
362 bsda->u.sun.sun_path);
374 addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
379 port = tsocket_address_inet_port(addr);
381 str = talloc_asprintf(mem_ctx, "%s:%s:%u",
382 prefix, addr_str, port);
383 talloc_free(addr_str);
388 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
390 const char *location)
392 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
393 struct tsocket_address_bsd);
394 struct tsocket_address *copy;
397 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
406 tsocket_address_inet_set_broadcast(copy, bsda->broadcast);
410 int _tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
411 int fd, bool close_on_disconnect,
412 struct tsocket_context **_sock,
413 const char *location)
415 struct tsocket_context *sock;
416 struct tsocket_context_bsd *bsds;
418 sock = tsocket_context_create(mem_ctx,
419 &tsocket_context_bsd_ops,
421 struct tsocket_context_bsd,
427 bsds->close_on_disconnect = close_on_disconnect;
435 static int tsocket_address_bsd_create_socket(const struct tsocket_address *addr,
436 enum tsocket_type type,
438 struct tsocket_context **_sock,
439 const char *location)
441 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
442 struct tsocket_address_bsd);
443 struct tsocket_context *sock;
447 bool do_bind = false;
448 bool do_reuseaddr = false;
451 case TSOCKET_TYPE_STREAM:
452 if (bsda->broadcast) {
456 bsd_type = SOCK_STREAM;
458 case TSOCKET_TYPE_DGRAM:
459 bsd_type = SOCK_DGRAM;
462 errno = EPROTONOSUPPORT;
466 switch (bsda->u.sa.sa_family) {
468 if (bsda->broadcast) {
472 if (bsda->u.sun.sun_path[0] != 0) {
477 if (bsda->u.sin.sin_port != 0) {
481 if (bsda->u.sin.sin_addr.s_addr == INADDR_ANY) {
487 if (bsda->u.sin6.sin6_port != 0) {
491 if (memcmp(&in6addr_any,
492 &bsda->u.sin6.sin6_addr,
493 sizeof(in6addr_any)) != 0) {
503 fd = socket(bsda->u.sa.sa_family, bsd_type, 0);
508 fd = tsocket_common_prepare_fd(fd, true);
513 ret = _tsocket_context_bsd_wrap_existing(mem_ctx, fd, true,
516 int saved_errno = errno;
522 if (bsda->broadcast) {
523 ret = tsocket_context_bsd_set_option(sock, "SO_BROADCAST", true, "1");
525 int saved_errno = errno;
533 ret = tsocket_context_bsd_set_option(sock, "SO_REUSEADDR", true, "1");
535 int saved_errno = errno;
543 ret = bind(fd, &bsda->u.sa, sizeof(bsda->u.ss));
545 int saved_errno = errno;
556 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
558 .string = tsocket_address_bsd_string,
559 .copy = tsocket_address_bsd_copy,
560 .create_socket = tsocket_address_bsd_create_socket
563 static void tsocket_context_bsd_fde_handler(struct tevent_context *ev,
564 struct tevent_fd *fde,
568 struct tsocket_context *sock = talloc_get_type(private_data,
569 struct tsocket_context);
571 if (flags & TEVENT_FD_WRITE) {
572 sock->event.write_handler(sock, sock->event.write_private);
575 if (flags & TEVENT_FD_READ) {
576 sock->event.read_handler(sock, sock->event.read_private);
581 static int tsocket_context_bsd_set_event_context(struct tsocket_context *sock,
582 struct tevent_context *ev)
584 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
585 struct tsocket_context_bsd);
587 talloc_free(bsds->fde);
589 ZERO_STRUCT(sock->event);
595 bsds->fde = tevent_add_fd(ev, bsds,
598 tsocket_context_bsd_fde_handler,
607 sock->event.ctx = ev;
612 static int tsocket_context_bsd_set_read_handler(struct tsocket_context *sock,
613 tsocket_event_handler_t handler,
616 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
617 struct tsocket_context_bsd);
619 if (sock->event.read_handler && !handler) {
620 TEVENT_FD_NOT_READABLE(bsds->fde);
621 } else if (!sock->event.read_handler && handler) {
622 TEVENT_FD_READABLE(bsds->fde);
625 sock->event.read_handler = handler;
626 sock->event.read_private = private_data;
631 static int tsocket_context_bsd_set_write_handler(struct tsocket_context *sock,
632 tsocket_event_handler_t handler,
635 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
636 struct tsocket_context_bsd);
638 if (sock->event.write_handler && !handler) {
639 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
640 } else if (!sock->event.write_handler && handler) {
641 TEVENT_FD_WRITEABLE(bsds->fde);
644 sock->event.write_handler = handler;
645 sock->event.write_private = private_data;
650 static int tsocket_context_bsd_connect_to(struct tsocket_context *sock,
651 const struct tsocket_address *remote)
653 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
654 struct tsocket_context_bsd);
655 struct tsocket_address_bsd *bsda = talloc_get_type(remote->private_data,
656 struct tsocket_address_bsd);
659 ret = connect(bsds->fd, &bsda->u.sa,
665 static int tsocket_context_bsd_listen_on(struct tsocket_context *sock,
668 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
669 struct tsocket_context_bsd);
672 ret = listen(bsds->fd, queue_size);
677 static int tsocket_context_bsd_accept_new(struct tsocket_context *sock,
679 struct tsocket_context **_new_sock,
680 const char *location)
682 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
683 struct tsocket_context_bsd);
685 struct tsocket_context *new_sock;
686 struct tsocket_context_bsd *new_bsds;
687 struct sockaddr_storage ss;
689 socklen_t ss_len = sizeof(ss);
691 new_fd = accept(bsds->fd, (struct sockaddr *)p, &ss_len);
696 new_fd = tsocket_common_prepare_fd(new_fd, true);
701 new_sock = tsocket_context_create(mem_ctx,
702 &tsocket_context_bsd_ops,
704 struct tsocket_context_bsd,
707 int saved_errno = errno;
713 new_bsds->close_on_disconnect = true;
714 new_bsds->fd = new_fd;
715 new_bsds->fde = NULL;
717 *_new_sock = new_sock;
721 static ssize_t tsocket_context_bsd_pending_data(struct tsocket_context *sock)
723 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
724 struct tsocket_context_bsd);
728 ret = ioctl(bsds->fd, FIONREAD, &value);
736 socklen_t len = sizeof(error);
738 * if no data is available check if the socket
739 * is in error state. For dgram sockets
740 * it's the way to return ICMP error messages
741 * of connected sockets to the caller.
743 ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR,
756 /* this should not be reached */
761 static int tsocket_context_bsd_readv_data(struct tsocket_context *sock,
762 const struct iovec *vector,
765 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
766 struct tsocket_context_bsd);
769 ret = readv(bsds->fd, vector, count);
774 static int tsocket_context_bsd_writev_data(struct tsocket_context *sock,
775 const struct iovec *vector,
778 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
779 struct tsocket_context_bsd);
782 ret = writev(bsds->fd, vector, count);
787 static ssize_t tsocket_context_bsd_recvfrom_data(struct tsocket_context *sock,
788 uint8_t *data, size_t len,
789 TALLOC_CTX *addr_ctx,
790 struct tsocket_address **remote)
792 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
793 struct tsocket_context_bsd);
794 struct tsocket_address *addr = NULL;
795 struct tsocket_address_bsd *bsda;
797 struct sockaddr *sa = NULL;
798 socklen_t sa_len = 0;
801 addr = tsocket_address_create(addr_ctx,
802 &tsocket_address_bsd_ops,
804 struct tsocket_address_bsd,
805 __location__ "recvfrom");
813 sa_len = sizeof(bsda->u.ss);
816 ret = recvfrom(bsds->fd, data, len, 0, sa, &sa_len);
818 int saved_errno = errno;
830 static ssize_t tsocket_context_bsd_sendto_data(struct tsocket_context *sock,
831 const uint8_t *data, size_t len,
832 const struct tsocket_address *remote)
834 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
835 struct tsocket_context_bsd);
836 struct sockaddr *sa = NULL;
837 socklen_t sa_len = 0;
841 struct tsocket_address_bsd *bsda =
842 talloc_get_type(remote->private_data,
843 struct tsocket_address_bsd);
846 sa_len = sizeof(bsda->u.ss);
849 ret = sendto(bsds->fd, data, len, 0, sa, sa_len);
854 static int tsocket_context_bsd_get_status(const struct tsocket_context *sock)
856 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
857 struct tsocket_context_bsd);
860 socklen_t len = sizeof(error);
862 if (bsds->fd == -1) {
867 ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR, &error, &len);
879 static int tsocket_context_bsd_get_local_address(const struct tsocket_context *sock,
881 struct tsocket_address **_addr,
882 const char *location)
884 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
885 struct tsocket_context_bsd);
886 struct tsocket_address *addr;
887 struct tsocket_address_bsd *bsda;
891 addr = tsocket_address_create(mem_ctx,
892 &tsocket_address_bsd_ops,
894 struct tsocket_address_bsd,
902 sa_len = sizeof(bsda->u.ss);
903 ret = getsockname(bsds->fd, &bsda->u.sa, &sa_len);
905 int saved_errno = errno;
915 static int tsocket_context_bsd_get_remote_address(const struct tsocket_context *sock,
917 struct tsocket_address **_addr,
918 const char *location)
920 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
921 struct tsocket_context_bsd);
922 struct tsocket_address *addr;
923 struct tsocket_address_bsd *bsda;
927 addr = tsocket_address_create(mem_ctx,
928 &tsocket_address_bsd_ops,
930 struct tsocket_address_bsd,
938 sa_len = sizeof(bsda->u.ss);
939 ret = getpeername(bsds->fd, &bsda->u.sa, &sa_len);
941 int saved_errno = errno;
951 static const struct tsocket_context_bsd_option {
956 } tsocket_context_bsd_options[] = {
957 #define TSOCKET_OPTION(_level, _optnum, _optval) { \
963 TSOCKET_OPTION(SOL_SOCKET, SO_REUSEADDR, 0),
964 TSOCKET_OPTION(SOL_SOCKET, SO_BROADCAST, 0)
967 static int tsocket_context_bsd_get_option(const struct tsocket_context *sock,
972 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
973 struct tsocket_context_bsd);
974 const struct tsocket_context_bsd_option *opt = NULL;
977 socklen_t optval_len = sizeof(optval);
981 for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
982 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
986 opt = &tsocket_context_bsd_options[i];
994 ret = getsockopt(bsds->fd, opt->level, opt->optnum,
995 (void *)&optval, &optval_len);
1000 if (optval_len != sizeof(optval)) {
1002 } if (opt->optval != 0) {
1003 if (optval == opt->optval) {
1004 value = talloc_strdup(mem_ctx, "1");
1006 value = talloc_strdup(mem_ctx, "0");
1012 value = talloc_asprintf(mem_ctx, "%d", optval);
1029 static int tsocket_context_bsd_set_option(const struct tsocket_context *sock,
1034 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1035 struct tsocket_context_bsd);
1036 const struct tsocket_context_bsd_option *opt = NULL;
1041 for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
1042 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
1046 opt = &tsocket_context_bsd_options[i];
1055 if (opt->optval != 0) {
1060 optval = atoi(value);
1062 optval = opt->optval;
1065 ret = setsockopt(bsds->fd, opt->level, opt->optnum,
1066 (const void *)&optval, sizeof(optval));
1086 static void tsocket_context_bsd_disconnect(struct tsocket_context *sock)
1088 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1089 struct tsocket_context_bsd);
1091 tsocket_context_bsd_set_event_context(sock, NULL);
1093 if (bsds->fd != -1) {
1094 if (bsds->close_on_disconnect) {
1101 static const struct tsocket_context_ops tsocket_context_bsd_ops = {
1104 .set_event_context = tsocket_context_bsd_set_event_context,
1105 .set_read_handler = tsocket_context_bsd_set_read_handler,
1106 .set_write_handler = tsocket_context_bsd_set_write_handler,
1108 .connect_to = tsocket_context_bsd_connect_to,
1109 .listen_on = tsocket_context_bsd_listen_on,
1110 .accept_new = tsocket_context_bsd_accept_new,
1112 .pending_data = tsocket_context_bsd_pending_data,
1113 .readv_data = tsocket_context_bsd_readv_data,
1114 .writev_data = tsocket_context_bsd_writev_data,
1115 .recvfrom_data = tsocket_context_bsd_recvfrom_data,
1116 .sendto_data = tsocket_context_bsd_sendto_data,
1118 .get_status = tsocket_context_bsd_get_status,
1119 .get_local_address = tsocket_context_bsd_get_local_address,
1120 .get_remote_address = tsocket_context_bsd_get_remote_address,
1122 .get_option = tsocket_context_bsd_get_option,
1123 .set_option = tsocket_context_bsd_set_option,
1125 .disconnect = tsocket_context_bsd_disconnect