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 static NTSTATUS
ipv4_init(struct socket_context
*sock
)
35 case SOCKET_TYPE_STREAM
:
38 case SOCKET_TYPE_DGRAM
:
42 return NT_STATUS_INVALID_PARAMETER
;
45 sock
->fd
= socket(PF_INET
, type
, 0);
47 return map_nt_error_from_unix(errno
);
50 sock
->backend_name
= "ipv4";
51 sock
->family
= AF_INET
;
56 static void ip_close(struct socket_context
*sock
)
61 static NTSTATUS
ip_connect_complete(struct socket_context
*sock
, uint32_t flags
)
64 socklen_t len
= sizeof(error
);
66 /* check for any errors that may have occurred - this is needed
67 for non-blocking connect */
68 ret
= getsockopt(sock
->fd
, SOL_SOCKET
, SO_ERROR
, &error
, &len
);
70 return map_nt_error_from_unix(errno
);
73 return map_nt_error_from_unix(error
);
76 if (!(flags
& SOCKET_FLAG_BLOCK
)) {
77 ret
= set_blocking(sock
->fd
, false);
79 return map_nt_error_from_unix(errno
);
83 sock
->state
= SOCKET_STATE_CLIENT_CONNECTED
;
89 static NTSTATUS
ipv4_connect(struct socket_context
*sock
,
90 const struct socket_address
*my_address
,
91 const struct socket_address
*srv_address
,
94 struct sockaddr_in srv_addr
;
96 struct in_addr srv_ip
;
99 if (my_address
&& my_address
->sockaddr
) {
100 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
102 return map_nt_error_from_unix(errno
);
104 } else if (my_address
) {
105 my_ip
= interpret_addr2(my_address
->addr
);
107 if (my_ip
.s_addr
!= 0 || my_address
->port
!= 0) {
108 struct sockaddr_in my_addr
;
109 ZERO_STRUCT(my_addr
);
110 #ifdef HAVE_SOCK_SIN_LEN
111 my_addr
.sin_len
= sizeof(my_addr
);
113 my_addr
.sin_addr
.s_addr
= my_ip
.s_addr
;
114 my_addr
.sin_port
= htons(my_address
->port
);
115 my_addr
.sin_family
= PF_INET
;
117 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
119 return map_nt_error_from_unix(errno
);
124 if (srv_address
->sockaddr
) {
125 ret
= connect(sock
->fd
, srv_address
->sockaddr
, srv_address
->sockaddrlen
);
127 return map_nt_error_from_unix(errno
);
130 srv_ip
= interpret_addr2(srv_address
->addr
);
131 if (!srv_ip
.s_addr
) {
132 return NT_STATUS_BAD_NETWORK_NAME
;
135 SMB_ASSERT(srv_address
->port
!= 0);
137 ZERO_STRUCT(srv_addr
);
138 #ifdef HAVE_SOCK_SIN_LEN
139 srv_addr
.sin_len
= sizeof(srv_addr
);
141 srv_addr
.sin_addr
.s_addr
= srv_ip
.s_addr
;
142 srv_addr
.sin_port
= htons(srv_address
->port
);
143 srv_addr
.sin_family
= PF_INET
;
145 ret
= connect(sock
->fd
, (const struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
147 return map_nt_error_from_unix(errno
);
151 return ip_connect_complete(sock
, flags
);
156 note that for simplicity of the API, socket_listen() is also
157 use for DGRAM sockets, but in reality only a bind() is done
159 static NTSTATUS
ipv4_listen(struct socket_context
*sock
,
160 const struct socket_address
*my_address
,
161 int queue_size
, uint32_t flags
)
163 struct sockaddr_in my_addr
;
164 struct in_addr ip_addr
;
167 socket_set_option(sock
, "SO_REUSEADDR=1", NULL
);
169 if (my_address
->sockaddr
) {
170 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
172 ip_addr
= interpret_addr2(my_address
->addr
);
174 ZERO_STRUCT(my_addr
);
175 #ifdef HAVE_SOCK_SIN_LEN
176 my_addr
.sin_len
= sizeof(my_addr
);
178 my_addr
.sin_addr
.s_addr
= ip_addr
.s_addr
;
179 my_addr
.sin_port
= htons(my_address
->port
);
180 my_addr
.sin_family
= PF_INET
;
182 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
186 return map_nt_error_from_unix(errno
);
189 if (sock
->type
== SOCKET_TYPE_STREAM
) {
190 ret
= listen(sock
->fd
, queue_size
);
192 return map_nt_error_from_unix(errno
);
196 if (!(flags
& SOCKET_FLAG_BLOCK
)) {
197 ret
= set_blocking(sock
->fd
, false);
199 return map_nt_error_from_unix(errno
);
203 sock
->state
= SOCKET_STATE_SERVER_LISTEN
;
208 static NTSTATUS
ipv4_accept(struct socket_context
*sock
, struct socket_context
**new_sock
)
210 struct sockaddr_in cli_addr
;
211 socklen_t cli_addr_len
= sizeof(cli_addr
);
214 if (sock
->type
!= SOCKET_TYPE_STREAM
) {
215 return NT_STATUS_INVALID_PARAMETER
;
218 new_fd
= accept(sock
->fd
, (struct sockaddr
*)&cli_addr
, &cli_addr_len
);
220 return map_nt_error_from_unix(errno
);
223 if (!(sock
->flags
& SOCKET_FLAG_BLOCK
)) {
224 int ret
= set_blocking(new_fd
, false);
227 return map_nt_error_from_unix(errno
);
231 /* TODO: we could add a 'accept_check' hook here
232 * which get the black/white lists via socket_set_accept_filter()
233 * or something like that
237 (*new_sock
) = talloc(NULL
, struct socket_context
);
240 return NT_STATUS_NO_MEMORY
;
243 /* copy the socket_context */
244 (*new_sock
)->type
= sock
->type
;
245 (*new_sock
)->state
= SOCKET_STATE_SERVER_CONNECTED
;
246 (*new_sock
)->flags
= sock
->flags
;
248 (*new_sock
)->fd
= new_fd
;
250 (*new_sock
)->private_data
= NULL
;
251 (*new_sock
)->ops
= sock
->ops
;
252 (*new_sock
)->backend_name
= sock
->backend_name
;
257 static NTSTATUS
ip_recv(struct socket_context
*sock
, void *buf
,
258 size_t wantlen
, size_t *nread
)
264 gotlen
= recv(sock
->fd
, buf
, wantlen
, 0);
266 return NT_STATUS_END_OF_FILE
;
267 } else if (gotlen
== -1) {
268 return map_nt_error_from_unix(errno
);
277 static NTSTATUS
ipv4_recvfrom(struct socket_context
*sock
, void *buf
,
278 size_t wantlen
, size_t *nread
,
279 TALLOC_CTX
*addr_ctx
, struct socket_address
**_src
)
282 struct sockaddr_in
*from_addr
;
283 socklen_t from_len
= sizeof(*from_addr
);
284 struct socket_address
*src
;
285 char addrstring
[INET_ADDRSTRLEN
];
287 src
= talloc(addr_ctx
, struct socket_address
);
289 return NT_STATUS_NO_MEMORY
;
292 src
->family
= sock
->backend_name
;
294 from_addr
= talloc(src
, struct sockaddr_in
);
297 return NT_STATUS_NO_MEMORY
;
300 src
->sockaddr
= (struct sockaddr
*)from_addr
;
304 gotlen
= recvfrom(sock
->fd
, buf
, wantlen
, 0,
305 src
->sockaddr
, &from_len
);
308 return NT_STATUS_END_OF_FILE
;
309 } else if (gotlen
== -1) {
311 return map_nt_error_from_unix(errno
);
314 src
->sockaddrlen
= from_len
;
316 if (inet_ntop(AF_INET
, &from_addr
->sin_addr
, addrstring
,
317 sizeof(addrstring
)) == NULL
) {
319 return NT_STATUS_INTERNAL_ERROR
;
321 src
->addr
= talloc_strdup(src
, addrstring
);
322 if (src
->addr
== NULL
) {
324 return NT_STATUS_NO_MEMORY
;
326 src
->port
= ntohs(from_addr
->sin_port
);
333 static NTSTATUS
ip_send(struct socket_context
*sock
,
334 const DATA_BLOB
*blob
, size_t *sendlen
)
340 len
= send(sock
->fd
, blob
->data
, blob
->length
, 0);
342 return map_nt_error_from_unix(errno
);
350 static NTSTATUS
ipv4_sendto(struct socket_context
*sock
,
351 const DATA_BLOB
*blob
, size_t *sendlen
,
352 const struct socket_address
*dest_addr
)
356 if (dest_addr
->sockaddr
) {
357 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
358 dest_addr
->sockaddr
, dest_addr
->sockaddrlen
);
360 struct sockaddr_in srv_addr
;
363 SMB_ASSERT(dest_addr
->port
!= 0);
365 ZERO_STRUCT(srv_addr
);
366 #ifdef HAVE_SOCK_SIN_LEN
367 srv_addr
.sin_len
= sizeof(srv_addr
);
369 addr
= interpret_addr2(dest_addr
->addr
);
370 if (addr
.s_addr
== 0) {
371 return NT_STATUS_HOST_UNREACHABLE
;
373 srv_addr
.sin_addr
.s_addr
= addr
.s_addr
;
374 srv_addr
.sin_port
= htons(dest_addr
->port
);
375 srv_addr
.sin_family
= PF_INET
;
379 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
380 (struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
383 return map_nt_error_from_unix(errno
);
391 static NTSTATUS
ipv4_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
393 set_socket_options(sock
->fd
, option
);
397 static char *ipv4_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
399 struct sockaddr_in peer_addr
;
400 socklen_t len
= sizeof(peer_addr
);
404 ret
= getpeername(sock
->fd
, (struct sockaddr
*)&peer_addr
, &len
);
409 he
= gethostbyaddr((char *)&peer_addr
.sin_addr
, sizeof(peer_addr
.sin_addr
), AF_INET
);
414 return talloc_strdup(mem_ctx
, he
->h_name
);
417 static struct socket_address
*ipv4_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
419 struct sockaddr_in
*peer_addr
;
420 socklen_t len
= sizeof(*peer_addr
);
421 struct socket_address
*peer
;
422 char addrstring
[INET_ADDRSTRLEN
];
425 peer
= talloc(mem_ctx
, struct socket_address
);
430 peer
->family
= sock
->backend_name
;
431 peer_addr
= talloc(peer
, struct sockaddr_in
);
437 peer
->sockaddr
= (struct sockaddr
*)peer_addr
;
439 ret
= getpeername(sock
->fd
, peer
->sockaddr
, &len
);
445 peer
->sockaddrlen
= len
;
447 if (inet_ntop(AF_INET
, &peer_addr
->sin_addr
, addrstring
,
448 sizeof(addrstring
)) == NULL
) {
452 peer
->addr
= talloc_strdup(peer
, addrstring
);
457 peer
->port
= ntohs(peer_addr
->sin_port
);
462 static struct socket_address
*ipv4_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
464 struct sockaddr_in
*local_addr
;
465 socklen_t len
= sizeof(*local_addr
);
466 struct socket_address
*local
;
467 char addrstring
[INET_ADDRSTRLEN
];
470 local
= talloc(mem_ctx
, struct socket_address
);
475 local
->family
= sock
->backend_name
;
476 local_addr
= talloc(local
, struct sockaddr_in
);
482 local
->sockaddr
= (struct sockaddr
*)local_addr
;
484 ret
= getsockname(sock
->fd
, local
->sockaddr
, &len
);
490 local
->sockaddrlen
= len
;
492 if (inet_ntop(AF_INET
, &local_addr
->sin_addr
, addrstring
,
493 sizeof(addrstring
)) == NULL
) {
497 local
->addr
= talloc_strdup(local
, addrstring
);
502 local
->port
= ntohs(local_addr
->sin_port
);
506 static int ip_get_fd(struct socket_context
*sock
)
511 static NTSTATUS
ip_pending(struct socket_context
*sock
, size_t *npending
)
514 if (ioctl(sock
->fd
, FIONREAD
, &value
) == 0) {
518 return map_nt_error_from_unix(errno
);
521 static const struct socket_ops ipv4_ops
= {
523 .fn_init
= ipv4_init
,
524 .fn_connect
= ipv4_connect
,
525 .fn_connect_complete
= ip_connect_complete
,
526 .fn_listen
= ipv4_listen
,
527 .fn_accept
= ipv4_accept
,
529 .fn_recvfrom
= ipv4_recvfrom
,
531 .fn_sendto
= ipv4_sendto
,
532 .fn_pending
= ip_pending
,
533 .fn_close
= ip_close
,
535 .fn_set_option
= ipv4_set_option
,
537 .fn_get_peer_name
= ipv4_get_peer_name
,
538 .fn_get_peer_addr
= ipv4_get_peer_addr
,
539 .fn_get_my_addr
= ipv4_get_my_addr
,
541 .fn_get_fd
= ip_get_fd
544 _PUBLIC_
const struct socket_ops
*socket_ipv4_ops(enum socket_type type
)
551 static struct in6_addr
interpret_addr6(const char *name
)
553 char addr
[INET6_ADDRSTRLEN
];
554 struct in6_addr dest6
;
555 const char *sp
= name
;
559 if (sp
== NULL
) return in6addr_any
;
561 p
= strchr_m(sp
, '%');
563 if (strcasecmp(sp
, "localhost") == 0) {
568 * Cope with link-local.
569 * This is IP:v6:addr%ifname.
572 if (p
&& (p
> sp
) && (if_nametoindex(p
+1) != 0)) {
574 MIN(PTR_DIFF(p
,sp
)+1,
579 ret
= inet_pton(AF_INET6
, sp
, &dest6
);
587 static NTSTATUS
ipv6_init(struct socket_context
*sock
)
591 switch (sock
->type
) {
592 case SOCKET_TYPE_STREAM
:
595 case SOCKET_TYPE_DGRAM
:
599 return NT_STATUS_INVALID_PARAMETER
;
602 sock
->fd
= socket(PF_INET6
, type
, 0);
603 if (sock
->fd
== -1) {
604 return map_nt_error_from_unix(errno
);
607 sock
->backend_name
= "ipv6";
608 sock
->family
= AF_INET6
;
613 static NTSTATUS
ipv6_tcp_connect(struct socket_context
*sock
,
614 const struct socket_address
*my_address
,
615 const struct socket_address
*srv_address
,
620 if (my_address
&& my_address
->sockaddr
) {
621 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
623 return map_nt_error_from_unix(errno
);
625 } else if (my_address
) {
626 struct in6_addr my_ip
;
627 my_ip
= interpret_addr6(my_address
->addr
);
629 if (memcmp(&my_ip
, &in6addr_any
, sizeof(my_ip
)) || my_address
->port
!= 0) {
630 struct sockaddr_in6 my_addr
;
631 ZERO_STRUCT(my_addr
);
632 my_addr
.sin6_addr
= my_ip
;
633 my_addr
.sin6_port
= htons(my_address
->port
);
634 my_addr
.sin6_family
= PF_INET6
;
636 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
638 return map_nt_error_from_unix(errno
);
643 if (srv_address
->sockaddr
) {
644 ret
= connect(sock
->fd
, srv_address
->sockaddr
, srv_address
->sockaddrlen
);
646 struct in6_addr srv_ip
;
647 struct sockaddr_in6 srv_addr
;
648 srv_ip
= interpret_addr6(srv_address
->addr
);
649 if (memcmp(&srv_ip
, &in6addr_any
, sizeof(srv_ip
)) == 0) {
650 return NT_STATUS_BAD_NETWORK_NAME
;
653 ZERO_STRUCT(srv_addr
);
654 srv_addr
.sin6_addr
= srv_ip
;
655 srv_addr
.sin6_port
= htons(srv_address
->port
);
656 srv_addr
.sin6_family
= PF_INET6
;
658 ret
= connect(sock
->fd
, (const struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
661 return map_nt_error_from_unix(errno
);
664 return ip_connect_complete(sock
, flags
);
667 static NTSTATUS
ipv6_listen(struct socket_context
*sock
,
668 const struct socket_address
*my_address
,
669 int queue_size
, uint32_t flags
)
671 struct sockaddr_in6 my_addr
;
672 struct in6_addr ip_addr
;
675 socket_set_option(sock
, "SO_REUSEADDR=1", NULL
);
677 if (my_address
->sockaddr
) {
678 ret
= bind(sock
->fd
, my_address
->sockaddr
, my_address
->sockaddrlen
);
680 ip_addr
= interpret_addr6(my_address
->addr
);
682 ZERO_STRUCT(my_addr
);
683 my_addr
.sin6_addr
= ip_addr
;
684 my_addr
.sin6_port
= htons(my_address
->port
);
685 my_addr
.sin6_family
= PF_INET6
;
687 ret
= bind(sock
->fd
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
));
691 return map_nt_error_from_unix(errno
);
694 if (sock
->type
== SOCKET_TYPE_STREAM
) {
695 ret
= listen(sock
->fd
, queue_size
);
697 return map_nt_error_from_unix(errno
);
701 if (!(flags
& SOCKET_FLAG_BLOCK
)) {
702 ret
= set_blocking(sock
->fd
, false);
704 return map_nt_error_from_unix(errno
);
708 sock
->state
= SOCKET_STATE_SERVER_LISTEN
;
713 static NTSTATUS
ipv6_tcp_accept(struct socket_context
*sock
, struct socket_context
**new_sock
)
715 struct sockaddr_in6 cli_addr
;
716 socklen_t cli_addr_len
= sizeof(cli_addr
);
719 if (sock
->type
!= SOCKET_TYPE_STREAM
) {
720 return NT_STATUS_INVALID_PARAMETER
;
723 new_fd
= accept(sock
->fd
, (struct sockaddr
*)&cli_addr
, &cli_addr_len
);
725 return map_nt_error_from_unix(errno
);
728 if (!(sock
->flags
& SOCKET_FLAG_BLOCK
)) {
729 int ret
= set_blocking(new_fd
, false);
732 return map_nt_error_from_unix(errno
);
736 /* TODO: we could add a 'accept_check' hook here
737 * which get the black/white lists via socket_set_accept_filter()
738 * or something like that
742 (*new_sock
) = talloc(NULL
, struct socket_context
);
745 return NT_STATUS_NO_MEMORY
;
748 /* copy the socket_context */
749 (*new_sock
)->type
= sock
->type
;
750 (*new_sock
)->state
= SOCKET_STATE_SERVER_CONNECTED
;
751 (*new_sock
)->flags
= sock
->flags
;
753 (*new_sock
)->fd
= new_fd
;
755 (*new_sock
)->private_data
= NULL
;
756 (*new_sock
)->ops
= sock
->ops
;
757 (*new_sock
)->backend_name
= sock
->backend_name
;
762 static NTSTATUS
ipv6_recvfrom(struct socket_context
*sock
, void *buf
,
763 size_t wantlen
, size_t *nread
,
764 TALLOC_CTX
*addr_ctx
, struct socket_address
**_src
)
767 struct sockaddr_in6
*from_addr
;
768 socklen_t from_len
= sizeof(*from_addr
);
769 struct socket_address
*src
;
770 char addrstring
[INET6_ADDRSTRLEN
];
772 src
= talloc(addr_ctx
, struct socket_address
);
774 return NT_STATUS_NO_MEMORY
;
777 src
->family
= sock
->backend_name
;
779 from_addr
= talloc(src
, struct sockaddr_in6
);
782 return NT_STATUS_NO_MEMORY
;
785 src
->sockaddr
= (struct sockaddr
*)from_addr
;
789 gotlen
= recvfrom(sock
->fd
, buf
, wantlen
, 0,
790 src
->sockaddr
, &from_len
);
793 return NT_STATUS_END_OF_FILE
;
794 } else if (gotlen
== -1) {
796 return map_nt_error_from_unix(errno
);
799 src
->sockaddrlen
= from_len
;
801 if (inet_ntop(AF_INET6
, &from_addr
->sin6_addr
, addrstring
, sizeof(addrstring
)) == NULL
) {
802 DEBUG(0, ("Unable to convert address to string: %s\n", strerror(errno
)));
804 return NT_STATUS_INTERNAL_ERROR
;
807 src
->addr
= talloc_strdup(src
, addrstring
);
808 if (src
->addr
== NULL
) {
810 return NT_STATUS_NO_MEMORY
;
812 src
->port
= ntohs(from_addr
->sin6_port
);
819 static NTSTATUS
ipv6_sendto(struct socket_context
*sock
,
820 const DATA_BLOB
*blob
, size_t *sendlen
,
821 const struct socket_address
*dest_addr
)
825 if (dest_addr
->sockaddr
) {
826 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
827 dest_addr
->sockaddr
, dest_addr
->sockaddrlen
);
829 struct sockaddr_in6 srv_addr
;
830 struct in6_addr addr
;
832 ZERO_STRUCT(srv_addr
);
833 addr
= interpret_addr6(dest_addr
->addr
);
834 if (addr
.s6_addr
== 0) {
835 return NT_STATUS_HOST_UNREACHABLE
;
837 srv_addr
.sin6_addr
= addr
;
838 srv_addr
.sin6_port
= htons(dest_addr
->port
);
839 srv_addr
.sin6_family
= PF_INET6
;
843 len
= sendto(sock
->fd
, blob
->data
, blob
->length
, 0,
844 (struct sockaddr
*)&srv_addr
, sizeof(srv_addr
));
847 return map_nt_error_from_unix(errno
);
855 static NTSTATUS
ipv6_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
857 set_socket_options(sock
->fd
, option
);
861 static char *ipv6_tcp_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
863 struct sockaddr_in6 peer_addr
;
864 socklen_t len
= sizeof(peer_addr
);
868 ret
= getpeername(sock
->fd
, (struct sockaddr
*)&peer_addr
, &len
);
873 he
= gethostbyaddr((char *)&peer_addr
.sin6_addr
, sizeof(peer_addr
.sin6_addr
), AF_INET6
);
878 return talloc_strdup(mem_ctx
, he
->h_name
);
881 static struct socket_address
*ipv6_tcp_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
883 struct sockaddr_in6
*peer_addr
;
884 socklen_t len
= sizeof(*peer_addr
);
885 struct socket_address
*peer
;
888 const char *addr_ret
;
890 peer
= talloc(mem_ctx
, struct socket_address
);
895 peer
->family
= sock
->backend_name
;
896 peer_addr
= talloc(peer
, struct sockaddr_in6
);
902 peer
->sockaddr
= (struct sockaddr
*)peer_addr
;
904 ret
= getpeername(sock
->fd
, peer
->sockaddr
, &len
);
910 peer
->sockaddrlen
= len
;
912 addr_ret
= inet_ntop(AF_INET6
, &peer_addr
->sin6_addr
, addr
, sizeof(addr
));
913 if (addr_ret
== NULL
) {
918 peer
->addr
= talloc_strdup(peer
, addr_ret
);
919 if (peer
->addr
== NULL
) {
924 peer
->port
= ntohs(peer_addr
->sin6_port
);
929 static struct socket_address
*ipv6_tcp_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
931 struct sockaddr_in6
*local_addr
;
932 socklen_t len
= sizeof(*local_addr
);
933 struct socket_address
*local
;
935 char addrstring
[INET6_ADDRSTRLEN
];
937 local
= talloc(mem_ctx
, struct socket_address
);
942 local
->family
= sock
->backend_name
;
943 local_addr
= talloc(local
, struct sockaddr_in6
);
949 local
->sockaddr
= (struct sockaddr
*)local_addr
;
951 ret
= getsockname(sock
->fd
, local
->sockaddr
, &len
);
957 local
->sockaddrlen
= len
;
959 if (inet_ntop(AF_INET6
, &local_addr
->sin6_addr
, addrstring
,
960 sizeof(addrstring
)) == NULL
) {
961 DEBUG(0, ("Unable to convert address to string: %s\n",
967 local
->addr
= talloc_strdup(mem_ctx
, addrstring
);
972 local
->port
= ntohs(local_addr
->sin6_port
);
977 static const struct socket_ops ipv6_tcp_ops
= {
979 .fn_init
= ipv6_init
,
980 .fn_connect
= ipv6_tcp_connect
,
981 .fn_connect_complete
= ip_connect_complete
,
982 .fn_listen
= ipv6_listen
,
983 .fn_accept
= ipv6_tcp_accept
,
985 .fn_recvfrom
= ipv6_recvfrom
,
987 .fn_sendto
= ipv6_sendto
,
988 .fn_pending
= ip_pending
,
989 .fn_close
= ip_close
,
991 .fn_set_option
= ipv6_set_option
,
993 .fn_get_peer_name
= ipv6_tcp_get_peer_name
,
994 .fn_get_peer_addr
= ipv6_tcp_get_peer_addr
,
995 .fn_get_my_addr
= ipv6_tcp_get_my_addr
,
997 .fn_get_fd
= ip_get_fd
1000 _PUBLIC_
const struct socket_ops
*socket_ipv6_ops(enum socket_type type
)
1002 return &ipv6_tcp_ops
;