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