2 Unix SMB/CIFS implementation.
4 Socket IPv4/IPv6 functions
6 Copyright (C) Stefan Metzmacher 2004
7 Copyright (C) Andrew Tridgell 2004-2005
8 Copyright (C) Jelmer Vernooij 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program 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
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "system/filesys.h"
26 #include "lib/socket/socket.h"
27 #include "system/network.h"
28 #include "lib/util/util_net.h"
30 _PUBLIC_
const struct socket_ops
*socket_ipv4_ops(enum socket_type type
);
31 _PUBLIC_
const struct socket_ops
*socket_ipv6_ops(enum socket_type type
);
33 static NTSTATUS
ipv4_init(struct socket_context
*sock
)
38 case SOCKET_TYPE_STREAM
:
41 case SOCKET_TYPE_DGRAM
:
45 return NT_STATUS_INVALID_PARAMETER
;
48 sock
->fd
= socket(PF_INET
, type
, 0);
50 return map_nt_error_from_unix_common(errno
);
53 smb_set_close_on_exec(sock
->fd
);
55 sock
->backend_name
= "ipv4";
56 sock
->family
= AF_INET
;
61 static void ip_close(struct socket_context
*sock
)
69 static NTSTATUS
ip_connect_complete(struct socket_context
*sock
, uint32_t flags
)
72 socklen_t len
= sizeof(error
);
74 /* check for any errors that may have occurred - this is needed
75 for non-blocking connect */
76 ret
= getsockopt(sock
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
);
78 return map_nt_error_from_unix_common(errno
);
81 return map_nt_error_from_unix_common(error
);
84 if (!(flags
& SOCKET_FLAG_BLOCK
)) {
85 ret
= set_blocking(sock
->fd
, false);
87 return map_nt_error_from_unix_common(errno
);
91 sock
->state
= SOCKET_STATE_CLIENT_CONNECTED
;
97 static NTSTATUS
ipv4_connect(struct socket_context
*sock
,
98 const struct socket_address
*my_address
,
99 const struct socket_address
*srv_address
,
102 struct sockaddr_in srv_addr
;
103 struct in_addr my_ip
;
104 struct in_addr srv_ip
;
107 if (my_address
&& my_address
->sockaddr
) {
108 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
110 return map_nt_error_from_unix_common(errno
);
112 } else if (my_address
) {
113 my_ip
= interpret_addr2(my_address
->addr
);
115 if (my_ip
.s_addr
!= 0 || my_address
->port
!= 0) {
116 struct sockaddr_in my_addr
;
117 ZERO_STRUCT(my_addr
);
118 #ifdef HAVE_SOCK_SIN_LEN
119 my_addr
.sin_len
= sizeof(my_addr
);
121 my_addr
.sin_addr
.s_addr
= my_ip
.s_addr
;
122 my_addr
.sin_port
= htons(my_address
->port
);
123 my_addr
.sin_family
= PF_INET
;
125 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
127 return map_nt_error_from_unix_common(errno
);
132 if (srv_address
->sockaddr
) {
133 ret
= connect(sock
->fd
, srv_address
->sockaddr
, srv_address
->sockaddrlen
);
135 return map_nt_error_from_unix_common(errno
);
138 srv_ip
= interpret_addr2(srv_address
->addr
);
139 if (!srv_ip
.s_addr
) {
140 return NT_STATUS_BAD_NETWORK_NAME
;
143 SMB_ASSERT(srv_address
->port
!= 0);
145 ZERO_STRUCT(srv_addr
);
146 #ifdef HAVE_SOCK_SIN_LEN
147 srv_addr
.sin_len
= sizeof(srv_addr
);
149 srv_addr
.sin_addr
.s_addr
= srv_ip
.s_addr
;
150 srv_addr
.sin_port
= htons(srv_address
->port
);
151 srv_addr
.sin_family
= PF_INET
;
153 ret
= connect(sock
->fd
, (const struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
155 return map_nt_error_from_unix_common(errno
);
159 return ip_connect_complete(sock
, flags
);
164 note that for simplicity of the API, socket_listen() is also
165 use for DGRAM sockets, but in reality only a bind() is done
167 static NTSTATUS
ipv4_listen(struct socket_context
*sock
,
168 const struct socket_address
*my_address
,
169 int queue_size
, uint32_t flags
)
171 struct sockaddr_in my_addr
;
172 struct in_addr ip_addr
;
175 socket_set_option(sock
, "SO_REUSEADDR=1", NULL
);
177 if (my_address
->sockaddr
) {
178 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
180 ip_addr
= interpret_addr2(my_address
->addr
);
182 ZERO_STRUCT(my_addr
);
183 #ifdef HAVE_SOCK_SIN_LEN
184 my_addr
.sin_len
= sizeof(my_addr
);
186 my_addr
.sin_addr
.s_addr
= ip_addr
.s_addr
;
187 my_addr
.sin_port
= htons(my_address
->port
);
188 my_addr
.sin_family
= PF_INET
;
190 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
194 return map_nt_error_from_unix_common(errno
);
197 if (sock
->type
== SOCKET_TYPE_STREAM
) {
198 ret
= listen(sock
->fd
, queue_size
);
200 return map_nt_error_from_unix_common(errno
);
204 if (!(flags
& SOCKET_FLAG_BLOCK
)) {
205 ret
= set_blocking(sock
->fd
, false);
207 return map_nt_error_from_unix_common(errno
);
211 sock
->state
= SOCKET_STATE_SERVER_LISTEN
;
216 static NTSTATUS
ipv4_accept(struct socket_context
*sock
, struct socket_context
**new_sock
)
218 struct sockaddr_in cli_addr
;
219 socklen_t cli_addr_len
= sizeof(cli_addr
);
222 if (sock
->type
!= SOCKET_TYPE_STREAM
) {
223 return NT_STATUS_INVALID_PARAMETER
;
226 new_fd
= accept(sock
->fd
, (struct sockaddr
*)&cli_addr
, &cli_addr_len
);
228 return map_nt_error_from_unix_common(errno
);
231 if (!(sock
->flags
& SOCKET_FLAG_BLOCK
)) {
232 int ret
= set_blocking(new_fd
, false);
235 return map_nt_error_from_unix_common(errno
);
239 /* TODO: we could add a 'accept_check' hook here
240 * which get the black/white lists via socket_set_accept_filter()
241 * or something like that
245 (*new_sock
) = talloc(NULL
, struct socket_context
);
248 return NT_STATUS_NO_MEMORY
;
251 /* copy the socket_context */
252 (*new_sock
)->type
= sock
->type
;
253 (*new_sock
)->state
= SOCKET_STATE_SERVER_CONNECTED
;
254 (*new_sock
)->flags
= sock
->flags
;
256 (*new_sock
)->fd
= new_fd
;
258 (*new_sock
)->private_data
= NULL
;
259 (*new_sock
)->ops
= sock
->ops
;
260 (*new_sock
)->backend_name
= sock
->backend_name
;
265 static NTSTATUS
ip_recv(struct socket_context
*sock
, void *buf
,
266 size_t wantlen
, size_t *nread
)
272 gotlen
= recv(sock
->fd
, buf
, wantlen
, 0);
274 return NT_STATUS_END_OF_FILE
;
275 } else if (gotlen
== -1) {
276 return map_nt_error_from_unix_common(errno
);
285 static NTSTATUS
ipv4_recvfrom(struct socket_context
*sock
, void *buf
,
286 size_t wantlen
, size_t *nread
,
287 TALLOC_CTX
*addr_ctx
, struct socket_address
**_src
)
290 struct sockaddr_in
*from_addr
;
291 socklen_t from_len
= sizeof(*from_addr
);
292 struct socket_address
*src
;
293 char addrstring
[INET_ADDRSTRLEN
];
295 src
= talloc(addr_ctx
, struct socket_address
);
297 return NT_STATUS_NO_MEMORY
;
300 src
->family
= sock
->backend_name
;
302 from_addr
= talloc(src
, struct sockaddr_in
);
305 return NT_STATUS_NO_MEMORY
;
308 src
->sockaddr
= (struct sockaddr
*)from_addr
;
312 gotlen
= recvfrom(sock
->fd
, buf
, wantlen
, 0,
313 src
->sockaddr
, &from_len
);
316 return NT_STATUS_END_OF_FILE
;
317 } else if (gotlen
== -1) {
319 return map_nt_error_from_unix_common(errno
);
322 src
->sockaddrlen
= from_len
;
324 if (inet_ntop(AF_INET
, &from_addr
->sin_addr
, addrstring
,
325 sizeof(addrstring
)) == NULL
) {
327 return NT_STATUS_INTERNAL_ERROR
;
329 src
->addr
= talloc_strdup(src
, addrstring
);
330 if (src
->addr
== NULL
) {
332 return NT_STATUS_NO_MEMORY
;
334 src
->port
= ntohs(from_addr
->sin_port
);
341 static NTSTATUS
ip_send(struct socket_context
*sock
,
342 const DATA_BLOB
*blob
, size_t *sendlen
)
348 len
= send(sock
->fd
, blob
->data
, blob
->length
, 0);
350 return map_nt_error_from_unix_common(errno
);
358 static NTSTATUS
ipv4_sendto(struct socket_context
*sock
,
359 const DATA_BLOB
*blob
, size_t *sendlen
,
360 const struct socket_address
*dest_addr
)
364 if (dest_addr
->sockaddr
) {
365 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
366 dest_addr
->sockaddr
, dest_addr
->sockaddrlen
);
368 struct sockaddr_in srv_addr
;
371 SMB_ASSERT(dest_addr
->port
!= 0);
373 ZERO_STRUCT(srv_addr
);
374 #ifdef HAVE_SOCK_SIN_LEN
375 srv_addr
.sin_len
= sizeof(srv_addr
);
377 addr
= interpret_addr2(dest_addr
->addr
);
378 if (addr
.s_addr
== 0) {
379 return NT_STATUS_HOST_UNREACHABLE
;
381 srv_addr
.sin_addr
.s_addr
= addr
.s_addr
;
382 srv_addr
.sin_port
= htons(dest_addr
->port
);
383 srv_addr
.sin_family
= PF_INET
;
387 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
388 (struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
391 return map_nt_error_from_unix_common(errno
);
399 static NTSTATUS
ipv4_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
401 set_socket_options(sock
->fd
, option
);
405 static char *ipv4_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
407 struct sockaddr_in peer_addr
;
408 socklen_t len
= sizeof(peer_addr
);
412 ret
= getpeername(sock
->fd
, (struct sockaddr
*)&peer_addr
, &len
);
417 he
= gethostbyaddr((char *)&peer_addr
.sin_addr
, sizeof(peer_addr
.sin_addr
), AF_INET
);
422 return talloc_strdup(mem_ctx
, he
->h_name
);
425 static struct socket_address
*ipv4_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
427 struct sockaddr_in
*peer_addr
;
428 socklen_t len
= sizeof(*peer_addr
);
429 struct socket_address
*peer
;
430 char addrstring
[INET_ADDRSTRLEN
];
433 peer
= talloc(mem_ctx
, struct socket_address
);
438 peer
->family
= sock
->backend_name
;
439 peer_addr
= talloc(peer
, struct sockaddr_in
);
445 peer
->sockaddr
= (struct sockaddr
*)peer_addr
;
447 ret
= getpeername(sock
->fd
, peer
->sockaddr
, &len
);
453 peer
->sockaddrlen
= len
;
455 if (inet_ntop(AF_INET
, &peer_addr
->sin_addr
, addrstring
,
456 sizeof(addrstring
)) == NULL
) {
460 peer
->addr
= talloc_strdup(peer
, addrstring
);
465 peer
->port
= ntohs(peer_addr
->sin_port
);
470 static struct socket_address
*ipv4_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
472 struct sockaddr_in
*local_addr
;
473 socklen_t len
= sizeof(*local_addr
);
474 struct socket_address
*local
;
475 char addrstring
[INET_ADDRSTRLEN
];
478 local
= talloc(mem_ctx
, struct socket_address
);
483 local
->family
= sock
->backend_name
;
484 local_addr
= talloc(local
, struct sockaddr_in
);
490 local
->sockaddr
= (struct sockaddr
*)local_addr
;
492 ret
= getsockname(sock
->fd
, local
->sockaddr
, &len
);
498 local
->sockaddrlen
= len
;
500 if (inet_ntop(AF_INET
, &local_addr
->sin_addr
, addrstring
,
501 sizeof(addrstring
)) == NULL
) {
505 local
->addr
= talloc_strdup(local
, addrstring
);
510 local
->port
= ntohs(local_addr
->sin_port
);
514 static int ip_get_fd(struct socket_context
*sock
)
519 static NTSTATUS
ip_pending(struct socket_context
*sock
, size_t *npending
)
522 if (ioctl(sock
->fd
, FIONREAD
, &value
) == 0) {
526 return map_nt_error_from_unix_common(errno
);
529 static const struct socket_ops ipv4_ops
= {
531 .fn_init
= ipv4_init
,
532 .fn_connect
= ipv4_connect
,
533 .fn_connect_complete
= ip_connect_complete
,
534 .fn_listen
= ipv4_listen
,
535 .fn_accept
= ipv4_accept
,
537 .fn_recvfrom
= ipv4_recvfrom
,
539 .fn_sendto
= ipv4_sendto
,
540 .fn_pending
= ip_pending
,
541 .fn_close
= ip_close
,
543 .fn_set_option
= ipv4_set_option
,
545 .fn_get_peer_name
= ipv4_get_peer_name
,
546 .fn_get_peer_addr
= ipv4_get_peer_addr
,
547 .fn_get_my_addr
= ipv4_get_my_addr
,
549 .fn_get_fd
= ip_get_fd
552 _PUBLIC_
const struct socket_ops
*socket_ipv4_ops(enum socket_type type
)
559 static struct in6_addr
interpret_addr6(const char *name
)
561 char addr
[INET6_ADDRSTRLEN
];
562 struct in6_addr dest6
;
563 const char *sp
= name
;
567 if (sp
== NULL
) return in6addr_any
;
569 p
= strchr_m(sp
, '%');
571 if (strcasecmp(sp
, "localhost") == 0) {
576 * Cope with link-local.
577 * This is IP:v6:addr%ifname.
580 if (p
&& (p
> sp
) && (if_nametoindex(p
+1) != 0)) {
582 MIN(PTR_DIFF(p
,sp
)+1,
587 ret
= inet_pton(AF_INET6
, sp
, &dest6
);
595 static NTSTATUS
ipv6_init(struct socket_context
*sock
)
599 switch (sock
->type
) {
600 case SOCKET_TYPE_STREAM
:
603 case SOCKET_TYPE_DGRAM
:
607 return NT_STATUS_INVALID_PARAMETER
;
610 sock
->fd
= socket(PF_INET6
, type
, 0);
611 if (sock
->fd
== -1) {
612 return map_nt_error_from_unix_common(errno
);
615 smb_set_close_on_exec(sock
->fd
);
617 sock
->backend_name
= "ipv6";
618 sock
->family
= AF_INET6
;
623 static NTSTATUS
ipv6_tcp_connect(struct socket_context
*sock
,
624 const struct socket_address
*my_address
,
625 const struct socket_address
*srv_address
,
630 if (my_address
&& my_address
->sockaddr
) {
631 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
633 return map_nt_error_from_unix_common(errno
);
635 } else if (my_address
) {
636 struct in6_addr my_ip
;
637 my_ip
= interpret_addr6(my_address
->addr
);
639 if (memcmp(&my_ip
, &in6addr_any
, sizeof(my_ip
)) || my_address
->port
!= 0) {
640 struct sockaddr_in6 my_addr
;
641 ZERO_STRUCT(my_addr
);
642 my_addr
.sin6_addr
= my_ip
;
643 my_addr
.sin6_port
= htons(my_address
->port
);
644 my_addr
.sin6_family
= PF_INET6
;
646 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
648 return map_nt_error_from_unix_common(errno
);
653 if (srv_address
->sockaddr
) {
654 ret
= connect(sock
->fd
, srv_address
->sockaddr
, srv_address
->sockaddrlen
);
656 struct in6_addr srv_ip
;
657 struct sockaddr_in6 srv_addr
;
658 srv_ip
= interpret_addr6(srv_address
->addr
);
659 if (memcmp(&srv_ip
, &in6addr_any
, sizeof(srv_ip
)) == 0) {
660 return NT_STATUS_BAD_NETWORK_NAME
;
663 ZERO_STRUCT(srv_addr
);
664 srv_addr
.sin6_addr
= srv_ip
;
665 srv_addr
.sin6_port
= htons(srv_address
->port
);
666 srv_addr
.sin6_family
= PF_INET6
;
668 ret
= connect(sock
->fd
, (const struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
671 return map_nt_error_from_unix_common(errno
);
674 return ip_connect_complete(sock
, flags
);
678 fix the sin6_scope_id based on the address interface
680 static void fix_scope_id(struct sockaddr_in6
*in6
,
683 const char *p
= strchr(address
, '%');
685 in6
->sin6_scope_id
= if_nametoindex(p
+1);
690 static NTSTATUS
ipv6_listen(struct socket_context
*sock
,
691 const struct socket_address
*my_address
,
692 int queue_size
, uint32_t flags
)
694 struct sockaddr_in6 my_addr
;
695 struct in6_addr ip_addr
;
698 socket_set_option(sock
, "SO_REUSEADDR=1", NULL
);
700 if (my_address
->sockaddr
) {
701 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
704 ip_addr
= interpret_addr6(my_address
->addr
);
706 ZERO_STRUCT(my_addr
);
707 my_addr
.sin6_addr
= ip_addr
;
708 my_addr
.sin6_port
= htons(my_address
->port
);
709 my_addr
.sin6_family
= PF_INET6
;
710 fix_scope_id(&my_addr
, my_address
->addr
);
712 /* when binding on ipv6 we always want to only bind on v6 */
713 ret
= setsockopt(sock
->fd
, IPPROTO_IPV6
, IPV6_V6ONLY
,
714 (const void *)&one
, sizeof(one
));
716 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
721 return map_nt_error_from_unix_common(errno
);
724 if (sock
->type
== SOCKET_TYPE_STREAM
) {
725 ret
= listen(sock
->fd
, queue_size
);
727 return map_nt_error_from_unix_common(errno
);
731 if (!(flags
& SOCKET_FLAG_BLOCK
)) {
732 ret
= set_blocking(sock
->fd
, false);
734 return map_nt_error_from_unix_common(errno
);
738 sock
->state
= SOCKET_STATE_SERVER_LISTEN
;
743 static NTSTATUS
ipv6_tcp_accept(struct socket_context
*sock
, struct socket_context
**new_sock
)
745 struct sockaddr_in6 cli_addr
;
746 socklen_t cli_addr_len
= sizeof(cli_addr
);
749 if (sock
->type
!= SOCKET_TYPE_STREAM
) {
750 return NT_STATUS_INVALID_PARAMETER
;
753 new_fd
= accept(sock
->fd
, (struct sockaddr
*)&cli_addr
, &cli_addr_len
);
755 return map_nt_error_from_unix_common(errno
);
758 if (!(sock
->flags
& SOCKET_FLAG_BLOCK
)) {
759 int ret
= set_blocking(new_fd
, false);
762 return map_nt_error_from_unix_common(errno
);
766 /* TODO: we could add a 'accept_check' hook here
767 * which get the black/white lists via socket_set_accept_filter()
768 * or something like that
772 (*new_sock
) = talloc(NULL
, struct socket_context
);
775 return NT_STATUS_NO_MEMORY
;
778 /* copy the socket_context */
779 (*new_sock
)->type
= sock
->type
;
780 (*new_sock
)->state
= SOCKET_STATE_SERVER_CONNECTED
;
781 (*new_sock
)->flags
= sock
->flags
;
783 (*new_sock
)->fd
= new_fd
;
785 (*new_sock
)->private_data
= NULL
;
786 (*new_sock
)->ops
= sock
->ops
;
787 (*new_sock
)->backend_name
= sock
->backend_name
;
792 static NTSTATUS
ipv6_recvfrom(struct socket_context
*sock
, void *buf
,
793 size_t wantlen
, size_t *nread
,
794 TALLOC_CTX
*addr_ctx
, struct socket_address
**_src
)
797 struct sockaddr_in6
*from_addr
;
798 socklen_t from_len
= sizeof(*from_addr
);
799 struct socket_address
*src
;
800 char addrstring
[INET6_ADDRSTRLEN
];
802 src
= talloc(addr_ctx
, struct socket_address
);
804 return NT_STATUS_NO_MEMORY
;
807 src
->family
= sock
->backend_name
;
809 from_addr
= talloc(src
, struct sockaddr_in6
);
812 return NT_STATUS_NO_MEMORY
;
815 src
->sockaddr
= (struct sockaddr
*)from_addr
;
819 gotlen
= recvfrom(sock
->fd
, buf
, wantlen
, 0,
820 src
->sockaddr
, &from_len
);
823 return NT_STATUS_END_OF_FILE
;
824 } else if (gotlen
== -1) {
826 return map_nt_error_from_unix_common(errno
);
829 src
->sockaddrlen
= from_len
;
831 if (inet_ntop(AF_INET6
, &from_addr
->sin6_addr
, addrstring
, sizeof(addrstring
)) == NULL
) {
832 DEBUG(0, ("Unable to convert address to string: %s\n", strerror(errno
)));
834 return NT_STATUS_INTERNAL_ERROR
;
837 src
->addr
= talloc_strdup(src
, addrstring
);
838 if (src
->addr
== NULL
) {
840 return NT_STATUS_NO_MEMORY
;
842 src
->port
= ntohs(from_addr
->sin6_port
);
849 static NTSTATUS
ipv6_sendto(struct socket_context
*sock
,
850 const DATA_BLOB
*blob
, size_t *sendlen
,
851 const struct socket_address
*dest_addr
)
855 if (dest_addr
->sockaddr
) {
856 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
857 dest_addr
->sockaddr
, dest_addr
->sockaddrlen
);
859 struct sockaddr_in6 srv_addr
;
860 struct in6_addr addr
;
862 ZERO_STRUCT(srv_addr
);
863 addr
= interpret_addr6(dest_addr
->addr
);
864 if (addr
.s6_addr
== 0) {
865 return NT_STATUS_HOST_UNREACHABLE
;
867 srv_addr
.sin6_addr
= addr
;
868 srv_addr
.sin6_port
= htons(dest_addr
->port
);
869 srv_addr
.sin6_family
= PF_INET6
;
873 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
874 (struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
877 return map_nt_error_from_unix_common(errno
);
885 static NTSTATUS
ipv6_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
887 set_socket_options(sock
->fd
, option
);
891 static char *ipv6_tcp_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
893 struct sockaddr_in6 peer_addr
;
894 socklen_t len
= sizeof(peer_addr
);
898 ret
= getpeername(sock
->fd
, (struct sockaddr
*)&peer_addr
, &len
);
903 he
= gethostbyaddr((char *)&peer_addr
.sin6_addr
, sizeof(peer_addr
.sin6_addr
), AF_INET6
);
908 return talloc_strdup(mem_ctx
, he
->h_name
);
911 static struct socket_address
*ipv6_tcp_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
913 struct sockaddr_in6
*peer_addr
;
914 socklen_t len
= sizeof(*peer_addr
);
915 struct socket_address
*peer
;
918 const char *addr_ret
;
920 peer
= talloc(mem_ctx
, struct socket_address
);
925 peer
->family
= sock
->backend_name
;
926 peer_addr
= talloc(peer
, struct sockaddr_in6
);
932 peer
->sockaddr
= (struct sockaddr
*)peer_addr
;
934 ret
= getpeername(sock
->fd
, peer
->sockaddr
, &len
);
940 peer
->sockaddrlen
= len
;
942 addr_ret
= inet_ntop(AF_INET6
, &peer_addr
->sin6_addr
, addr
, sizeof(addr
));
943 if (addr_ret
== NULL
) {
948 peer
->addr
= talloc_strdup(peer
, addr_ret
);
949 if (peer
->addr
== NULL
) {
954 peer
->port
= ntohs(peer_addr
->sin6_port
);
959 static struct socket_address
*ipv6_tcp_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
961 struct sockaddr_in6
*local_addr
;
962 socklen_t len
= sizeof(*local_addr
);
963 struct socket_address
*local
;
965 char addrstring
[INET6_ADDRSTRLEN
];
967 local
= talloc(mem_ctx
, struct socket_address
);
972 local
->family
= sock
->backend_name
;
973 local_addr
= talloc(local
, struct sockaddr_in6
);
979 local
->sockaddr
= (struct sockaddr
*)local_addr
;
981 ret
= getsockname(sock
->fd
, local
->sockaddr
, &len
);
987 local
->sockaddrlen
= len
;
989 if (inet_ntop(AF_INET6
, &local_addr
->sin6_addr
, addrstring
,
990 sizeof(addrstring
)) == NULL
) {
991 DEBUG(0, ("Unable to convert address to string: %s\n",
997 local
->addr
= talloc_strdup(mem_ctx
, addrstring
);
1002 local
->port
= ntohs(local_addr
->sin6_port
);
1007 static const struct socket_ops ipv6_tcp_ops
= {
1009 .fn_init
= ipv6_init
,
1010 .fn_connect
= ipv6_tcp_connect
,
1011 .fn_connect_complete
= ip_connect_complete
,
1012 .fn_listen
= ipv6_listen
,
1013 .fn_accept
= ipv6_tcp_accept
,
1015 .fn_recvfrom
= ipv6_recvfrom
,
1017 .fn_sendto
= ipv6_sendto
,
1018 .fn_pending
= ip_pending
,
1019 .fn_close
= ip_close
,
1021 .fn_set_option
= ipv6_set_option
,
1023 .fn_get_peer_name
= ipv6_tcp_get_peer_name
,
1024 .fn_get_peer_addr
= ipv6_tcp_get_peer_addr
,
1025 .fn_get_my_addr
= ipv6_tcp_get_my_addr
,
1027 .fn_get_fd
= ip_get_fd
1030 _PUBLIC_
const struct socket_ops
*socket_ipv6_ops(enum socket_type type
)
1032 return &ipv6_tcp_ops
;