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 const struct tsocket_context_ops tsocket_context_bsd_ops;
31 static const struct tsocket_address_ops tsocket_address_bsd_ops;
33 static int tsocket_context_bsd_set_option(const struct tsocket_context *sock,
38 struct tsocket_context_bsd {
39 bool close_on_disconnect;
41 struct tevent_fd *fde;
44 struct tsocket_address_bsd {
48 struct sockaddr_in in;
50 struct sockaddr_in6 in6;
52 struct sockaddr_un un;
53 struct sockaddr_storage ss;
57 static int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
60 struct tsocket_address **_addr,
63 struct tsocket_address *addr;
64 struct tsocket_address_bsd *bsda;
66 switch (sa->sa_family) {
68 if (sa_len < sizeof(struct sockaddr_un)) {
74 if (sa_len < sizeof(struct sockaddr_in)) {
81 if (sa_len < sizeof(struct sockaddr_in6)) {
92 if (sa_len > sizeof(struct sockaddr_storage)) {
97 addr = tsocket_address_create(mem_ctx,
98 &tsocket_address_bsd_ops,
100 struct tsocket_address_bsd,
109 memcpy(&bsda->u.ss, sa, sa_len);
115 int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
119 struct tsocket_address **_addr,
120 const char *location)
122 struct addrinfo hints;
123 struct addrinfo *result = NULL;
129 * we use SOCKET_STREAM here to get just one result
130 * back from getaddrinfo().
132 hints.ai_socktype = SOCK_STREAM;
133 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
135 if (strcasecmp(fam, "ip") == 0) {
136 hints.ai_family = AF_UNSPEC;
144 } else if (strcasecmp(fam, "ipv4") == 0) {
145 hints.ai_family = AF_INET;
150 } else if (strcasecmp(fam, "ipv6") == 0) {
151 hints.ai_family = AF_INET6;
157 errno = EAFNOSUPPORT;
161 snprintf(port_str, sizeof(port_str) - 1, "%u", port);
163 ret = getaddrinfo(addr, port_str, &hints, &result);
174 if (result->ai_socktype != SOCK_STREAM) {
180 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
188 freeaddrinfo(result);
193 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
196 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
197 struct tsocket_address_bsd);
198 char addr_str[INET6_ADDRSTRLEN+1];
206 switch (bsda->u.sa.sa_family) {
208 str = inet_ntop(bsda->u.in.sin_family,
209 &bsda->u.in.sin_addr,
210 addr_str, sizeof(addr_str));
214 str = inet_ntop(bsda->u.in6.sin6_family,
215 &bsda->u.in6.sin6_addr,
216 addr_str, sizeof(addr_str));
228 return talloc_strdup(mem_ctx, str);
231 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
233 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
234 struct tsocket_address_bsd);
242 switch (bsda->u.sa.sa_family) {
244 port = ntohs(bsda->u.in.sin_port);
248 port = ntohs(bsda->u.in6.sin6_port);
259 int tsocket_address_inet_set_port(struct tsocket_address *addr,
262 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
263 struct tsocket_address_bsd);
270 switch (bsda->u.sa.sa_family) {
272 bsda->u.in.sin_port = htons(port);
276 bsda->u.in6.sin6_port = htons(port);
287 void tsocket_address_inet_set_broadcast(struct tsocket_address *addr,
290 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
291 struct tsocket_address_bsd);
297 bsda->broadcast = broadcast;
300 int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
302 struct tsocket_address **_addr,
303 const char *location)
305 struct sockaddr_un un;
314 un.sun_family = AF_UNIX;
315 strncpy(un.sun_path, path, sizeof(un.sun_path));
317 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
318 (struct sockaddr *)p,
326 char *tsocket_address_unix_path(const struct tsocket_address *addr,
329 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
330 struct tsocket_address_bsd);
338 switch (bsda->u.sa.sa_family) {
340 str = bsda->u.un.sun_path;
347 return talloc_strdup(mem_ctx, str);
350 static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
353 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
354 struct tsocket_address_bsd);
357 const char *prefix = NULL;
360 switch (bsda->u.sa.sa_family) {
362 return talloc_asprintf(mem_ctx, "unix:%s",
363 bsda->u.un.sun_path);
375 addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
380 port = tsocket_address_inet_port(addr);
382 str = talloc_asprintf(mem_ctx, "%s:%s:%u",
383 prefix, addr_str, port);
384 talloc_free(addr_str);
389 static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
391 const char *location)
393 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
394 struct tsocket_address_bsd);
395 struct tsocket_address *copy;
398 ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
407 tsocket_address_inet_set_broadcast(copy, bsda->broadcast);
411 int _tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
412 int fd, bool close_on_disconnect,
413 struct tsocket_context **_sock,
414 const char *location)
416 struct tsocket_context *sock;
417 struct tsocket_context_bsd *bsds;
419 sock = tsocket_context_create(mem_ctx,
420 &tsocket_context_bsd_ops,
422 struct tsocket_context_bsd,
428 bsds->close_on_disconnect = close_on_disconnect;
436 static int tsocket_address_bsd_create_socket(const struct tsocket_address *addr,
437 enum tsocket_type type,
439 struct tsocket_context **_sock,
440 const char *location)
442 struct tsocket_address_bsd *bsda = talloc_get_type(addr->private_data,
443 struct tsocket_address_bsd);
444 struct tsocket_context *sock;
448 bool do_bind = false;
449 bool do_reuseaddr = false;
452 case TSOCKET_TYPE_STREAM:
453 if (bsda->broadcast) {
457 bsd_type = SOCK_STREAM;
459 case TSOCKET_TYPE_DGRAM:
460 bsd_type = SOCK_DGRAM;
463 errno = EPROTONOSUPPORT;
467 switch (bsda->u.sa.sa_family) {
469 if (bsda->broadcast) {
473 if (bsda->u.un.sun_path[0] != 0) {
478 if (bsda->u.in.sin_port != 0) {
482 if (bsda->u.in.sin_addr.s_addr == INADDR_ANY) {
488 if (bsda->u.in6.sin6_port != 0) {
492 if (memcmp(&in6addr_any,
493 &bsda->u.in6.sin6_addr,
494 sizeof(in6addr_any)) != 0) {
504 fd = socket(bsda->u.sa.sa_family, bsd_type, 0);
509 fd = tsocket_common_prepare_fd(fd, true);
514 ret = _tsocket_context_bsd_wrap_existing(mem_ctx, fd, true,
517 int saved_errno = errno;
523 if (bsda->broadcast) {
524 ret = tsocket_context_bsd_set_option(sock, "SO_BROADCAST", true, "1");
526 int saved_errno = errno;
534 ret = tsocket_context_bsd_set_option(sock, "SO_REUSEADDR", true, "1");
536 int saved_errno = errno;
544 ret = bind(fd, &bsda->u.sa, sizeof(bsda->u.ss));
546 int saved_errno = errno;
557 static const struct tsocket_address_ops tsocket_address_bsd_ops = {
559 .string = tsocket_address_bsd_string,
560 .copy = tsocket_address_bsd_copy,
561 .create_socket = tsocket_address_bsd_create_socket
564 static void tsocket_context_bsd_fde_handler(struct tevent_context *ev,
565 struct tevent_fd *fde,
569 struct tsocket_context *sock = talloc_get_type(private_data,
570 struct tsocket_context);
572 if (flags & TEVENT_FD_WRITE) {
573 sock->event.write_handler(sock, sock->event.write_private);
576 if (flags & TEVENT_FD_READ) {
577 sock->event.read_handler(sock, sock->event.read_private);
582 static int tsocket_context_bsd_set_event_context(struct tsocket_context *sock,
583 struct tevent_context *ev)
585 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
586 struct tsocket_context_bsd);
588 talloc_free(bsds->fde);
590 ZERO_STRUCT(sock->event);
596 bsds->fde = tevent_add_fd(ev, bsds,
599 tsocket_context_bsd_fde_handler,
608 sock->event.ctx = ev;
613 static int tsocket_context_bsd_set_read_handler(struct tsocket_context *sock,
614 tsocket_event_handler_t handler,
617 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
618 struct tsocket_context_bsd);
620 if (sock->event.read_handler && !handler) {
621 TEVENT_FD_NOT_READABLE(bsds->fde);
622 } else if (!sock->event.read_handler && handler) {
623 TEVENT_FD_READABLE(bsds->fde);
626 sock->event.read_handler = handler;
627 sock->event.read_private = private_data;
632 static int tsocket_context_bsd_set_write_handler(struct tsocket_context *sock,
633 tsocket_event_handler_t handler,
636 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
637 struct tsocket_context_bsd);
639 if (sock->event.write_handler && !handler) {
640 TEVENT_FD_NOT_WRITEABLE(bsds->fde);
641 } else if (!sock->event.write_handler && handler) {
642 TEVENT_FD_WRITEABLE(bsds->fde);
645 sock->event.write_handler = handler;
646 sock->event.write_private = private_data;
651 static int tsocket_context_bsd_connect_to(struct tsocket_context *sock,
652 const struct tsocket_address *remote)
654 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
655 struct tsocket_context_bsd);
656 struct tsocket_address_bsd *bsda = talloc_get_type(remote->private_data,
657 struct tsocket_address_bsd);
660 ret = connect(bsds->fd, &bsda->u.sa,
666 static int tsocket_context_bsd_listen_on(struct tsocket_context *sock,
669 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
670 struct tsocket_context_bsd);
673 ret = listen(bsds->fd, queue_size);
678 static int tsocket_context_bsd_accept_new(struct tsocket_context *sock,
680 struct tsocket_context **_new_sock,
681 const char *location)
683 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
684 struct tsocket_context_bsd);
686 struct tsocket_context *new_sock;
687 struct tsocket_context_bsd *new_bsds;
688 struct sockaddr_storage ss;
690 socklen_t ss_len = sizeof(ss);
692 new_fd = accept(bsds->fd, (struct sockaddr *)p, &ss_len);
697 new_fd = tsocket_common_prepare_fd(new_fd, true);
702 new_sock = tsocket_context_create(mem_ctx,
703 &tsocket_context_bsd_ops,
705 struct tsocket_context_bsd,
708 int saved_errno = errno;
714 new_bsds->close_on_disconnect = true;
715 new_bsds->fd = new_fd;
716 new_bsds->fde = NULL;
718 *_new_sock = new_sock;
722 static ssize_t tsocket_context_bsd_pending_data(struct tsocket_context *sock)
724 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
725 struct tsocket_context_bsd);
729 ret = ioctl(bsds->fd, FIONREAD, &value);
737 socklen_t len = sizeof(error);
739 * if no data is available check if the socket
740 * is in error state. For dgram sockets
741 * it's the way to return ICMP error messages
742 * of connected sockets to the caller.
744 ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR,
757 /* this should not be reached */
762 static int tsocket_context_bsd_readv_data(struct tsocket_context *sock,
763 const struct iovec *vector,
766 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
767 struct tsocket_context_bsd);
770 ret = readv(bsds->fd, vector, count);
775 static int tsocket_context_bsd_writev_data(struct tsocket_context *sock,
776 const struct iovec *vector,
779 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
780 struct tsocket_context_bsd);
783 ret = writev(bsds->fd, vector, count);
788 static ssize_t tsocket_context_bsd_recvfrom_data(struct tsocket_context *sock,
789 uint8_t *data, size_t len,
790 TALLOC_CTX *addr_ctx,
791 struct tsocket_address **remote)
793 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
794 struct tsocket_context_bsd);
795 struct tsocket_address *addr = NULL;
796 struct tsocket_address_bsd *bsda;
798 struct sockaddr *sa = NULL;
799 socklen_t sa_len = 0;
802 addr = tsocket_address_create(addr_ctx,
803 &tsocket_address_bsd_ops,
805 struct tsocket_address_bsd,
806 __location__ "recvfrom");
814 sa_len = sizeof(bsda->u.ss);
817 ret = recvfrom(bsds->fd, data, len, 0, sa, &sa_len);
819 int saved_errno = errno;
831 static ssize_t tsocket_context_bsd_sendto_data(struct tsocket_context *sock,
832 const uint8_t *data, size_t len,
833 const struct tsocket_address *remote)
835 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
836 struct tsocket_context_bsd);
837 struct sockaddr *sa = NULL;
838 socklen_t sa_len = 0;
842 struct tsocket_address_bsd *bsda =
843 talloc_get_type(remote->private_data,
844 struct tsocket_address_bsd);
847 sa_len = sizeof(bsda->u.ss);
850 ret = sendto(bsds->fd, data, len, 0, sa, sa_len);
855 static int tsocket_context_bsd_get_status(const struct tsocket_context *sock)
857 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
858 struct tsocket_context_bsd);
861 socklen_t len = sizeof(error);
863 if (bsds->fd == -1) {
868 ret = getsockopt(bsds->fd, SOL_SOCKET, SO_ERROR, &error, &len);
880 static int tsocket_context_bsd_get_local_address(const struct tsocket_context *sock,
882 struct tsocket_address **_addr,
883 const char *location)
885 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
886 struct tsocket_context_bsd);
887 struct tsocket_address *addr;
888 struct tsocket_address_bsd *bsda;
892 addr = tsocket_address_create(mem_ctx,
893 &tsocket_address_bsd_ops,
895 struct tsocket_address_bsd,
903 sa_len = sizeof(bsda->u.ss);
904 ret = getsockname(bsds->fd, &bsda->u.sa, &sa_len);
906 int saved_errno = errno;
916 static int tsocket_context_bsd_get_remote_address(const struct tsocket_context *sock,
918 struct tsocket_address **_addr,
919 const char *location)
921 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
922 struct tsocket_context_bsd);
923 struct tsocket_address *addr;
924 struct tsocket_address_bsd *bsda;
928 addr = tsocket_address_create(mem_ctx,
929 &tsocket_address_bsd_ops,
931 struct tsocket_address_bsd,
939 sa_len = sizeof(bsda->u.ss);
940 ret = getpeername(bsds->fd, &bsda->u.sa, &sa_len);
942 int saved_errno = errno;
952 static const struct tsocket_context_bsd_option {
957 } tsocket_context_bsd_options[] = {
958 #define TSOCKET_OPTION(_level, _optnum, _optval) { \
964 TSOCKET_OPTION(SOL_SOCKET, SO_REUSEADDR, 0),
965 TSOCKET_OPTION(SOL_SOCKET, SO_BROADCAST, 0)
968 static int tsocket_context_bsd_get_option(const struct tsocket_context *sock,
973 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
974 struct tsocket_context_bsd);
975 const struct tsocket_context_bsd_option *opt = NULL;
978 socklen_t optval_len = sizeof(optval);
982 for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
983 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
987 opt = &tsocket_context_bsd_options[i];
995 ret = getsockopt(bsds->fd, opt->level, opt->optnum,
996 (void *)&optval, &optval_len);
1001 if (optval_len != sizeof(optval)) {
1003 } if (opt->optval != 0) {
1004 if (optval == opt->optval) {
1005 value = talloc_strdup(mem_ctx, "1");
1007 value = talloc_strdup(mem_ctx, "0");
1013 value = talloc_asprintf(mem_ctx, "%d", optval);
1030 static int tsocket_context_bsd_set_option(const struct tsocket_context *sock,
1035 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1036 struct tsocket_context_bsd);
1037 const struct tsocket_context_bsd_option *opt = NULL;
1042 for (i=0; i < ARRAY_SIZE(tsocket_context_bsd_options); i++) {
1043 if (strcmp(option, tsocket_context_bsd_options[i].name) != 0) {
1047 opt = &tsocket_context_bsd_options[i];
1056 if (opt->optval != 0) {
1061 optval = atoi(value);
1063 optval = opt->optval;
1066 ret = setsockopt(bsds->fd, opt->level, opt->optnum,
1067 (const void *)&optval, sizeof(optval));
1087 static void tsocket_context_bsd_disconnect(struct tsocket_context *sock)
1089 struct tsocket_context_bsd *bsds = talloc_get_type(sock->private_data,
1090 struct tsocket_context_bsd);
1092 tsocket_context_bsd_set_event_context(sock, NULL);
1094 if (bsds->fd != -1) {
1095 if (bsds->close_on_disconnect) {
1102 static const struct tsocket_context_ops tsocket_context_bsd_ops = {
1105 .set_event_context = tsocket_context_bsd_set_event_context,
1106 .set_read_handler = tsocket_context_bsd_set_read_handler,
1107 .set_write_handler = tsocket_context_bsd_set_write_handler,
1109 .connect_to = tsocket_context_bsd_connect_to,
1110 .listen_on = tsocket_context_bsd_listen_on,
1111 .accept_new = tsocket_context_bsd_accept_new,
1113 .pending_data = tsocket_context_bsd_pending_data,
1114 .readv_data = tsocket_context_bsd_readv_data,
1115 .writev_data = tsocket_context_bsd_writev_data,
1116 .recvfrom_data = tsocket_context_bsd_recvfrom_data,
1117 .sendto_data = tsocket_context_bsd_sendto_data,
1119 .get_status = tsocket_context_bsd_get_status,
1120 .get_local_address = tsocket_context_bsd_get_local_address,
1121 .get_remote_address = tsocket_context_bsd_get_remote_address,
1123 .get_option = tsocket_context_bsd_get_option,
1124 .set_option = tsocket_context_bsd_set_option,
1126 .disconnect = tsocket_context_bsd_disconnect