xref: /freebsd/crypto/openssl/crypto/bio/bio_sock2.c (revision b077aed3)
1*b077aed3SPierre Pronchery /*
2*b077aed3SPierre Pronchery  * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3*b077aed3SPierre Pronchery  *
4*b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7*b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8*b077aed3SPierre Pronchery  */
9*b077aed3SPierre Pronchery 
10*b077aed3SPierre Pronchery #include <stdio.h>
11*b077aed3SPierre Pronchery #include <stdlib.h>
12*b077aed3SPierre Pronchery #include <errno.h>
13*b077aed3SPierre Pronchery 
14*b077aed3SPierre Pronchery #include "bio_local.h"
15*b077aed3SPierre Pronchery #include "internal/ktls.h"
16*b077aed3SPierre Pronchery 
17*b077aed3SPierre Pronchery #include <openssl/err.h>
18*b077aed3SPierre Pronchery 
19*b077aed3SPierre Pronchery #ifndef OPENSSL_NO_SOCK
20*b077aed3SPierre Pronchery # ifdef SO_MAXCONN
21*b077aed3SPierre Pronchery #  define MAX_LISTEN  SO_MAXCONN
22*b077aed3SPierre Pronchery # elif defined(SOMAXCONN)
23*b077aed3SPierre Pronchery #  define MAX_LISTEN  SOMAXCONN
24*b077aed3SPierre Pronchery # else
25*b077aed3SPierre Pronchery #  define MAX_LISTEN  32
26*b077aed3SPierre Pronchery # endif
27*b077aed3SPierre Pronchery 
28*b077aed3SPierre Pronchery /*-
29*b077aed3SPierre Pronchery  * BIO_socket - create a socket
30*b077aed3SPierre Pronchery  * @domain: the socket domain (AF_INET, AF_INET6, AF_UNIX, ...)
31*b077aed3SPierre Pronchery  * @socktype: the socket type (SOCK_STEAM, SOCK_DGRAM)
32*b077aed3SPierre Pronchery  * @protocol: the protocol to use (IPPROTO_TCP, IPPROTO_UDP)
33*b077aed3SPierre Pronchery  * @options: BIO socket options (currently unused)
34*b077aed3SPierre Pronchery  *
35*b077aed3SPierre Pronchery  * Creates a socket.  This should be called before calling any
36*b077aed3SPierre Pronchery  * of BIO_connect and BIO_listen.
37*b077aed3SPierre Pronchery  *
38*b077aed3SPierre Pronchery  * Returns the file descriptor on success or INVALID_SOCKET on failure.  On
39*b077aed3SPierre Pronchery  * failure errno is set, and a status is added to the OpenSSL error stack.
40*b077aed3SPierre Pronchery  */
BIO_socket(int domain,int socktype,int protocol,int options)41*b077aed3SPierre Pronchery int BIO_socket(int domain, int socktype, int protocol, int options)
42*b077aed3SPierre Pronchery {
43*b077aed3SPierre Pronchery     int sock = -1;
44*b077aed3SPierre Pronchery 
45*b077aed3SPierre Pronchery     if (BIO_sock_init() != 1)
46*b077aed3SPierre Pronchery         return INVALID_SOCKET;
47*b077aed3SPierre Pronchery 
48*b077aed3SPierre Pronchery     sock = socket(domain, socktype, protocol);
49*b077aed3SPierre Pronchery     if (sock == -1) {
50*b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
51*b077aed3SPierre Pronchery                        "calling socket()");
52*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_CREATE_SOCKET);
53*b077aed3SPierre Pronchery         return INVALID_SOCKET;
54*b077aed3SPierre Pronchery     }
55*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_KTLS
56*b077aed3SPierre Pronchery     {
57*b077aed3SPierre Pronchery         /*
58*b077aed3SPierre Pronchery          * The new socket is created successfully regardless of ktls_enable.
59*b077aed3SPierre Pronchery          * ktls_enable doesn't change any functionality of the socket, except
60*b077aed3SPierre Pronchery          * changing the setsockopt to enable the processing of ktls_start.
61*b077aed3SPierre Pronchery          * Thus, it is not a problem to call it for non-TLS sockets.
62*b077aed3SPierre Pronchery          */
63*b077aed3SPierre Pronchery         ktls_enable(sock);
64*b077aed3SPierre Pronchery     }
65*b077aed3SPierre Pronchery # endif
66*b077aed3SPierre Pronchery 
67*b077aed3SPierre Pronchery     return sock;
68*b077aed3SPierre Pronchery }
69*b077aed3SPierre Pronchery 
70*b077aed3SPierre Pronchery /*-
71*b077aed3SPierre Pronchery  * BIO_connect - connect to an address
72*b077aed3SPierre Pronchery  * @sock: the socket to connect with
73*b077aed3SPierre Pronchery  * @addr: the address to connect to
74*b077aed3SPierre Pronchery  * @options: BIO socket options
75*b077aed3SPierre Pronchery  *
76*b077aed3SPierre Pronchery  * Connects to the address using the given socket and options.
77*b077aed3SPierre Pronchery  *
78*b077aed3SPierre Pronchery  * Options can be a combination of the following:
79*b077aed3SPierre Pronchery  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
80*b077aed3SPierre Pronchery  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
81*b077aed3SPierre Pronchery  * - BIO_SOCK_NODELAY: don't delay small messages.
82*b077aed3SPierre Pronchery  *
83*b077aed3SPierre Pronchery  * options holds BIO socket options that can be used
84*b077aed3SPierre Pronchery  * You should call this for every address returned by BIO_lookup
85*b077aed3SPierre Pronchery  * until the connection is successful.
86*b077aed3SPierre Pronchery  *
87*b077aed3SPierre Pronchery  * Returns 1 on success or 0 on failure.  On failure errno is set
88*b077aed3SPierre Pronchery  * and an error status is added to the OpenSSL error stack.
89*b077aed3SPierre Pronchery  */
BIO_connect(int sock,const BIO_ADDR * addr,int options)90*b077aed3SPierre Pronchery int BIO_connect(int sock, const BIO_ADDR *addr, int options)
91*b077aed3SPierre Pronchery {
92*b077aed3SPierre Pronchery     const int on = 1;
93*b077aed3SPierre Pronchery 
94*b077aed3SPierre Pronchery     if (sock == -1) {
95*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
96*b077aed3SPierre Pronchery         return 0;
97*b077aed3SPierre Pronchery     }
98*b077aed3SPierre Pronchery 
99*b077aed3SPierre Pronchery     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
100*b077aed3SPierre Pronchery         return 0;
101*b077aed3SPierre Pronchery 
102*b077aed3SPierre Pronchery     if (options & BIO_SOCK_KEEPALIVE) {
103*b077aed3SPierre Pronchery         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
104*b077aed3SPierre Pronchery                        (const void *)&on, sizeof(on)) != 0) {
105*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
106*b077aed3SPierre Pronchery                            "calling setsockopt()");
107*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
108*b077aed3SPierre Pronchery             return 0;
109*b077aed3SPierre Pronchery         }
110*b077aed3SPierre Pronchery     }
111*b077aed3SPierre Pronchery 
112*b077aed3SPierre Pronchery     if (options & BIO_SOCK_NODELAY) {
113*b077aed3SPierre Pronchery         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
114*b077aed3SPierre Pronchery                        (const void *)&on, sizeof(on)) != 0) {
115*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
116*b077aed3SPierre Pronchery                            "calling setsockopt()");
117*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
118*b077aed3SPierre Pronchery             return 0;
119*b077aed3SPierre Pronchery         }
120*b077aed3SPierre Pronchery     }
121*b077aed3SPierre Pronchery 
122*b077aed3SPierre Pronchery     if (connect(sock, BIO_ADDR_sockaddr(addr),
123*b077aed3SPierre Pronchery                 BIO_ADDR_sockaddr_size(addr)) == -1) {
124*b077aed3SPierre Pronchery         if (!BIO_sock_should_retry(-1)) {
125*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
126*b077aed3SPierre Pronchery                            "calling connect()");
127*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_CONNECT_ERROR);
128*b077aed3SPierre Pronchery         }
129*b077aed3SPierre Pronchery         return 0;
130*b077aed3SPierre Pronchery     }
131*b077aed3SPierre Pronchery # ifndef OPENSSL_NO_KTLS
132*b077aed3SPierre Pronchery     /*
133*b077aed3SPierre Pronchery      * The new socket is created successfully regardless of ktls_enable.
134*b077aed3SPierre Pronchery      * ktls_enable doesn't change any functionality of the socket, except
135*b077aed3SPierre Pronchery      * changing the setsockopt to enable the processing of ktls_start.
136*b077aed3SPierre Pronchery      * Thus, it is not a problem to call it for non-TLS sockets.
137*b077aed3SPierre Pronchery      */
138*b077aed3SPierre Pronchery     ktls_enable(sock);
139*b077aed3SPierre Pronchery # endif
140*b077aed3SPierre Pronchery     return 1;
141*b077aed3SPierre Pronchery }
142*b077aed3SPierre Pronchery 
143*b077aed3SPierre Pronchery /*-
144*b077aed3SPierre Pronchery  * BIO_bind - bind socket to address
145*b077aed3SPierre Pronchery  * @sock: the socket to set
146*b077aed3SPierre Pronchery  * @addr: local address to bind to
147*b077aed3SPierre Pronchery  * @options: BIO socket options
148*b077aed3SPierre Pronchery  *
149*b077aed3SPierre Pronchery  * Binds to the address using the given socket and options.
150*b077aed3SPierre Pronchery  *
151*b077aed3SPierre Pronchery  * Options can be a combination of the following:
152*b077aed3SPierre Pronchery  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
153*b077aed3SPierre Pronchery  *   for a recently closed port.
154*b077aed3SPierre Pronchery  *
155*b077aed3SPierre Pronchery  * When restarting the program it could be that the port is still in use.  If
156*b077aed3SPierre Pronchery  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
157*b077aed3SPierre Pronchery  * It's recommended that you use this.
158*b077aed3SPierre Pronchery  */
BIO_bind(int sock,const BIO_ADDR * addr,int options)159*b077aed3SPierre Pronchery int BIO_bind(int sock, const BIO_ADDR *addr, int options)
160*b077aed3SPierre Pronchery {
161*b077aed3SPierre Pronchery # ifndef OPENSSL_SYS_WINDOWS
162*b077aed3SPierre Pronchery     int on = 1;
163*b077aed3SPierre Pronchery # endif
164*b077aed3SPierre Pronchery 
165*b077aed3SPierre Pronchery     if (sock == -1) {
166*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
167*b077aed3SPierre Pronchery         return 0;
168*b077aed3SPierre Pronchery     }
169*b077aed3SPierre Pronchery 
170*b077aed3SPierre Pronchery # ifndef OPENSSL_SYS_WINDOWS
171*b077aed3SPierre Pronchery     /*
172*b077aed3SPierre Pronchery      * SO_REUSEADDR has different behavior on Windows than on
173*b077aed3SPierre Pronchery      * other operating systems, don't set it there.
174*b077aed3SPierre Pronchery      */
175*b077aed3SPierre Pronchery     if (options & BIO_SOCK_REUSEADDR) {
176*b077aed3SPierre Pronchery         if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
177*b077aed3SPierre Pronchery                        (const void *)&on, sizeof(on)) != 0) {
178*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
179*b077aed3SPierre Pronchery                            "calling setsockopt()");
180*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_REUSEADDR);
181*b077aed3SPierre Pronchery             return 0;
182*b077aed3SPierre Pronchery         }
183*b077aed3SPierre Pronchery     }
184*b077aed3SPierre Pronchery # endif
185*b077aed3SPierre Pronchery 
186*b077aed3SPierre Pronchery     if (bind(sock, BIO_ADDR_sockaddr(addr), BIO_ADDR_sockaddr_size(addr)) != 0) {
187*b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error() /* may be 0 */,
188*b077aed3SPierre Pronchery                        "calling bind()");
189*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_BIND_SOCKET);
190*b077aed3SPierre Pronchery         return 0;
191*b077aed3SPierre Pronchery     }
192*b077aed3SPierre Pronchery 
193*b077aed3SPierre Pronchery     return 1;
194*b077aed3SPierre Pronchery }
195*b077aed3SPierre Pronchery 
196*b077aed3SPierre Pronchery /*-
197*b077aed3SPierre Pronchery  * BIO_listen - Creates a listen socket
198*b077aed3SPierre Pronchery  * @sock: the socket to listen with
199*b077aed3SPierre Pronchery  * @addr: local address to bind to
200*b077aed3SPierre Pronchery  * @options: BIO socket options
201*b077aed3SPierre Pronchery  *
202*b077aed3SPierre Pronchery  * Binds to the address using the given socket and options, then
203*b077aed3SPierre Pronchery  * starts listening for incoming connections.
204*b077aed3SPierre Pronchery  *
205*b077aed3SPierre Pronchery  * Options can be a combination of the following:
206*b077aed3SPierre Pronchery  * - BIO_SOCK_KEEPALIVE: enable regularly sending keep-alive messages.
207*b077aed3SPierre Pronchery  * - BIO_SOCK_NONBLOCK: Make the socket non-blocking.
208*b077aed3SPierre Pronchery  * - BIO_SOCK_NODELAY: don't delay small messages.
209*b077aed3SPierre Pronchery  * - BIO_SOCK_REUSEADDR: Try to reuse the address and port combination
210*b077aed3SPierre Pronchery  *   for a recently closed port.
211*b077aed3SPierre Pronchery  * - BIO_SOCK_V6_ONLY: When creating an IPv6 socket, make it listen only
212*b077aed3SPierre Pronchery  *   for IPv6 addresses and not IPv4 addresses mapped to IPv6.
213*b077aed3SPierre Pronchery  *
214*b077aed3SPierre Pronchery  * It's recommended that you set up both an IPv6 and IPv4 listen socket, and
215*b077aed3SPierre Pronchery  * then check both for new clients that connect to it.  You want to set up
216*b077aed3SPierre Pronchery  * the socket as non-blocking in that case since else it could hang.
217*b077aed3SPierre Pronchery  *
218*b077aed3SPierre Pronchery  * Not all operating systems support IPv4 addresses on an IPv6 socket, and for
219*b077aed3SPierre Pronchery  * others it's an option.  If you pass the BIO_LISTEN_V6_ONLY it will try to
220*b077aed3SPierre Pronchery  * create the IPv6 sockets to only listen for IPv6 connection.
221*b077aed3SPierre Pronchery  *
222*b077aed3SPierre Pronchery  * It could be that the first BIO_listen() call will listen to all the IPv6
223*b077aed3SPierre Pronchery  * and IPv4 addresses and that then trying to bind to the IPv4 address will
224*b077aed3SPierre Pronchery  * fail.  We can't tell the difference between already listening ourself to
225*b077aed3SPierre Pronchery  * it and someone else listening to it when failing and errno is EADDRINUSE, so
226*b077aed3SPierre Pronchery  * it's recommended to not give an error in that case if the first call was
227*b077aed3SPierre Pronchery  * successful.
228*b077aed3SPierre Pronchery  *
229*b077aed3SPierre Pronchery  * When restarting the program it could be that the port is still in use.  If
230*b077aed3SPierre Pronchery  * you set to BIO_SOCK_REUSEADDR option it will try to reuse the port anyway.
231*b077aed3SPierre Pronchery  * It's recommended that you use this.
232*b077aed3SPierre Pronchery  */
BIO_listen(int sock,const BIO_ADDR * addr,int options)233*b077aed3SPierre Pronchery int BIO_listen(int sock, const BIO_ADDR *addr, int options)
234*b077aed3SPierre Pronchery {
235*b077aed3SPierre Pronchery     int on = 1;
236*b077aed3SPierre Pronchery     int socktype;
237*b077aed3SPierre Pronchery     socklen_t socktype_len = sizeof(socktype);
238*b077aed3SPierre Pronchery 
239*b077aed3SPierre Pronchery     if (sock == -1) {
240*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_INVALID_SOCKET);
241*b077aed3SPierre Pronchery         return 0;
242*b077aed3SPierre Pronchery     }
243*b077aed3SPierre Pronchery 
244*b077aed3SPierre Pronchery     if (getsockopt(sock, SOL_SOCKET, SO_TYPE,
245*b077aed3SPierre Pronchery                    (void *)&socktype, &socktype_len) != 0
246*b077aed3SPierre Pronchery         || socktype_len != sizeof(socktype)) {
247*b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
248*b077aed3SPierre Pronchery                        "calling getsockopt()");
249*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_GETTING_SOCKTYPE);
250*b077aed3SPierre Pronchery         return 0;
251*b077aed3SPierre Pronchery     }
252*b077aed3SPierre Pronchery 
253*b077aed3SPierre Pronchery     if (!BIO_socket_nbio(sock, (options & BIO_SOCK_NONBLOCK) != 0))
254*b077aed3SPierre Pronchery         return 0;
255*b077aed3SPierre Pronchery 
256*b077aed3SPierre Pronchery     if (options & BIO_SOCK_KEEPALIVE) {
257*b077aed3SPierre Pronchery         if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
258*b077aed3SPierre Pronchery                        (const void *)&on, sizeof(on)) != 0) {
259*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
260*b077aed3SPierre Pronchery                            "calling setsockopt()");
261*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_KEEPALIVE);
262*b077aed3SPierre Pronchery             return 0;
263*b077aed3SPierre Pronchery         }
264*b077aed3SPierre Pronchery     }
265*b077aed3SPierre Pronchery 
266*b077aed3SPierre Pronchery     if (options & BIO_SOCK_NODELAY) {
267*b077aed3SPierre Pronchery         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
268*b077aed3SPierre Pronchery                        (const void *)&on, sizeof(on)) != 0) {
269*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
270*b077aed3SPierre Pronchery                            "calling setsockopt()");
271*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_NODELAY);
272*b077aed3SPierre Pronchery             return 0;
273*b077aed3SPierre Pronchery         }
274*b077aed3SPierre Pronchery     }
275*b077aed3SPierre Pronchery 
276*b077aed3SPierre Pronchery   /* On OpenBSD it is always ipv6 only with ipv6 sockets thus read-only */
277*b077aed3SPierre Pronchery # if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
278*b077aed3SPierre Pronchery     if (BIO_ADDR_family(addr) == AF_INET6) {
279*b077aed3SPierre Pronchery         /*
280*b077aed3SPierre Pronchery          * Note: Windows default of IPV6_V6ONLY is ON, and Linux is OFF.
281*b077aed3SPierre Pronchery          * Therefore we always have to use setsockopt here.
282*b077aed3SPierre Pronchery          */
283*b077aed3SPierre Pronchery         on = options & BIO_SOCK_V6_ONLY ? 1 : 0;
284*b077aed3SPierre Pronchery         if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
285*b077aed3SPierre Pronchery                        (const void *)&on, sizeof(on)) != 0) {
286*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
287*b077aed3SPierre Pronchery                            "calling setsockopt()");
288*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_LISTEN_V6_ONLY);
289*b077aed3SPierre Pronchery             return 0;
290*b077aed3SPierre Pronchery         }
291*b077aed3SPierre Pronchery     }
292*b077aed3SPierre Pronchery # endif
293*b077aed3SPierre Pronchery 
294*b077aed3SPierre Pronchery     if (!BIO_bind(sock, addr, options))
295*b077aed3SPierre Pronchery         return 0;
296*b077aed3SPierre Pronchery 
297*b077aed3SPierre Pronchery     if (socktype != SOCK_DGRAM && listen(sock, MAX_LISTEN) == -1) {
298*b077aed3SPierre Pronchery         ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
299*b077aed3SPierre Pronchery                        "calling listen()");
300*b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_BIO, BIO_R_UNABLE_TO_LISTEN_SOCKET);
301*b077aed3SPierre Pronchery         return 0;
302*b077aed3SPierre Pronchery     }
303*b077aed3SPierre Pronchery 
304*b077aed3SPierre Pronchery     return 1;
305*b077aed3SPierre Pronchery }
306*b077aed3SPierre Pronchery 
307*b077aed3SPierre Pronchery /*-
308*b077aed3SPierre Pronchery  * BIO_accept_ex - Accept new incoming connections
309*b077aed3SPierre Pronchery  * @sock: the listening socket
310*b077aed3SPierre Pronchery  * @addr: the BIO_ADDR to store the peer address in
311*b077aed3SPierre Pronchery  * @options: BIO socket options, applied on the accepted socket.
312*b077aed3SPierre Pronchery  *
313*b077aed3SPierre Pronchery  */
BIO_accept_ex(int accept_sock,BIO_ADDR * addr_,int options)314*b077aed3SPierre Pronchery int BIO_accept_ex(int accept_sock, BIO_ADDR *addr_, int options)
315*b077aed3SPierre Pronchery {
316*b077aed3SPierre Pronchery     socklen_t len;
317*b077aed3SPierre Pronchery     int accepted_sock;
318*b077aed3SPierre Pronchery     BIO_ADDR locaddr;
319*b077aed3SPierre Pronchery     BIO_ADDR *addr = addr_ == NULL ? &locaddr : addr_;
320*b077aed3SPierre Pronchery 
321*b077aed3SPierre Pronchery     len = sizeof(*addr);
322*b077aed3SPierre Pronchery     accepted_sock = accept(accept_sock,
323*b077aed3SPierre Pronchery                            BIO_ADDR_sockaddr_noconst(addr), &len);
324*b077aed3SPierre Pronchery     if (accepted_sock == -1) {
325*b077aed3SPierre Pronchery         if (!BIO_sock_should_retry(accepted_sock)) {
326*b077aed3SPierre Pronchery             ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
327*b077aed3SPierre Pronchery                            "calling accept()");
328*b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR);
329*b077aed3SPierre Pronchery         }
330*b077aed3SPierre Pronchery         return INVALID_SOCKET;
331*b077aed3SPierre Pronchery     }
332*b077aed3SPierre Pronchery 
333*b077aed3SPierre Pronchery     if (!BIO_socket_nbio(accepted_sock, (options & BIO_SOCK_NONBLOCK) != 0)) {
334*b077aed3SPierre Pronchery         closesocket(accepted_sock);
335*b077aed3SPierre Pronchery         return INVALID_SOCKET;
336*b077aed3SPierre Pronchery     }
337*b077aed3SPierre Pronchery 
338*b077aed3SPierre Pronchery     return accepted_sock;
339*b077aed3SPierre Pronchery }
340*b077aed3SPierre Pronchery 
341*b077aed3SPierre Pronchery /*-
342*b077aed3SPierre Pronchery  * BIO_closesocket - Close a socket
343*b077aed3SPierre Pronchery  * @sock: the socket to close
344*b077aed3SPierre Pronchery  */
BIO_closesocket(int sock)345*b077aed3SPierre Pronchery int BIO_closesocket(int sock)
346*b077aed3SPierre Pronchery {
347*b077aed3SPierre Pronchery     if (sock < 0 || closesocket(sock) < 0)
348*b077aed3SPierre Pronchery         return 0;
349*b077aed3SPierre Pronchery     return 1;
350*b077aed3SPierre Pronchery }
351*b077aed3SPierre Pronchery #endif
352