]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/bio/b_sock2.c
Fix invalid function type casts.
[thirdparty/openssl.git] / crypto / bio / b_sock2.c
CommitLineData
b1322259
RS
1/*
2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
d33b215b 3 *
b1322259
RS
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
d33b215b
RL
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <errno.h>
13
14#include "bio_lcl.h"
15
16#include <openssl/err.h>
17
18#ifndef OPENSSL_NO_SOCK
19# ifdef SO_MAXCONN
20# define MAX_LISTEN SO_MAXCONN
21# elif defined(SOMAXCONN)
22# define MAX_LISTEN SOMAXCONN
23# else
24# define MAX_LISTEN 32
25# endif
26
27/*-
28 * BIO_socket - create a socket
29 * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
30 * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
31 * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
32 * @options: BIO socket options (currently unused)
33 *
34 * Creates a socket. This should be called before calling any
35 * of BIO_connect and BIO_listen.
36 *
37 * Returns the file descriptor on success or INVALID_SOCKET on failure. On
38 * failure errno is set, and a status is added to the OpenSSL error stack.
39 */
40int BIO_socket(int domain, int socktype, int protocol, int options)
41{
42 int sock = -1;
43
44 if (BIO_sock_init() != 1)
45 return INVALID_SOCKET;
46
47 sock = socket(domain, socktype, protocol);
48 if (sock == -1) {
49 SYSerr(SYS_F_SOCKET, get_last_socket_error());
50 BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
51 return INVALID_SOCKET;
52 }
53
54 return sock;
55}
56
57/*-
58 * BIO_connect - connect to an address
59 * @sock: the socket to connect with
60 * @addr: the address to connect to
61 * @options: BIO socket options
62 *
63 * Connects to the address using the given socket and options.
64 *
65 * Options can be a combination of the following:
66 * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
67 * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
68 * - BIO_SOCK_NODELAY: don't delay small messages.
69 *
70 * options holds BIO socket options that can be used
71 * You should call this for every address returned by BIO_lookup
60250017 72 * until the connection is successful.
d33b215b
RL
73 *
74 * Returns 1 on success or 0 on failure. On failure errno is set
75 * and an error status is added to the OpenSSL error stack.
76 */
77int BIO_connect(int sock, const BIO_ADDR *addr, int options)
78{
3a63c0ed 79 const int on = 1;
d33b215b
RL
80
81 if (sock == -1) {
82 BIOerr(BIO_F_BIO_CONNECT, BIO_R_INVALID_SOCKET);
83 return 0;
84 }
85
86 if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
87 return 0;
88
89 if (options & BIO_SOCK_KEEPALIVE) {
3a63c0ed
AP
90 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
91 (const void *)&on, sizeof(on)) != 0) {
d33b215b
RL
92 SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
93 BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_KEEPALIVE);
94 return 0;
95 }
96 }
97
98 if (options & BIO_SOCK_NODELAY) {
3a63c0ed
AP
99 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
100 (const void *)&on, sizeof(on)) != 0) {
d33b215b
RL
101 SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
102 BIOerr(BIO_F_BIO_CONNECT, BIO_R_UNABLE_TO_NODELAY);
103 return 0;
104 }
105 }
106
107 if (connect(sock, BIO_ADDR_sockaddr(addr),
108 BIO_ADDR_sockaddr_size(addr)) == -1) {
81161070
MC
109 if (!BIO_sock_should_retry(-1)) {
110 SYSerr(SYS_F_CONNECT, get_last_socket_error());
111 BIOerr(BIO_F_BIO_CONNECT, BIO_R_CONNECT_ERROR);
112 }
d33b215b
RL
113 return 0;
114 }
115 return 1;
116}
117
118/*-
119 * BIO_listen - Creates a listen socket
120 * @sock: the socket to listen with
121 * @addr: local address to bind to
122 * @options: BIO socket options
123 *
124 * Binds to the address using the given socket and options, then
125 * starts listening for incoming connections.
126 *
127 * Options can be a combination of the following:
128 * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
129 * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
130 * - BIO_SOCK_NODELAY: don't delay small messages.
131 * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
132 * for a recently closed port.
133 * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
134 * for IPv6 addresses and not IPv4 addresses mapped to IPv6.
135 *
136 * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
137 * then check both for new clients that connect to it. You want to set up
138 * the socket as non-blocking in that case since else it could hang.
139 *
140 * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
141 * others it's an option. If you pass the BIO_LISTEN_V6_ONLY it will try to
142 * create the IPv6 sockets to only listen for IPv6 connection.
143 *
144 * It could be that the first BIO_listen() call will listen to all the IPv6
145 * and IPv4 addresses and that then trying to bind to the IPv4 address will
146 * fail. We can't tell the difference between already listening ourself to
147 * it and someone else listening to it when failing and errno is EADDRINUSE, so
148 * it's recommended to not give an error in that case if the first call was
60250017 149 * successful.
d33b215b
RL
150 *
151 * When restarting the program it could be that the port is still in use. If
152 * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
153 * It's recommended that you use this.
154 */
155int BIO_listen(int sock, const BIO_ADDR *addr, int options)
156{
157 int on = 1;
158 int socktype;
159 socklen_t socktype_len = sizeof(socktype);
160
161 if (sock == -1) {
162 BIOerr(BIO_F_BIO_LISTEN, BIO_R_INVALID_SOCKET);
163 return 0;
164 }
165
3a63c0ed
AP
166 if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
167 (void *)&socktype, &socktype_len) != 0
d33b215b
RL
168 || socktype_len != sizeof(socktype)) {
169 SYSerr(SYS_F_GETSOCKOPT, get_last_socket_error());
170 BIOerr(BIO_F_BIO_LISTEN, BIO_R_GETTING_SOCKTYPE);
171 return 0;
172 }
173
174 if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
175 return 0;
176
177# ifndef OPENSSL_SYS_WINDOWS
178 /* SO_REUSEADDR has different behavior on Windows than on
179 * other operating systems, don't set it there. */
180 if (options & BIO_SOCK_REUSEADDR) {
3a63c0ed
AP
181 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
182 (const void *)&on, sizeof(on)) != 0) {
d33b215b
RL
183 SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
184 BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_REUSEADDR);
185 return 0;
186 }
187 }
188# endif
189
190 if (options & BIO_SOCK_KEEPALIVE) {
3a63c0ed
AP
191 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
192 (const void *)&on, sizeof(on)) != 0) {
d33b215b
RL
193 SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
194 BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_KEEPALIVE);
195 return 0;
196 }
197 }
198
199 if (options & BIO_SOCK_NODELAY) {
3a63c0ed
AP
200 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
201 (const void *)&on, sizeof(on)) != 0) {
d33b215b
RL
202 SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
203 BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_NODELAY);
204 return 0;
205 }
206 }
207
208# ifdef IPV6_V6ONLY
209 if ((options & BIO_SOCK_V6_ONLY) && BIO_ADDR_family(addr) == AF_INET6) {
3a63c0ed
AP
210 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
211 (const void *)&on, sizeof(on)) != 0) {
d33b215b
RL
212 SYSerr(SYS_F_SETSOCKOPT, get_last_socket_error());
213 BIOerr(BIO_F_BIO_LISTEN, BIO_R_LISTEN_V6_ONLY);
214 return 0;
215 }
216 }
217# endif
218
219 if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
220 SYSerr(SYS_F_BIND, get_last_socket_error());
221 BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_BIND_SOCKET);
222 return 0;
223 }
224
225 if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
226 SYSerr(SYS_F_LISTEN, get_last_socket_error());
227 BIOerr(BIO_F_BIO_LISTEN, BIO_R_UNABLE_TO_LISTEN_SOCKET);
228 return 0;
229 }
230
231 return 1;
232}
233
234/*-
235 * BIO_accept_ex - Accept new incoming connections
236 * @sock: the listening socket
237 * @addr: the BIO_ADDR to store the peer address in
238 * @options: BIO socket options, applied on the accepted socket.
239 *
240 */
d9d8e7a9 241int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
d33b215b
RL
242{
243 socklen_t len;
244 int accepted_sock;
d9d8e7a9
RS
245 BIO_ADDR locaddr;
246 BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
d33b215b
RL
247
248 len = sizeof(*addr);
249 accepted_sock = accept(accept_sock,
250 BIO_ADDR_sockaddr_noconst(addr), &len);
251 if (accepted_sock == -1) {
81161070
MC
252 if (!BIO_sock_should_retry(accepted_sock)) {
253 SYSerr(SYS_F_ACCEPT, get_last_socket_error());
254 BIOerr(BIO_F_BIO_ACCEPT_EX, BIO_R_ACCEPT_ERROR);
255 }
d33b215b
RL
256 return INVALID_SOCKET;
257 }
258
df0f2759
MC
259 if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
260 closesocket(accepted_sock);
d33b215b 261 return INVALID_SOCKET;
df0f2759 262 }
d33b215b
RL
263
264 return accepted_sock;
265}
266
267/*-
268 * BIO_closesocket - Close a socket
269 * @sock: the socket to close
270 */
271int BIO_closesocket(int sock)
272{
273 if (closesocket(sock) < 0)
274 return 0;
275 return 1;
276}
277#endif