1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-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 "bio_local.h" 13e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SOCK 14e1051a39Sopenharmony_ci# define SOCKET_PROTOCOL IPPROTO_TCP 15e1051a39Sopenharmony_ci# ifdef SO_MAXCONN 16e1051a39Sopenharmony_ci# define MAX_LISTEN SO_MAXCONN 17e1051a39Sopenharmony_ci# elif defined(SOMAXCONN) 18e1051a39Sopenharmony_ci# define MAX_LISTEN SOMAXCONN 19e1051a39Sopenharmony_ci# else 20e1051a39Sopenharmony_ci# define MAX_LISTEN 32 21e1051a39Sopenharmony_ci# endif 22e1051a39Sopenharmony_ci# if defined(OPENSSL_SYS_WINDOWS) 23e1051a39Sopenharmony_cistatic int wsa_init_done = 0; 24e1051a39Sopenharmony_ci# endif 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci# if defined __TANDEM 27e1051a39Sopenharmony_ci# include <unistd.h> 28e1051a39Sopenharmony_ci# include <sys/time.h> /* select */ 29e1051a39Sopenharmony_ci# if defined(OPENSSL_TANDEM_FLOSS) 30e1051a39Sopenharmony_ci# include <floss.h(floss_select)> 31e1051a39Sopenharmony_ci# endif 32e1051a39Sopenharmony_ci# elif defined _WIN32 33e1051a39Sopenharmony_ci# include <winsock.h> /* for type fd_set */ 34e1051a39Sopenharmony_ci# else 35e1051a39Sopenharmony_ci# include <unistd.h> 36e1051a39Sopenharmony_ci# if defined __VMS 37e1051a39Sopenharmony_ci# include <sys/socket.h> 38e1051a39Sopenharmony_ci# elif defined _HPUX_SOURCE 39e1051a39Sopenharmony_ci# include <sys/time.h> 40e1051a39Sopenharmony_ci# else 41e1051a39Sopenharmony_ci# include <sys/select.h> 42e1051a39Sopenharmony_ci# endif 43e1051a39Sopenharmony_ci# endif 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DEPRECATED_1_1_0 46e1051a39Sopenharmony_ciint BIO_get_host_ip(const char *str, unsigned char *ip) 47e1051a39Sopenharmony_ci{ 48e1051a39Sopenharmony_ci BIO_ADDRINFO *res = NULL; 49e1051a39Sopenharmony_ci int ret = 0; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci if (BIO_sock_init() != 1) 52e1051a39Sopenharmony_ci return 0; /* don't generate another error code here */ 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { 55e1051a39Sopenharmony_ci size_t l; 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_ci if (BIO_ADDRINFO_family(res) != AF_INET) { 58e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); 59e1051a39Sopenharmony_ci } else if (BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l)) { 60e1051a39Sopenharmony_ci /* 61e1051a39Sopenharmony_ci * Because only AF_INET addresses will reach this far, we can assert 62e1051a39Sopenharmony_ci * that l should be 4 63e1051a39Sopenharmony_ci */ 64e1051a39Sopenharmony_ci if (ossl_assert(l == 4)) 65e1051a39Sopenharmony_ci ret = BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l); 66e1051a39Sopenharmony_ci } 67e1051a39Sopenharmony_ci BIO_ADDRINFO_free(res); 68e1051a39Sopenharmony_ci } else { 69e1051a39Sopenharmony_ci ERR_add_error_data(2, "host=", str); 70e1051a39Sopenharmony_ci } 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci return ret; 73e1051a39Sopenharmony_ci} 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ciint BIO_get_port(const char *str, unsigned short *port_ptr) 76e1051a39Sopenharmony_ci{ 77e1051a39Sopenharmony_ci BIO_ADDRINFO *res = NULL; 78e1051a39Sopenharmony_ci int ret = 0; 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci if (str == NULL) { 81e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_NO_PORT_DEFINED); 82e1051a39Sopenharmony_ci return 0; 83e1051a39Sopenharmony_ci } 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_ci if (BIO_sock_init() != 1) 86e1051a39Sopenharmony_ci return 0; /* don't generate another error code here */ 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) { 89e1051a39Sopenharmony_ci if (BIO_ADDRINFO_family(res) != AF_INET) { 90e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET); 91e1051a39Sopenharmony_ci } else { 92e1051a39Sopenharmony_ci *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res))); 93e1051a39Sopenharmony_ci ret = 1; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci BIO_ADDRINFO_free(res); 96e1051a39Sopenharmony_ci } else { 97e1051a39Sopenharmony_ci ERR_add_error_data(2, "host=", str); 98e1051a39Sopenharmony_ci } 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_ci return ret; 101e1051a39Sopenharmony_ci} 102e1051a39Sopenharmony_ci# endif 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ciint BIO_sock_error(int sock) 105e1051a39Sopenharmony_ci{ 106e1051a39Sopenharmony_ci int j = 0, i; 107e1051a39Sopenharmony_ci socklen_t size = sizeof(j); 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci /* 110e1051a39Sopenharmony_ci * Note: under Windows the third parameter is of type (char *) whereas 111e1051a39Sopenharmony_ci * under other systems it is (void *) if you don't have a cast it will 112e1051a39Sopenharmony_ci * choke the compiler: if you do have a cast then you can either go for 113e1051a39Sopenharmony_ci * (char *) or (void *). 114e1051a39Sopenharmony_ci */ 115e1051a39Sopenharmony_ci i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size); 116e1051a39Sopenharmony_ci if (i < 0) 117e1051a39Sopenharmony_ci return get_last_socket_error(); 118e1051a39Sopenharmony_ci else 119e1051a39Sopenharmony_ci return j; 120e1051a39Sopenharmony_ci} 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DEPRECATED_1_1_0 123e1051a39Sopenharmony_cistruct hostent *BIO_gethostbyname(const char *name) 124e1051a39Sopenharmony_ci{ 125e1051a39Sopenharmony_ci /* 126e1051a39Sopenharmony_ci * Caching gethostbyname() results forever is wrong, so we have to let 127e1051a39Sopenharmony_ci * the true gethostbyname() worry about this 128e1051a39Sopenharmony_ci */ 129e1051a39Sopenharmony_ci return gethostbyname(name); 130e1051a39Sopenharmony_ci} 131e1051a39Sopenharmony_ci# endif 132e1051a39Sopenharmony_ci 133e1051a39Sopenharmony_ciint BIO_sock_init(void) 134e1051a39Sopenharmony_ci{ 135e1051a39Sopenharmony_ci# ifdef OPENSSL_SYS_WINDOWS 136e1051a39Sopenharmony_ci static struct WSAData wsa_state; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci if (!wsa_init_done) { 139e1051a39Sopenharmony_ci wsa_init_done = 1; 140e1051a39Sopenharmony_ci memset(&wsa_state, 0, sizeof(wsa_state)); 141e1051a39Sopenharmony_ci /* 142e1051a39Sopenharmony_ci * Not making wsa_state available to the rest of the code is formally 143e1051a39Sopenharmony_ci * wrong. But the structures we use are [believed to be] invariable 144e1051a39Sopenharmony_ci * among Winsock DLLs, while API availability is [expected to be] 145e1051a39Sopenharmony_ci * probed at run-time with DSO_global_lookup. 146e1051a39Sopenharmony_ci */ 147e1051a39Sopenharmony_ci if (WSAStartup(0x0202, &wsa_state) != 0) { 148e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 149e1051a39Sopenharmony_ci "calling wsastartup()"); 150e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_WSASTARTUP); 151e1051a39Sopenharmony_ci return -1; 152e1051a39Sopenharmony_ci } 153e1051a39Sopenharmony_ci } 154e1051a39Sopenharmony_ci# endif /* OPENSSL_SYS_WINDOWS */ 155e1051a39Sopenharmony_ci# ifdef WATT32 156e1051a39Sopenharmony_ci extern int _watt_do_exit; 157e1051a39Sopenharmony_ci _watt_do_exit = 0; /* don't make sock_init() call exit() */ 158e1051a39Sopenharmony_ci if (sock_init()) 159e1051a39Sopenharmony_ci return -1; 160e1051a39Sopenharmony_ci# endif 161e1051a39Sopenharmony_ci 162e1051a39Sopenharmony_ci return 1; 163e1051a39Sopenharmony_ci} 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_civoid bio_sock_cleanup_int(void) 166e1051a39Sopenharmony_ci{ 167e1051a39Sopenharmony_ci# ifdef OPENSSL_SYS_WINDOWS 168e1051a39Sopenharmony_ci if (wsa_init_done) { 169e1051a39Sopenharmony_ci wsa_init_done = 0; 170e1051a39Sopenharmony_ci WSACleanup(); 171e1051a39Sopenharmony_ci } 172e1051a39Sopenharmony_ci# endif 173e1051a39Sopenharmony_ci} 174e1051a39Sopenharmony_ci 175e1051a39Sopenharmony_ciint BIO_socket_ioctl(int fd, long type, void *arg) 176e1051a39Sopenharmony_ci{ 177e1051a39Sopenharmony_ci int i; 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci# ifdef __DJGPP__ 180e1051a39Sopenharmony_ci i = ioctlsocket(fd, type, (char *)arg); 181e1051a39Sopenharmony_ci# else 182e1051a39Sopenharmony_ci# if defined(OPENSSL_SYS_VMS) 183e1051a39Sopenharmony_ci /*- 184e1051a39Sopenharmony_ci * 2011-02-18 SMS. 185e1051a39Sopenharmony_ci * VMS ioctl() can't tolerate a 64-bit "void *arg", but we 186e1051a39Sopenharmony_ci * observe that all the consumers pass in an "unsigned long *", 187e1051a39Sopenharmony_ci * so we arrange a local copy with a short pointer, and use 188e1051a39Sopenharmony_ci * that, instead. 189e1051a39Sopenharmony_ci */ 190e1051a39Sopenharmony_ci# if __INITIAL_POINTER_SIZE == 64 191e1051a39Sopenharmony_ci# define ARG arg_32p 192e1051a39Sopenharmony_ci# pragma pointer_size save 193e1051a39Sopenharmony_ci# pragma pointer_size 32 194e1051a39Sopenharmony_ci unsigned long arg_32; 195e1051a39Sopenharmony_ci unsigned long *arg_32p; 196e1051a39Sopenharmony_ci# pragma pointer_size restore 197e1051a39Sopenharmony_ci arg_32p = &arg_32; 198e1051a39Sopenharmony_ci arg_32 = *((unsigned long *)arg); 199e1051a39Sopenharmony_ci# else /* __INITIAL_POINTER_SIZE == 64 */ 200e1051a39Sopenharmony_ci# define ARG arg 201e1051a39Sopenharmony_ci# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ 202e1051a39Sopenharmony_ci# else /* defined(OPENSSL_SYS_VMS) */ 203e1051a39Sopenharmony_ci# define ARG arg 204e1051a39Sopenharmony_ci# endif /* defined(OPENSSL_SYS_VMS) [else] */ 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci i = ioctlsocket(fd, type, ARG); 207e1051a39Sopenharmony_ci# endif /* __DJGPP__ */ 208e1051a39Sopenharmony_ci if (i < 0) 209e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 210e1051a39Sopenharmony_ci "calling ioctlsocket()"); 211e1051a39Sopenharmony_ci return i; 212e1051a39Sopenharmony_ci} 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DEPRECATED_1_1_0 215e1051a39Sopenharmony_ciint BIO_get_accept_socket(char *host, int bind_mode) 216e1051a39Sopenharmony_ci{ 217e1051a39Sopenharmony_ci int s = INVALID_SOCKET; 218e1051a39Sopenharmony_ci char *h = NULL, *p = NULL; 219e1051a39Sopenharmony_ci BIO_ADDRINFO *res = NULL; 220e1051a39Sopenharmony_ci 221e1051a39Sopenharmony_ci if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV)) 222e1051a39Sopenharmony_ci return INVALID_SOCKET; 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci if (BIO_sock_init() != 1) 225e1051a39Sopenharmony_ci return INVALID_SOCKET; 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_ci if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0) 228e1051a39Sopenharmony_ci goto err; 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res), 231e1051a39Sopenharmony_ci BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) { 232e1051a39Sopenharmony_ci s = INVALID_SOCKET; 233e1051a39Sopenharmony_ci goto err; 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci if (!BIO_listen(s, BIO_ADDRINFO_address(res), 237e1051a39Sopenharmony_ci bind_mode ? BIO_SOCK_REUSEADDR : 0)) { 238e1051a39Sopenharmony_ci BIO_closesocket(s); 239e1051a39Sopenharmony_ci s = INVALID_SOCKET; 240e1051a39Sopenharmony_ci } 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci err: 243e1051a39Sopenharmony_ci BIO_ADDRINFO_free(res); 244e1051a39Sopenharmony_ci OPENSSL_free(h); 245e1051a39Sopenharmony_ci OPENSSL_free(p); 246e1051a39Sopenharmony_ci 247e1051a39Sopenharmony_ci return s; 248e1051a39Sopenharmony_ci} 249e1051a39Sopenharmony_ci 250e1051a39Sopenharmony_ciint BIO_accept(int sock, char **ip_port) 251e1051a39Sopenharmony_ci{ 252e1051a39Sopenharmony_ci BIO_ADDR res; 253e1051a39Sopenharmony_ci int ret = -1; 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci ret = BIO_accept_ex(sock, &res, 0); 256e1051a39Sopenharmony_ci if (ret == (int)INVALID_SOCKET) { 257e1051a39Sopenharmony_ci if (BIO_sock_should_retry(ret)) { 258e1051a39Sopenharmony_ci ret = -2; 259e1051a39Sopenharmony_ci goto end; 260e1051a39Sopenharmony_ci } 261e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 262e1051a39Sopenharmony_ci "calling accept()"); 263e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_ACCEPT_ERROR); 264e1051a39Sopenharmony_ci goto end; 265e1051a39Sopenharmony_ci } 266e1051a39Sopenharmony_ci 267e1051a39Sopenharmony_ci if (ip_port != NULL) { 268e1051a39Sopenharmony_ci char *host = BIO_ADDR_hostname_string(&res, 1); 269e1051a39Sopenharmony_ci char *port = BIO_ADDR_service_string(&res, 1); 270e1051a39Sopenharmony_ci if (host != NULL && port != NULL) 271e1051a39Sopenharmony_ci *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2); 272e1051a39Sopenharmony_ci else 273e1051a39Sopenharmony_ci *ip_port = NULL; 274e1051a39Sopenharmony_ci 275e1051a39Sopenharmony_ci if (*ip_port == NULL) { 276e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 277e1051a39Sopenharmony_ci BIO_closesocket(ret); 278e1051a39Sopenharmony_ci ret = (int)INVALID_SOCKET; 279e1051a39Sopenharmony_ci } else { 280e1051a39Sopenharmony_ci strcpy(*ip_port, host); 281e1051a39Sopenharmony_ci strcat(*ip_port, ":"); 282e1051a39Sopenharmony_ci strcat(*ip_port, port); 283e1051a39Sopenharmony_ci } 284e1051a39Sopenharmony_ci OPENSSL_free(host); 285e1051a39Sopenharmony_ci OPENSSL_free(port); 286e1051a39Sopenharmony_ci } 287e1051a39Sopenharmony_ci 288e1051a39Sopenharmony_ci end: 289e1051a39Sopenharmony_ci return ret; 290e1051a39Sopenharmony_ci} 291e1051a39Sopenharmony_ci# endif 292e1051a39Sopenharmony_ci 293e1051a39Sopenharmony_ciint BIO_set_tcp_ndelay(int s, int on) 294e1051a39Sopenharmony_ci{ 295e1051a39Sopenharmony_ci int ret = 0; 296e1051a39Sopenharmony_ci# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) 297e1051a39Sopenharmony_ci int opt; 298e1051a39Sopenharmony_ci 299e1051a39Sopenharmony_ci# ifdef SOL_TCP 300e1051a39Sopenharmony_ci opt = SOL_TCP; 301e1051a39Sopenharmony_ci# else 302e1051a39Sopenharmony_ci# ifdef IPPROTO_TCP 303e1051a39Sopenharmony_ci opt = IPPROTO_TCP; 304e1051a39Sopenharmony_ci# endif 305e1051a39Sopenharmony_ci# endif 306e1051a39Sopenharmony_ci 307e1051a39Sopenharmony_ci ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); 308e1051a39Sopenharmony_ci# endif 309e1051a39Sopenharmony_ci return (ret == 0); 310e1051a39Sopenharmony_ci} 311e1051a39Sopenharmony_ci 312e1051a39Sopenharmony_ciint BIO_socket_nbio(int s, int mode) 313e1051a39Sopenharmony_ci{ 314e1051a39Sopenharmony_ci int ret = -1; 315e1051a39Sopenharmony_ci int l; 316e1051a39Sopenharmony_ci 317e1051a39Sopenharmony_ci l = mode; 318e1051a39Sopenharmony_ci# ifdef FIONBIO 319e1051a39Sopenharmony_ci l = mode; 320e1051a39Sopenharmony_ci 321e1051a39Sopenharmony_ci ret = BIO_socket_ioctl(s, FIONBIO, &l); 322e1051a39Sopenharmony_ci# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY)) 323e1051a39Sopenharmony_ci /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_ci l = fcntl(s, F_GETFL, 0); 326e1051a39Sopenharmony_ci if (l == -1) { 327e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), 328e1051a39Sopenharmony_ci "calling fcntl()"); 329e1051a39Sopenharmony_ci ret = -1; 330e1051a39Sopenharmony_ci } else { 331e1051a39Sopenharmony_ci# if defined(O_NONBLOCK) 332e1051a39Sopenharmony_ci l &= ~O_NONBLOCK; 333e1051a39Sopenharmony_ci# else 334e1051a39Sopenharmony_ci l &= ~FNDELAY; /* BSD4.x */ 335e1051a39Sopenharmony_ci# endif 336e1051a39Sopenharmony_ci if (mode) { 337e1051a39Sopenharmony_ci# if defined(O_NONBLOCK) 338e1051a39Sopenharmony_ci l |= O_NONBLOCK; 339e1051a39Sopenharmony_ci# else 340e1051a39Sopenharmony_ci l |= FNDELAY; /* BSD4.x */ 341e1051a39Sopenharmony_ci# endif 342e1051a39Sopenharmony_ci } 343e1051a39Sopenharmony_ci ret = fcntl(s, F_SETFL, l); 344e1051a39Sopenharmony_ci 345e1051a39Sopenharmony_ci if (ret < 0) { 346e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, get_last_sys_error(), 347e1051a39Sopenharmony_ci "calling fcntl()"); 348e1051a39Sopenharmony_ci } 349e1051a39Sopenharmony_ci } 350e1051a39Sopenharmony_ci# else 351e1051a39Sopenharmony_ci /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */ 352e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, ERR_R_PASSED_INVALID_ARGUMENT); 353e1051a39Sopenharmony_ci# endif 354e1051a39Sopenharmony_ci 355e1051a39Sopenharmony_ci return (ret == 0); 356e1051a39Sopenharmony_ci} 357e1051a39Sopenharmony_ci 358e1051a39Sopenharmony_ciint BIO_sock_info(int sock, 359e1051a39Sopenharmony_ci enum BIO_sock_info_type type, union BIO_sock_info_u *info) 360e1051a39Sopenharmony_ci{ 361e1051a39Sopenharmony_ci switch (type) { 362e1051a39Sopenharmony_ci case BIO_SOCK_INFO_ADDRESS: 363e1051a39Sopenharmony_ci { 364e1051a39Sopenharmony_ci socklen_t addr_len; 365e1051a39Sopenharmony_ci int ret = 0; 366e1051a39Sopenharmony_ci addr_len = sizeof(*info->addr); 367e1051a39Sopenharmony_ci ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr), 368e1051a39Sopenharmony_ci &addr_len); 369e1051a39Sopenharmony_ci if (ret == -1) { 370e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(), 371e1051a39Sopenharmony_ci "calling getsockname()"); 372e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_ERROR); 373e1051a39Sopenharmony_ci return 0; 374e1051a39Sopenharmony_ci } 375e1051a39Sopenharmony_ci if ((size_t)addr_len > sizeof(*info->addr)) { 376e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS); 377e1051a39Sopenharmony_ci return 0; 378e1051a39Sopenharmony_ci } 379e1051a39Sopenharmony_ci } 380e1051a39Sopenharmony_ci break; 381e1051a39Sopenharmony_ci default: 382e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_BIO, BIO_R_UNKNOWN_INFO_TYPE); 383e1051a39Sopenharmony_ci return 0; 384e1051a39Sopenharmony_ci } 385e1051a39Sopenharmony_ci return 1; 386e1051a39Sopenharmony_ci} 387e1051a39Sopenharmony_ci 388e1051a39Sopenharmony_ci/* 389e1051a39Sopenharmony_ci * Wait on fd at most until max_time; succeed immediately if max_time == 0. 390e1051a39Sopenharmony_ci * If for_read == 0 then assume to wait for writing, else wait for reading. 391e1051a39Sopenharmony_ci * Returns -1 on error, 0 on timeout, and 1 on success. 392e1051a39Sopenharmony_ci */ 393e1051a39Sopenharmony_ciint BIO_socket_wait(int fd, int for_read, time_t max_time) 394e1051a39Sopenharmony_ci{ 395e1051a39Sopenharmony_ci fd_set confds; 396e1051a39Sopenharmony_ci struct timeval tv; 397e1051a39Sopenharmony_ci time_t now; 398e1051a39Sopenharmony_ci 399e1051a39Sopenharmony_ci if (fd < 0 || fd >= FD_SETSIZE) 400e1051a39Sopenharmony_ci return -1; 401e1051a39Sopenharmony_ci if (max_time == 0) 402e1051a39Sopenharmony_ci return 1; 403e1051a39Sopenharmony_ci 404e1051a39Sopenharmony_ci now = time(NULL); 405e1051a39Sopenharmony_ci if (max_time < now) 406e1051a39Sopenharmony_ci return 0; 407e1051a39Sopenharmony_ci 408e1051a39Sopenharmony_ci FD_ZERO(&confds); 409e1051a39Sopenharmony_ci openssl_fdset(fd, &confds); 410e1051a39Sopenharmony_ci tv.tv_usec = 0; 411e1051a39Sopenharmony_ci tv.tv_sec = (long)(max_time - now); /* might overflow */ 412e1051a39Sopenharmony_ci return select(fd + 1, for_read ? &confds : NULL, 413e1051a39Sopenharmony_ci for_read ? NULL : &confds, NULL, &tv); 414e1051a39Sopenharmony_ci} 415e1051a39Sopenharmony_ci#endif /* !defined(OPENSSL_NO_SOCK) */ 416