Refactoring BIO: new socket-handling functions, deprecate older ones
[openssl.git] / crypto / bio / b_sock2.c
1 /* ====================================================================
2  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This product includes cryptographic software written by Eric Young
50  * (eay@cryptsoft.com).  This product includes software written by Tim
51  * Hudson (tjh@cryptsoft.com).
52  *
53  */
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <errno.h>
58
59 #include "bio_lcl.h"
60
61 #include <openssl/err.h>
62
63 #ifndef OPENSSL_NO_SOCK
64 # ifdef SO_MAXCONN
65 #  define MAX_LISTEN  SO_MAXCONN
66 # elif defined(SOMAXCONN)
67 #  define MAX_LISTEN  SOMAXCONN
68 # else
69 #  define MAX_LISTEN  32
70 # endif
71
72 /*-
73  * BIO_socket - create a socket
74  * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
75  * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
76  * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
77  * @options: BIO socket options (currently unused)
78  *
79  * Creates a socket.  This should be called before calling any
80  * of BIO_connect and BIO_listen.
81  *
82  * Returns the file descriptor on success or INVALID_SOCKET on failure.  On
83  * failure errno is set, and a status is added to the OpenSSL error stack.
84  */
85 int BIO_socket(int domain, int socktype, int protocol, int options)
86 {
87     int sock = -1;
88
89     if (BIO_sock_init() != 1)
90         return INVALID_SOCKET;
91
92     sock = socket(domain, socktype, protocol);
93     if (sock == -1) {
94         SYSerr(SYS_F_SOCKET, get_last_socket_error());
95         BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
96         return INVALID_SOCKET;
97     }
98
99     return sock;
100 }
101
102 /*-
103  * BIO_connect - connect to an address
104  * @sock: the socket to connect with
105  * @addr: the address to connect to
106  * @options: BIO socket options
107  *
108  * Connects to the address using the given socket and options.
109  *
110  * Options can be a combination of the following:
111  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
112  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
113  * - BIO_SOCK_NODELAY: don't delay small messages.
114  *
115  * options holds BIO socket options that can be used
116  * You should call this for every address returned by BIO_lookup
117  * until the connection is succesful.
118  *
119  * Returns 1 on success or 0 on failure.  On failure errno is set
120  * and an error status is added to the OpenSSL error stack.
121  */
122 int BIO_connect(int sock, const BIO_ADDR *addr, int options)
123 {
124     int on = 1;
125
126     if (sock == -1) {
127         BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
128         return 0;
129     }
130
131     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
132         return 0;
133
134     if (options & BIO_SOCK_KEEPALIVE) {
135         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) != 0) {
136             SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
137             BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
138             return 0;
139         }
140     }
141
142     if (options & BIO_SOCK_NODELAY) {
143         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) != 0) {
144             SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
145             BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
146             return 0;
147         }
148     }
149
150     if (connect(sock, BIO_ADDR_sockaddr(addr),
151                 BIO_ADDR_sockaddr_size(addr)) == -1) {
152         SYSerr(SYS_F_CONNECT, get_last_socket_error());
153         BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
154         return 0;
155     }
156     return 1;
157 }
158
159 /*-
160  * BIO_listen - Creates a listen socket
161  * @sock: the socket to listen with
162  * @addr: local address to bind to
163  * @options: BIO socket options
164  *
165  * Binds to the address using the given socket and options, then
166  * starts listening for incoming connections.
167  *
168  * Options can be a combination of the following:
169  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
170  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
171  * - BIO_SOCK_NODELAY: don't delay small messages.
172  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
173  *   for a recently closed port.
174  * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
175  *   for IPv6 addresses and not IPv4 addresses mapped to IPv6.
176  *
177  * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
178  * then check both for new clients that connect to it.  You want to set up
179  * the socket as non-blocking in that case since else it could hang.
180  *
181  * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
182  * others it's an option.  If you pass the BIO_LISTEN_V6_ONLY it will try to
183  * create the IPv6 sockets to only listen for IPv6 connection.
184  *
185  * It could be that the first BIO_listen() call will listen to all the IPv6
186  * and IPv4 addresses and that then trying to bind to the IPv4 address will
187  * fail.  We can't tell the difference between already listening ourself to
188  * it and someone else listening to it when failing and errno is EADDRINUSE, so
189  * it's recommended to not give an error in that case if the first call was
190  * succesful.
191  *
192  * When restarting the program it could be that the port is still in use.  If
193  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
194  * It's recommended that you use this.
195  */
196 int BIO_listen(int sock, const BIO_ADDR *addr, int options)
197 {
198     int on = 1;
199     int socktype;
200     socklen_t socktype_len = sizeof(socktype);
201
202     if (sock == -1) {
203         BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
204         return 0;
205     }
206
207     if (getsockopt(sock, SOL_SOCKET, SO_TYPE, &socktype, &socktype_len) != 0
208         || socktype_len != sizeof(socktype)) {
209         SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
210         BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
211         return 0;
212     }
213
214     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
215         return 0;
216
217 # ifndef OPENSSL_SYS_WINDOWS
218     /* SO_REUSEADDR has different behavior on Windows than on
219      * other operating systems, don't set it there. */
220     if (options & BIO_SOCK_REUSEADDR) {
221         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
222             SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
223             BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_REUSEADDR);
224             return 0;
225         }
226     }
227 # endif
228
229     if (options & BIO_SOCK_KEEPALIVE) {
230         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) != 0) {
231             SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
232             BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE);
233             return 0;
234         }
235     }
236
237     if (options & BIO_SOCK_NODELAY) {
238         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) != 0) {
239             SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
240             BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY);
241             return 0;
242         }
243     }
244
245 # ifdef IPV6_V6ONLY
246     if ((options & BIO_SOCK_V6_ONLY) && BIO_ADDR_family(addr) == AF_INET6) {
247         if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) != 0) {
248             SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
249             BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY);
250             return 0;
251         }
252     }
253 # endif
254
255     if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
256         SYSerr(SYS_F_BIND, get_last_socket_error());
257         BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_BIND_SOCKET);
258         return 0;
259     }
260
261     if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
262         SYSerr(SYS_F_LISTEN, get_last_socket_error());
263         BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET);
264         return 0;
265     }
266
267     return 1;
268 }
269
270 /*-
271  * BIO_accept_ex - Accept new incoming connections
272  * @sock: the listening socket
273  * @addr: the BIO_ADDR to store the peer address in
274  * @options: BIO socket options, applied on the accepted socket.
275  *
276  */
277 int BIO_accept_ex(int accept_sock, BIO_ADDR *addr, int options)
278 {
279     socklen_t len;
280     int accepted_sock;
281
282     len = sizeof(*addr);
283     accepted_sock = accept(accept_sock,
284                            BIO_ADDR_sockaddr_noconst(addr), &len);
285     if (accepted_sock == -1) {
286         SYSerr(SYS_F_ACCEPT, get_last_socket_error());
287         BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
288         return INVALID_SOCKET;
289     }
290
291     if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0))
292         return INVALID_SOCKET;
293
294     return accepted_sock;
295 }
296
297 /*-
298  * BIO_closesocket - Close a socket
299  * @sock: the socket to close
300  */
301 int BIO_closesocket(int sock)
302 {
303     if (closesocket(sock) < 0)
304         return 0;
305     return 1;
306 }
307 #endif