2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Tim Potter 2000-2001
6 Copyright (C) Stefan Metzmacher 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "lib/socket/socket.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "param/param.h"
27 #include "../lib/tsocket/tsocket.h"
28 #include "lib/util/util_net.h"
31 auto-close sockets on free
33 static int socket_destructor(struct socket_context
*sock
)
35 if (sock
->ops
->fn_close
&&
36 !(sock
->flags
& SOCKET_FLAG_NOCLOSE
)) {
37 sock
->ops
->fn_close(sock
);
42 _PUBLIC_
void socket_tevent_fd_close_fn(struct tevent_context
*ev
,
43 struct tevent_fd
*fde
,
47 /* this might be the socket_wrapper swrap_close() */
51 _PUBLIC_ NTSTATUS
socket_create_with_ops(TALLOC_CTX
*mem_ctx
, const struct socket_ops
*ops
,
52 struct socket_context
**new_sock
,
53 enum socket_type type
, uint32_t flags
)
57 (*new_sock
) = talloc(mem_ctx
, struct socket_context
);
59 return NT_STATUS_NO_MEMORY
;
62 (*new_sock
)->type
= type
;
63 (*new_sock
)->state
= SOCKET_STATE_UNDEFINED
;
64 (*new_sock
)->flags
= flags
;
68 (*new_sock
)->private_data
= NULL
;
69 (*new_sock
)->ops
= ops
;
70 (*new_sock
)->backend_name
= NULL
;
72 status
= (*new_sock
)->ops
->fn_init((*new_sock
));
73 if (!NT_STATUS_IS_OK(status
)) {
74 talloc_free(*new_sock
);
78 /* by enabling "testnonblock" mode, all socket receive and
79 send calls on non-blocking sockets will randomly recv/send
80 less data than requested */
82 if (!(flags
& SOCKET_FLAG_BLOCK
) &&
83 type
== SOCKET_TYPE_STREAM
&&
84 getenv("SOCKET_TESTNONBLOCK") != NULL
) {
85 (*new_sock
)->flags
|= SOCKET_FLAG_TESTNONBLOCK
;
88 /* we don't do a connect() on dgram sockets, so need to set
89 non-blocking at socket create time */
90 if (!(flags
& SOCKET_FLAG_BLOCK
) && type
== SOCKET_TYPE_DGRAM
) {
91 set_blocking(socket_get_fd(*new_sock
), false);
94 talloc_set_destructor(*new_sock
, socket_destructor
);
99 _PUBLIC_ NTSTATUS
socket_create(const char *name
, enum socket_type type
,
100 struct socket_context
**new_sock
, uint32_t flags
)
102 const struct socket_ops
*ops
;
104 ops
= socket_getops_byname(name
, type
);
106 return NT_STATUS_INVALID_PARAMETER
;
109 return socket_create_with_ops(NULL
, ops
, new_sock
, type
, flags
);
112 _PUBLIC_ NTSTATUS
socket_connect(struct socket_context
*sock
,
113 const struct socket_address
*my_address
,
114 const struct socket_address
*server_address
,
118 return NT_STATUS_CONNECTION_DISCONNECTED
;
120 if (sock
->state
!= SOCKET_STATE_UNDEFINED
) {
121 return NT_STATUS_INVALID_PARAMETER
;
124 if (!sock
->ops
->fn_connect
) {
125 return NT_STATUS_NOT_IMPLEMENTED
;
128 return sock
->ops
->fn_connect(sock
, my_address
, server_address
, flags
);
131 _PUBLIC_ NTSTATUS
socket_connect_complete(struct socket_context
*sock
, uint32_t flags
)
133 if (!sock
->ops
->fn_connect_complete
) {
134 return NT_STATUS_NOT_IMPLEMENTED
;
136 return sock
->ops
->fn_connect_complete(sock
, flags
);
139 _PUBLIC_ NTSTATUS
socket_listen(struct socket_context
*sock
,
140 const struct socket_address
*my_address
,
141 int queue_size
, uint32_t flags
)
144 return NT_STATUS_CONNECTION_DISCONNECTED
;
146 if (sock
->state
!= SOCKET_STATE_UNDEFINED
) {
147 return NT_STATUS_INVALID_PARAMETER
;
150 if (!sock
->ops
->fn_listen
) {
151 return NT_STATUS_NOT_IMPLEMENTED
;
154 return sock
->ops
->fn_listen(sock
, my_address
, queue_size
, flags
);
157 _PUBLIC_ NTSTATUS
socket_accept(struct socket_context
*sock
, struct socket_context
**new_sock
)
162 return NT_STATUS_CONNECTION_DISCONNECTED
;
164 if (sock
->type
!= SOCKET_TYPE_STREAM
) {
165 return NT_STATUS_INVALID_PARAMETER
;
168 if (sock
->state
!= SOCKET_STATE_SERVER_LISTEN
) {
169 return NT_STATUS_INVALID_PARAMETER
;
172 if (!sock
->ops
->fn_accept
) {
173 return NT_STATUS_NOT_IMPLEMENTED
;
176 status
= sock
->ops
->fn_accept(sock
, new_sock
);
178 if (NT_STATUS_IS_OK(status
)) {
179 talloc_set_destructor(*new_sock
, socket_destructor
);
180 (*new_sock
)->flags
= 0;
186 _PUBLIC_ NTSTATUS
socket_recv(struct socket_context
*sock
, void *buf
,
187 size_t wantlen
, size_t *nread
)
190 return NT_STATUS_CONNECTION_DISCONNECTED
;
192 if (sock
->state
!= SOCKET_STATE_CLIENT_CONNECTED
&&
193 sock
->state
!= SOCKET_STATE_SERVER_CONNECTED
&&
194 sock
->type
!= SOCKET_TYPE_DGRAM
) {
195 return NT_STATUS_INVALID_PARAMETER
;
198 if (!sock
->ops
->fn_recv
) {
199 return NT_STATUS_NOT_IMPLEMENTED
;
202 if ((sock
->flags
& SOCKET_FLAG_TESTNONBLOCK
)
205 if (random() % 10 == 0) {
207 return STATUS_MORE_ENTRIES
;
209 return sock
->ops
->fn_recv(sock
, buf
, 1+(random() % wantlen
), nread
);
211 return sock
->ops
->fn_recv(sock
, buf
, wantlen
, nread
);
214 _PUBLIC_ NTSTATUS
socket_recvfrom(struct socket_context
*sock
, void *buf
,
215 size_t wantlen
, size_t *nread
,
216 TALLOC_CTX
*mem_ctx
, struct socket_address
**src_addr
)
219 return NT_STATUS_CONNECTION_DISCONNECTED
;
221 if (sock
->type
!= SOCKET_TYPE_DGRAM
) {
222 return NT_STATUS_INVALID_PARAMETER
;
225 if (!sock
->ops
->fn_recvfrom
) {
226 return NT_STATUS_NOT_IMPLEMENTED
;
229 return sock
->ops
->fn_recvfrom(sock
, buf
, wantlen
, nread
,
233 _PUBLIC_ NTSTATUS
socket_send(struct socket_context
*sock
,
234 const DATA_BLOB
*blob
, size_t *sendlen
)
237 return NT_STATUS_CONNECTION_DISCONNECTED
;
239 if (sock
->state
!= SOCKET_STATE_CLIENT_CONNECTED
&&
240 sock
->state
!= SOCKET_STATE_SERVER_CONNECTED
) {
241 return NT_STATUS_INVALID_PARAMETER
;
244 if (!sock
->ops
->fn_send
) {
245 return NT_STATUS_NOT_IMPLEMENTED
;
248 if ((sock
->flags
& SOCKET_FLAG_TESTNONBLOCK
)
249 && blob
->length
> 1) {
250 DATA_BLOB blob2
= *blob
;
251 if (random() % 10 == 0) {
253 return STATUS_MORE_ENTRIES
;
255 /* The random size sends are incompatible with TLS and SASL
256 * sockets, which require re-sends to be consistant */
257 if (!(sock
->flags
& SOCKET_FLAG_ENCRYPT
)) {
258 blob2
.length
= 1+(random() % blob2
.length
);
260 /* This is particularly stressful on buggy
261 * LDAP clients, that don't expect on LDAP
262 * packet in many SASL packets */
263 blob2
.length
= 1 + blob2
.length
/2;
265 return sock
->ops
->fn_send(sock
, &blob2
, sendlen
);
267 return sock
->ops
->fn_send(sock
, blob
, sendlen
);
271 _PUBLIC_ NTSTATUS
socket_sendto(struct socket_context
*sock
,
272 const DATA_BLOB
*blob
, size_t *sendlen
,
273 const struct socket_address
*dest_addr
)
276 return NT_STATUS_CONNECTION_DISCONNECTED
;
278 if (sock
->type
!= SOCKET_TYPE_DGRAM
) {
279 return NT_STATUS_INVALID_PARAMETER
;
282 if (sock
->state
== SOCKET_STATE_CLIENT_CONNECTED
||
283 sock
->state
== SOCKET_STATE_SERVER_CONNECTED
) {
284 return NT_STATUS_INVALID_PARAMETER
;
287 if (!sock
->ops
->fn_sendto
) {
288 return NT_STATUS_NOT_IMPLEMENTED
;
291 return sock
->ops
->fn_sendto(sock
, blob
, sendlen
, dest_addr
);
296 ask for the number of bytes in a pending incoming packet
298 _PUBLIC_ NTSTATUS
socket_pending(struct socket_context
*sock
, size_t *npending
)
301 return NT_STATUS_CONNECTION_DISCONNECTED
;
303 if (!sock
->ops
->fn_pending
) {
304 return NT_STATUS_NOT_IMPLEMENTED
;
306 return sock
->ops
->fn_pending(sock
, npending
);
310 _PUBLIC_ NTSTATUS
socket_set_option(struct socket_context
*sock
, const char *option
, const char *val
)
313 return NT_STATUS_CONNECTION_DISCONNECTED
;
315 if (!sock
->ops
->fn_set_option
) {
316 return NT_STATUS_NOT_IMPLEMENTED
;
319 return sock
->ops
->fn_set_option(sock
, option
, val
);
322 _PUBLIC_
char *socket_get_peer_name(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
324 if (!sock
->ops
->fn_get_peer_name
) {
328 return sock
->ops
->fn_get_peer_name(sock
, mem_ctx
);
331 _PUBLIC_
struct socket_address
*socket_get_peer_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
333 if (!sock
->ops
->fn_get_peer_addr
) {
337 return sock
->ops
->fn_get_peer_addr(sock
, mem_ctx
);
340 _PUBLIC_
struct socket_address
*socket_get_my_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
342 if (!sock
->ops
->fn_get_my_addr
) {
346 return sock
->ops
->fn_get_my_addr(sock
, mem_ctx
);
349 _PUBLIC_
struct tsocket_address
*socket_address_to_tsocket_address(TALLOC_CTX
*mem_ctx
,
350 const struct socket_address
*a
)
352 struct tsocket_address
*r
;
356 ret
= tsocket_address_bsd_from_sockaddr(mem_ctx
,
361 ret
= tsocket_address_inet_from_strings(mem_ctx
,
375 _PUBLIC_
void socket_address_set_port(struct socket_address
*a
,
379 set_sockaddr_port(a
->sockaddr
, port
);
386 _PUBLIC_
struct socket_address
*tsocket_address_to_socket_address(TALLOC_CTX
*mem_ctx
,
387 const struct tsocket_address
*a
)
390 struct sockaddr_storage ss
;
391 size_t sslen
= sizeof(ss
);
393 ret
= tsocket_address_bsd_sockaddr(a
, (struct sockaddr
*)(void *)&ss
, sslen
);
398 return socket_address_from_sockaddr(mem_ctx
, (struct sockaddr
*)(void *)&ss
, ret
);
401 _PUBLIC_
struct tsocket_address
*socket_get_remote_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
403 struct socket_address
*a
;
404 struct tsocket_address
*r
;
406 a
= socket_get_peer_addr(sock
, mem_ctx
);
411 r
= socket_address_to_tsocket_address(mem_ctx
, a
);
416 _PUBLIC_
struct tsocket_address
*socket_get_local_addr(struct socket_context
*sock
, TALLOC_CTX
*mem_ctx
)
418 struct socket_address
*a
;
419 struct tsocket_address
*r
;
421 a
= socket_get_my_addr(sock
, mem_ctx
);
426 r
= socket_address_to_tsocket_address(mem_ctx
, a
);
431 _PUBLIC_
int socket_get_fd(struct socket_context
*sock
)
433 if (!sock
->ops
->fn_get_fd
) {
437 return sock
->ops
->fn_get_fd(sock
);
441 call dup() on a socket, and close the old fd. This is used to change
442 the fd to the lowest available number, to make select() more
443 efficient (select speed depends on the maxiumum fd number passed to
446 _PUBLIC_ NTSTATUS
socket_dup(struct socket_context
*sock
)
449 if (sock
->fd
== -1) {
450 return NT_STATUS_INVALID_HANDLE
;
454 return map_nt_error_from_unix(errno
);
462 /* Create a new socket_address. The type must match the socket type.
463 * The host parameter may be an IP or a hostname
466 _PUBLIC_
struct socket_address
*socket_address_from_strings(TALLOC_CTX
*mem_ctx
,
471 struct socket_address
*addr
= talloc(mem_ctx
, struct socket_address
);
476 addr
->family
= family
;
477 addr
->addr
= talloc_strdup(addr
, host
);
483 addr
->sockaddr
= NULL
;
484 addr
->sockaddrlen
= 0;
489 /* Create a new socket_address. Copy the struct sockaddr into the new
490 * structure. Used for hooks in the kerberos libraries, where they
491 * supply only a struct sockaddr */
493 _PUBLIC_
struct socket_address
*socket_address_from_sockaddr(TALLOC_CTX
*mem_ctx
,
494 struct sockaddr
*sockaddr
,
497 struct socket_address
*addr
= talloc(mem_ctx
, struct socket_address
);
504 addr
->sockaddr
= (struct sockaddr
*)talloc_memdup(addr
, sockaddr
, sockaddrlen
);
505 if (!addr
->sockaddr
) {
509 addr
->sockaddrlen
= sockaddrlen
;
513 /* Copy a socket_address structure */
514 struct socket_address
*socket_address_copy(TALLOC_CTX
*mem_ctx
,
515 const struct socket_address
*oaddr
)
517 struct socket_address
*addr
= talloc_zero(mem_ctx
, struct socket_address
);
521 addr
->family
= oaddr
->family
;
523 addr
->addr
= talloc_strdup(addr
, oaddr
->addr
);
528 addr
->port
= oaddr
->port
;
529 if (oaddr
->sockaddr
) {
530 addr
->sockaddr
= (struct sockaddr
*)talloc_memdup(addr
,
533 if (!addr
->sockaddr
) {
536 addr
->sockaddrlen
= oaddr
->sockaddrlen
;
546 _PUBLIC_
const struct socket_ops
*socket_getops_byname(const char *family
, enum socket_type type
)
548 extern const struct socket_ops
*socket_ipv4_ops(enum socket_type
);
549 extern const struct socket_ops
*socket_ipv6_ops(enum socket_type
);
550 extern const struct socket_ops
*socket_unixdom_ops(enum socket_type
);
552 if (strcmp("ip", family
) == 0 ||
553 strcmp("ipv4", family
) == 0) {
554 return socket_ipv4_ops(type
);
558 if (strcmp("ipv6", family
) == 0) {
559 return socket_ipv6_ops(type
);
563 if (strcmp("unix", family
) == 0) {
564 return socket_unixdom_ops(type
);
570 enum SOCK_OPT_TYPES
{OPT_BOOL
,OPT_INT
,OPT_ON
};
572 static const struct {
578 } socket_options
[] = {
579 {"SO_KEEPALIVE", SOL_SOCKET
, SO_KEEPALIVE
, 0, OPT_BOOL
},
580 {"SO_REUSEADDR", SOL_SOCKET
, SO_REUSEADDR
, 0, OPT_BOOL
},
581 {"SO_BROADCAST", SOL_SOCKET
, SO_BROADCAST
, 0, OPT_BOOL
},
583 {"TCP_NODELAY", IPPROTO_TCP
, TCP_NODELAY
, 0, OPT_BOOL
},
585 #ifdef IPTOS_LOWDELAY
586 {"IPTOS_LOWDELAY", IPPROTO_IP
, IP_TOS
, IPTOS_LOWDELAY
, OPT_ON
},
588 #ifdef IPTOS_THROUGHPUT
589 {"IPTOS_THROUGHPUT", IPPROTO_IP
, IP_TOS
, IPTOS_THROUGHPUT
, OPT_ON
},
592 {"SO_REUSEPORT", SOL_SOCKET
, SO_REUSEPORT
, 0, OPT_BOOL
},
595 {"SO_SNDBUF", SOL_SOCKET
, SO_SNDBUF
, 0, OPT_INT
},
598 {"SO_RCVBUF", SOL_SOCKET
, SO_RCVBUF
, 0, OPT_INT
},
601 {"SO_SNDLOWAT", SOL_SOCKET
, SO_SNDLOWAT
, 0, OPT_INT
},
604 {"SO_RCVLOWAT", SOL_SOCKET
, SO_RCVLOWAT
, 0, OPT_INT
},
607 {"SO_SNDTIMEO", SOL_SOCKET
, SO_SNDTIMEO
, 0, OPT_INT
},
610 {"SO_RCVTIMEO", SOL_SOCKET
, SO_RCVTIMEO
, 0, OPT_INT
},
616 Set user socket options.
618 _PUBLIC_
void set_socket_options(int fd
, const char *options
)
620 const char **options_list
= (const char **)str_list_make(NULL
, options
, " \t,");
626 for (j
= 0; options_list
[j
]; j
++) {
627 const char *tok
= options_list
[j
];
631 bool got_value
= false;
633 if ((p
= strchr(tok
,'='))) {
639 for (i
=0;socket_options
[i
].name
;i
++)
640 if (strequal(socket_options
[i
].name
,tok
))
643 if (!socket_options
[i
].name
) {
644 DEBUG(0,("Unknown socket option %s\n",tok
));
648 switch (socket_options
[i
].opttype
) {
651 ret
= setsockopt(fd
,socket_options
[i
].level
,
652 socket_options
[i
].option
,(char *)&value
,sizeof(int));
657 DEBUG(0,("syntax error - %s does not take a value\n",tok
));
660 int on
= socket_options
[i
].value
;
661 ret
= setsockopt(fd
,socket_options
[i
].level
,
662 socket_options
[i
].option
,(char *)&on
,sizeof(int));
668 DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok
, strerror(errno
) ));
671 talloc_free(options_list
);
675 set some flags on a socket
677 void socket_set_flags(struct socket_context
*sock
, unsigned flags
)
679 sock
->flags
|= flags
;