155714Skris/* crypto/bio/b_sock.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8280297Sjkim * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280297Sjkim * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22280297Sjkim * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37280297Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280297Sjkim * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52280297Sjkim * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 59340704Sjkim#define _DEFAULT_SOURCE 60340704Sjkim#define _BSD_SOURCE 61340704Sjkim 6255714Skris#include <stdio.h> 6355714Skris#include <stdlib.h> 6455714Skris#include <errno.h> 6555714Skris#define USE_SOCKETS 6655714Skris#include "cryptlib.h" 6755714Skris#include <openssl/bio.h> 68160814Ssimon#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK) 69280297Sjkim# include <netdb.h> 70280297Sjkim# if defined(NETWARE_CLIB) 71280297Sjkim# include <sys/ioctl.h> 72194206SsimonNETDB_DEFINE_CONTEXT 73280297Sjkim# endif 74160814Ssimon#endif 75160814Ssimon#ifndef OPENSSL_NO_SOCK 76280297Sjkim# include <openssl/dso.h> 77280297Sjkim# define SOCKET_PROTOCOL IPPROTO_TCP 78280297Sjkim# ifdef SO_MAXCONN 79280297Sjkim# define MAX_LISTEN SO_MAXCONN 80280297Sjkim# elif defined(SOMAXCONN) 81280297Sjkim# define MAX_LISTEN SOMAXCONN 82280297Sjkim# else 83280297Sjkim# define MAX_LISTEN 32 84280297Sjkim# endif 85280297Sjkim# if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)) 86280297Sjkimstatic int wsa_init_done = 0; 87280297Sjkim# endif 88160814Ssimon 89340704Sjkim# if defined(__GLIBC__) 90340704Sjkim# define HAVE_GETHOSTBYNAME_R 91340704Sjkim# define GETHOSTNAME_R_BUF (2 * 1024) 92340704Sjkim# endif 93340704Sjkim 94238405Sjkim/* 95238405Sjkim * WSAAPI specifier is required to make indirect calls to run-time 96238405Sjkim * linked WinSock 2 functions used in this module, to be specific 97238405Sjkim * [get|free]addrinfo and getnameinfo. This is because WinSock uses 98238405Sjkim * uses non-C calling convention, __stdcall vs. __cdecl, on x86 99238405Sjkim * Windows. On non-WinSock platforms WSAAPI needs to be void. 100238405Sjkim */ 101280297Sjkim# ifndef WSAAPI 102280297Sjkim# define WSAAPI 103280297Sjkim# endif 104238405Sjkim 105280297Sjkim# if 0 106280297Sjkimstatic unsigned long BIO_ghbn_hits = 0L; 107280297Sjkimstatic unsigned long BIO_ghbn_miss = 0L; 10855714Skris 109280297Sjkim# define GHBN_NUM 4 110280297Sjkimstatic struct ghbn_cache_st { 111280297Sjkim char name[129]; 112280297Sjkim struct hostent *ent; 113280297Sjkim unsigned long order; 114280297Sjkim} ghbn_cache[GHBN_NUM]; 115280297Sjkim# endif 11655714Skris 117280297Sjkimstatic int get_ip(const char *str, unsigned char *ip); 118280297Sjkim# if 0 11955714Skrisstatic void ghbn_free(struct hostent *a); 12055714Skrisstatic struct hostent *ghbn_dup(struct hostent *a); 121280297Sjkim# endif 12255714Skrisint BIO_get_host_ip(const char *str, unsigned char *ip) 123280297Sjkim{ 124280297Sjkim int i; 125280297Sjkim int err = 1; 126280297Sjkim int locked = 0; 127340704Sjkim struct hostent *he = NULL; 128340704Sjkim# ifdef HAVE_GETHOSTBYNAME_R 129340704Sjkim char buf[GETHOSTNAME_R_BUF]; 130340704Sjkim struct hostent hostent; 131340704Sjkim int h_errnop; 132340704Sjkim# endif 13355714Skris 134280297Sjkim i = get_ip(str, ip); 135280297Sjkim if (i < 0) { 136280297Sjkim BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_INVALID_IP_ADDRESS); 137280297Sjkim goto err; 138280297Sjkim } 13955714Skris 140280297Sjkim /* 141280297Sjkim * At this point, we have something that is most probably correct in some 142280297Sjkim * way, so let's init the socket. 143280297Sjkim */ 144280297Sjkim if (BIO_sock_init() != 1) 145280297Sjkim return 0; /* don't generate another error code here */ 14655714Skris 147280297Sjkim /* 148280297Sjkim * If the string actually contained an IP address, we need not do 149280297Sjkim * anything more 150280297Sjkim */ 151280297Sjkim if (i > 0) 152280297Sjkim return (1); 15368651Skris 154340704Sjkim /* if gethostbyname_r is supported, use it. */ 155340704Sjkim# ifdef HAVE_GETHOSTBYNAME_R 156340704Sjkim memset(&hostent, 0x00, sizeof(hostent)); 157340704Sjkim /* gethostbyname_r() sets |he| to NULL on error, we check it further down */ 158340704Sjkim gethostbyname_r(str, &hostent, buf, sizeof(buf), &he, &h_errnop); 159340704Sjkim# else 160280297Sjkim /* do a gethostbyname */ 161280297Sjkim CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 162280297Sjkim locked = 1; 163280297Sjkim he = BIO_gethostbyname(str); 164340704Sjkim# endif 165340704Sjkim 166280297Sjkim if (he == NULL) { 167280297Sjkim BIOerr(BIO_F_BIO_GET_HOST_IP, BIO_R_BAD_HOSTNAME_LOOKUP); 168280297Sjkim goto err; 169280297Sjkim } 17055714Skris 171280297Sjkim /* cast to short because of win16 winsock definition */ 172280297Sjkim if ((short)he->h_addrtype != AF_INET) { 173280297Sjkim BIOerr(BIO_F_BIO_GET_HOST_IP, 174280297Sjkim BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET); 175280297Sjkim goto err; 176280297Sjkim } 177280297Sjkim for (i = 0; i < 4; i++) 178280297Sjkim ip[i] = he->h_addr_list[0][i]; 179280297Sjkim err = 0; 18055714Skris 18155714Skris err: 182280297Sjkim if (locked) 183280297Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 184280297Sjkim if (err) { 185280297Sjkim ERR_add_error_data(2, "host=", str); 186280297Sjkim return 0; 187280297Sjkim } else 188280297Sjkim return 1; 189280297Sjkim} 19055714Skris 19155714Skrisint BIO_get_port(const char *str, unsigned short *port_ptr) 192280297Sjkim{ 193280297Sjkim int i; 194280297Sjkim struct servent *s; 19555714Skris 196280297Sjkim if (str == NULL) { 197280297Sjkim BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED); 198280297Sjkim return (0); 199280297Sjkim } 200280297Sjkim i = atoi(str); 201280297Sjkim if (i != 0) 202280297Sjkim *port_ptr = (unsigned short)i; 203280297Sjkim else { 204280297Sjkim CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME); 205280297Sjkim /* 206280297Sjkim * Note: under VMS with SOCKETSHR, it seems like the first parameter 207280297Sjkim * is 'char *', instead of 'const char *' 208280297Sjkim */ 209280297Sjkim# ifndef CONST_STRICT 210280297Sjkim s = getservbyname((char *)str, "tcp"); 211280297Sjkim# else 212280297Sjkim s = getservbyname(str, "tcp"); 213280297Sjkim# endif 214280297Sjkim if (s != NULL) 215280297Sjkim *port_ptr = ntohs((unsigned short)s->s_port); 216280297Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME); 217280297Sjkim if (s == NULL) { 218280297Sjkim if (strcmp(str, "http") == 0) 219280297Sjkim *port_ptr = 80; 220280297Sjkim else if (strcmp(str, "telnet") == 0) 221280297Sjkim *port_ptr = 23; 222280297Sjkim else if (strcmp(str, "socks") == 0) 223280297Sjkim *port_ptr = 1080; 224280297Sjkim else if (strcmp(str, "https") == 0) 225280297Sjkim *port_ptr = 443; 226280297Sjkim else if (strcmp(str, "ssl") == 0) 227280297Sjkim *port_ptr = 443; 228280297Sjkim else if (strcmp(str, "ftp") == 0) 229280297Sjkim *port_ptr = 21; 230280297Sjkim else if (strcmp(str, "gopher") == 0) 231280297Sjkim *port_ptr = 70; 232280297Sjkim# if 0 233280297Sjkim else if (strcmp(str, "wais") == 0) 234280297Sjkim *port_ptr = 21; 235280297Sjkim# endif 236280297Sjkim else { 237280297Sjkim SYSerr(SYS_F_GETSERVBYNAME, get_last_socket_error()); 238280297Sjkim ERR_add_error_data(3, "service='", str, "'"); 239280297Sjkim return (0); 240280297Sjkim } 241280297Sjkim } 242280297Sjkim } 243280297Sjkim return (1); 244280297Sjkim} 24555714Skris 24655714Skrisint BIO_sock_error(int sock) 247280297Sjkim{ 248280297Sjkim int j, i; 249290207Sjkim union { 250290207Sjkim size_t s; 251290207Sjkim int i; 252290207Sjkim } size; 25355714Skris 254280297Sjkim# if defined(OPENSSL_SYS_BEOS_R5) 255280297Sjkim return 0; 256280297Sjkim# endif 257280297Sjkim 258290207Sjkim /* heuristic way to adapt for platforms that expect 64-bit optlen */ 259290207Sjkim size.s = 0, size.i = sizeof(j); 260280297Sjkim /* 261280297Sjkim * Note: under Windows the third parameter is of type (char *) whereas 262280297Sjkim * under other systems it is (void *) if you don't have a cast it will 263280297Sjkim * choke the compiler: if you do have a cast then you can either go for 264280297Sjkim * (char *) or (void *). 265280297Sjkim */ 266280297Sjkim i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, (void *)&size); 267280297Sjkim if (i < 0) 268280297Sjkim return (1); 269280297Sjkim else 270280297Sjkim return (j); 271280297Sjkim} 272280297Sjkim 273280297Sjkim# if 0 27455714Skrislong BIO_ghbn_ctrl(int cmd, int iarg, char *parg) 275280297Sjkim{ 276280297Sjkim int i; 277280297Sjkim char **p; 27855714Skris 279280297Sjkim switch (cmd) { 280280297Sjkim case BIO_GHBN_CTRL_HITS: 281280297Sjkim return (BIO_ghbn_hits); 282280297Sjkim /* break; */ 283280297Sjkim case BIO_GHBN_CTRL_MISSES: 284280297Sjkim return (BIO_ghbn_miss); 285280297Sjkim /* break; */ 286280297Sjkim case BIO_GHBN_CTRL_CACHE_SIZE: 287280297Sjkim return (GHBN_NUM); 288280297Sjkim /* break; */ 289280297Sjkim case BIO_GHBN_CTRL_GET_ENTRY: 290280297Sjkim if ((iarg >= 0) && (iarg < GHBN_NUM) && (ghbn_cache[iarg].order > 0)) { 291280297Sjkim p = (char **)parg; 292280297Sjkim if (p == NULL) 293280297Sjkim return (0); 294280297Sjkim *p = ghbn_cache[iarg].name; 295280297Sjkim ghbn_cache[iarg].name[128] = '\0'; 296280297Sjkim return (1); 297280297Sjkim } 298280297Sjkim return (0); 299280297Sjkim /* break; */ 300280297Sjkim case BIO_GHBN_CTRL_FLUSH: 301280297Sjkim for (i = 0; i < GHBN_NUM; i++) 302280297Sjkim ghbn_cache[i].order = 0; 303280297Sjkim break; 304280297Sjkim default: 305280297Sjkim return (0); 306280297Sjkim } 307280297Sjkim return (1); 308280297Sjkim} 309280297Sjkim# endif 31055714Skris 311280297Sjkim# if 0 31255714Skrisstatic struct hostent *ghbn_dup(struct hostent *a) 313280297Sjkim{ 314280297Sjkim struct hostent *ret; 315280297Sjkim int i, j; 31655714Skris 317280297Sjkim MemCheck_off(); 318280297Sjkim ret = (struct hostent *)OPENSSL_malloc(sizeof(struct hostent)); 319280297Sjkim if (ret == NULL) 320280297Sjkim return (NULL); 321280297Sjkim memset(ret, 0, sizeof(struct hostent)); 32255714Skris 323280297Sjkim for (i = 0; a->h_aliases[i] != NULL; i++) ; 324280297Sjkim i++; 325280297Sjkim ret->h_aliases = (char **)OPENSSL_malloc(i * sizeof(char *)); 326280297Sjkim if (ret->h_aliases == NULL) 327280297Sjkim goto err; 328280297Sjkim memset(ret->h_aliases, 0, i * sizeof(char *)); 32955714Skris 330280297Sjkim for (i = 0; a->h_addr_list[i] != NULL; i++) ; 331280297Sjkim i++; 332280297Sjkim ret->h_addr_list = (char **)OPENSSL_malloc(i * sizeof(char *)); 333280297Sjkim if (ret->h_addr_list == NULL) 334280297Sjkim goto err; 335280297Sjkim memset(ret->h_addr_list, 0, i * sizeof(char *)); 33655714Skris 337280297Sjkim j = strlen(a->h_name) + 1; 338280297Sjkim if ((ret->h_name = OPENSSL_malloc(j)) == NULL) 339280297Sjkim goto err; 340280297Sjkim memcpy((char *)ret->h_name, a->h_name, j); 341280297Sjkim for (i = 0; a->h_aliases[i] != NULL; i++) { 342280297Sjkim j = strlen(a->h_aliases[i]) + 1; 343280297Sjkim if ((ret->h_aliases[i] = OPENSSL_malloc(j)) == NULL) 344280297Sjkim goto err; 345280297Sjkim memcpy(ret->h_aliases[i], a->h_aliases[i], j); 346280297Sjkim } 347280297Sjkim ret->h_length = a->h_length; 348280297Sjkim ret->h_addrtype = a->h_addrtype; 349280297Sjkim for (i = 0; a->h_addr_list[i] != NULL; i++) { 350280297Sjkim if ((ret->h_addr_list[i] = OPENSSL_malloc(a->h_length)) == NULL) 351280297Sjkim goto err; 352280297Sjkim memcpy(ret->h_addr_list[i], a->h_addr_list[i], a->h_length); 353280297Sjkim } 354280297Sjkim if (0) { 355280297Sjkim err: 356280297Sjkim if (ret != NULL) 357280297Sjkim ghbn_free(ret); 358280297Sjkim ret = NULL; 359280297Sjkim } 360280297Sjkim MemCheck_on(); 361280297Sjkim return (ret); 362280297Sjkim} 36355714Skris 36455714Skrisstatic void ghbn_free(struct hostent *a) 365280297Sjkim{ 366280297Sjkim int i; 36755714Skris 368280297Sjkim if (a == NULL) 369280297Sjkim return; 37055714Skris 371280297Sjkim if (a->h_aliases != NULL) { 372280297Sjkim for (i = 0; a->h_aliases[i] != NULL; i++) 373280297Sjkim OPENSSL_free(a->h_aliases[i]); 374280297Sjkim OPENSSL_free(a->h_aliases); 375280297Sjkim } 376280297Sjkim if (a->h_addr_list != NULL) { 377280297Sjkim for (i = 0; a->h_addr_list[i] != NULL; i++) 378280297Sjkim OPENSSL_free(a->h_addr_list[i]); 379280297Sjkim OPENSSL_free(a->h_addr_list); 380280297Sjkim } 381280297Sjkim if (a->h_name != NULL) 382280297Sjkim OPENSSL_free(a->h_name); 383280297Sjkim OPENSSL_free(a); 384280297Sjkim} 385109998Smarkm 386280297Sjkim# endif 38755714Skris 38855714Skrisstruct hostent *BIO_gethostbyname(const char *name) 389280297Sjkim{ 390280297Sjkim# if 1 391280297Sjkim /* 392280297Sjkim * Caching gethostbyname() results forever is wrong, so we have to let 393280297Sjkim * the true gethostbyname() worry about this 394280297Sjkim */ 395280297Sjkim# if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__)) 396280297Sjkim return gethostbyname((char *)name); 397280297Sjkim# else 398280297Sjkim return gethostbyname(name); 399280297Sjkim# endif 400280297Sjkim# else 401280297Sjkim struct hostent *ret; 402280297Sjkim int i, lowi = 0, j; 403280297Sjkim unsigned long low = (unsigned long)-1; 40455714Skris 40589837Skris# if 0 406280297Sjkim /* 407280297Sjkim * It doesn't make sense to use locking here: The function interface is 408280297Sjkim * not thread-safe, because threads can never be sure when some other 409280297Sjkim * thread destroys the data they were given a pointer to. 410280297Sjkim */ 411280297Sjkim CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME); 41289837Skris# endif 413280297Sjkim j = strlen(name); 414280297Sjkim if (j < 128) { 415280297Sjkim for (i = 0; i < GHBN_NUM; i++) { 416280297Sjkim if (low > ghbn_cache[i].order) { 417280297Sjkim low = ghbn_cache[i].order; 418280297Sjkim lowi = i; 419280297Sjkim } 420280297Sjkim if (ghbn_cache[i].order > 0) { 421280297Sjkim if (strncmp(name, ghbn_cache[i].name, 128) == 0) 422280297Sjkim break; 423280297Sjkim } 424280297Sjkim } 425280297Sjkim } else 426280297Sjkim i = GHBN_NUM; 42755714Skris 428280297Sjkim if (i == GHBN_NUM) { /* no hit */ 429280297Sjkim BIO_ghbn_miss++; 430280297Sjkim /* 431280297Sjkim * Note: under VMS with SOCKETSHR, it seems like the first parameter 432280297Sjkim * is 'char *', instead of 'const char *' 433280297Sjkim */ 43489837Skris# ifndef CONST_STRICT 435280297Sjkim ret = gethostbyname((char *)name); 436194206Ssimon# else 437280297Sjkim ret = gethostbyname(name); 43889837Skris# endif 43955714Skris 440280297Sjkim if (ret == NULL) 441280297Sjkim goto end; 442280297Sjkim if (j > 128) { /* too big to cache */ 44389837Skris# if 0 444280297Sjkim /* 445280297Sjkim * If we were trying to make this function thread-safe (which is 446280297Sjkim * bound to fail), we'd have to give up in this case (or allocate 447280297Sjkim * more memory). 448280297Sjkim */ 449280297Sjkim ret = NULL; 45089837Skris# endif 451280297Sjkim goto end; 452280297Sjkim } 45355714Skris 454280297Sjkim /* else add to cache */ 455280297Sjkim if (ghbn_cache[lowi].ent != NULL) 456280297Sjkim ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */ 457280297Sjkim ghbn_cache[lowi].name[0] = '\0'; 45855714Skris 459280297Sjkim if ((ret = ghbn_cache[lowi].ent = ghbn_dup(ret)) == NULL) { 460280297Sjkim BIOerr(BIO_F_BIO_GETHOSTBYNAME, ERR_R_MALLOC_FAILURE); 461280297Sjkim goto end; 462280297Sjkim } 463280297Sjkim strncpy(ghbn_cache[lowi].name, name, 128); 464280297Sjkim ghbn_cache[lowi].order = BIO_ghbn_miss + BIO_ghbn_hits; 465280297Sjkim } else { 466280297Sjkim BIO_ghbn_hits++; 467280297Sjkim ret = ghbn_cache[i].ent; 468280297Sjkim ghbn_cache[i].order = BIO_ghbn_miss + BIO_ghbn_hits; 469280297Sjkim } 470280297Sjkim end: 47189837Skris# if 0 472280297Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME); 47389837Skris# endif 474280297Sjkim return (ret); 475280297Sjkim# endif 476280297Sjkim} 47755714Skris 47855714Skrisint BIO_sock_init(void) 479280297Sjkim{ 480280297Sjkim# ifdef OPENSSL_SYS_WINDOWS 481280297Sjkim static struct WSAData wsa_state; 48255714Skris 483280297Sjkim if (!wsa_init_done) { 484280297Sjkim int err; 485160814Ssimon 486280297Sjkim wsa_init_done = 1; 487280297Sjkim memset(&wsa_state, 0, sizeof(wsa_state)); 488280297Sjkim /* 489280297Sjkim * Not making wsa_state available to the rest of the code is formally 490280297Sjkim * wrong. But the structures we use are [beleived to be] invariable 491280297Sjkim * among Winsock DLLs, while API availability is [expected to be] 492280297Sjkim * probed at run-time with DSO_global_lookup. 493280297Sjkim */ 494280297Sjkim if (WSAStartup(0x0202, &wsa_state) != 0) { 495280297Sjkim err = WSAGetLastError(); 496280297Sjkim SYSerr(SYS_F_WSASTARTUP, err); 497280297Sjkim BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); 498280297Sjkim return (-1); 499280297Sjkim } 500280297Sjkim } 501280297Sjkim# endif /* OPENSSL_SYS_WINDOWS */ 502280297Sjkim# ifdef WATT32 503280297Sjkim extern int _watt_do_exit; 504280297Sjkim _watt_do_exit = 0; /* don't make sock_init() call exit() */ 505280297Sjkim if (sock_init()) 506280297Sjkim return (-1); 507280297Sjkim# endif 508280297Sjkim 509280297Sjkim# if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 510160814Ssimon WORD wVerReq; 511160814Ssimon WSADATA wsaData; 512160814Ssimon int err; 513160814Ssimon 514280297Sjkim if (!wsa_init_done) { 515280297Sjkim wsa_init_done = 1; 516280297Sjkim wVerReq = MAKEWORD(2, 0); 517280297Sjkim err = WSAStartup(wVerReq, &wsaData); 518280297Sjkim if (err != 0) { 519280297Sjkim SYSerr(SYS_F_WSASTARTUP, err); 520280297Sjkim BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP); 521280297Sjkim return (-1); 522280297Sjkim } 523280297Sjkim } 524280297Sjkim# endif 525160814Ssimon 526280297Sjkim return (1); 527280297Sjkim} 52855714Skris 52955714Skrisvoid BIO_sock_cleanup(void) 530280297Sjkim{ 531280297Sjkim# ifdef OPENSSL_SYS_WINDOWS 532280297Sjkim if (wsa_init_done) { 533280297Sjkim wsa_init_done = 0; 534280297Sjkim# if 0 /* this call is claimed to be non-present in 535280297Sjkim * Winsock2 */ 536280297Sjkim WSACancelBlockingCall(); 537280297Sjkim# endif 538160814Ssimon WSACleanup(); 539280297Sjkim } 540280297Sjkim# elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK) 541280297Sjkim if (wsa_init_done) { 542280297Sjkim wsa_init_done = 0; 543280297Sjkim WSACleanup(); 544280297Sjkim } 545280297Sjkim# endif 546280297Sjkim} 54755714Skris 548280297Sjkim# if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000 54955714Skris 550111147Snectarint BIO_socket_ioctl(int fd, long type, void *arg) 551280297Sjkim{ 552280297Sjkim int i; 55355714Skris 554280297Sjkim# ifdef __DJGPP__ 555280297Sjkim i = ioctlsocket(fd, type, (char *)arg); 556280297Sjkim# else 557280297Sjkim# if defined(OPENSSL_SYS_VMS) 558280297Sjkim /*- 559280297Sjkim * 2011-02-18 SMS. 560280297Sjkim * VMS ioctl() can't tolerate a 64-bit "void *arg", but we 561280297Sjkim * observe that all the consumers pass in an "unsigned long *", 562280297Sjkim * so we arrange a local copy with a short pointer, and use 563280297Sjkim * that, instead. 564280297Sjkim */ 565280297Sjkim# if __INITIAL_POINTER_SIZE == 64 566280297Sjkim# define ARG arg_32p 567280297Sjkim# pragma pointer_size save 568280297Sjkim# pragma pointer_size 32 569280297Sjkim unsigned long arg_32; 570280297Sjkim unsigned long *arg_32p; 571280297Sjkim# pragma pointer_size restore 572280297Sjkim arg_32p = &arg_32; 573280297Sjkim arg_32 = *((unsigned long *)arg); 574280297Sjkim# else /* __INITIAL_POINTER_SIZE == 64 */ 575280297Sjkim# define ARG arg 576280297Sjkim# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ 577280297Sjkim# else /* defined(OPENSSL_SYS_VMS) */ 578280297Sjkim# define ARG arg 579280297Sjkim# endif /* defined(OPENSSL_SYS_VMS) [else] */ 580238405Sjkim 581280297Sjkim i = ioctlsocket(fd, type, ARG); 582280297Sjkim# endif /* __DJGPP__ */ 583280297Sjkim if (i < 0) 584280297Sjkim SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error()); 585280297Sjkim return (i); 586280297Sjkim} 587280297Sjkim# endif /* __VMS_VER */ 58855714Skris 589280297Sjkim/* 590280297Sjkim * The reason I have implemented this instead of using sscanf is because 591280297Sjkim * Visual C 1.52c gives an unresolved external when linking a DLL :-( 592280297Sjkim */ 59355714Skrisstatic int get_ip(const char *str, unsigned char ip[4]) 594280297Sjkim{ 595280297Sjkim unsigned int tmp[4]; 596280297Sjkim int num = 0, c, ok = 0; 59755714Skris 598280297Sjkim tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; 59955714Skris 600280297Sjkim for (;;) { 601280297Sjkim c = *(str++); 602280297Sjkim if ((c >= '0') && (c <= '9')) { 603280297Sjkim ok = 1; 604280297Sjkim tmp[num] = tmp[num] * 10 + c - '0'; 605280297Sjkim if (tmp[num] > 255) 606280297Sjkim return (0); 607280297Sjkim } else if (c == '.') { 608280297Sjkim if (!ok) 609280297Sjkim return (-1); 610280297Sjkim if (num == 3) 611280297Sjkim return (0); 612280297Sjkim num++; 613280297Sjkim ok = 0; 614280297Sjkim } else if (c == '\0' && (num == 3) && ok) 615280297Sjkim break; 616280297Sjkim else 617280297Sjkim return (0); 618280297Sjkim } 619280297Sjkim ip[0] = tmp[0]; 620280297Sjkim ip[1] = tmp[1]; 621280297Sjkim ip[2] = tmp[2]; 622280297Sjkim ip[3] = tmp[3]; 623280297Sjkim return (1); 624280297Sjkim} 62555714Skris 62655714Skrisint BIO_get_accept_socket(char *host, int bind_mode) 627280297Sjkim{ 628280297Sjkim int ret = 0; 629280297Sjkim union { 630280297Sjkim struct sockaddr sa; 631280297Sjkim struct sockaddr_in sa_in; 632280297Sjkim# if OPENSSL_USE_IPV6 633280297Sjkim struct sockaddr_in6 sa_in6; 634280297Sjkim# endif 635280297Sjkim } server, client; 636280297Sjkim int s = INVALID_SOCKET, cs, addrlen; 637280297Sjkim unsigned char ip[4]; 638280297Sjkim unsigned short port; 639280297Sjkim char *str = NULL, *e; 640280297Sjkim char *h, *p; 641280297Sjkim unsigned long l; 642280297Sjkim int err_num; 64355714Skris 644280297Sjkim if (BIO_sock_init() != 1) 645280297Sjkim return (INVALID_SOCKET); 64655714Skris 647280297Sjkim if ((str = BUF_strdup(host)) == NULL) 648280297Sjkim return (INVALID_SOCKET); 64955714Skris 650280297Sjkim h = p = NULL; 651280297Sjkim h = str; 652280297Sjkim for (e = str; *e; e++) { 653280297Sjkim if (*e == ':') { 654280297Sjkim p = e; 655280297Sjkim } else if (*e == '/') { 656280297Sjkim *e = '\0'; 657280297Sjkim break; 658280297Sjkim } 659280297Sjkim } 660280297Sjkim if (p) 661280297Sjkim *p++ = '\0'; /* points at last ':', '::port' is special 662280297Sjkim * [see below] */ 663280297Sjkim else 664280297Sjkim p = h, h = NULL; 66555714Skris 666280297Sjkim# ifdef EAI_FAMILY 667280297Sjkim do { 668280297Sjkim static union { 669280297Sjkim void *p; 670280297Sjkim int (WSAAPI *f) (const char *, const char *, 671280297Sjkim const struct addrinfo *, struct addrinfo **); 672280297Sjkim } p_getaddrinfo = { 673280297Sjkim NULL 674280297Sjkim }; 675280297Sjkim static union { 676280297Sjkim void *p; 677280297Sjkim void (WSAAPI *f) (struct addrinfo *); 678280297Sjkim } p_freeaddrinfo = { 679280297Sjkim NULL 680280297Sjkim }; 681280297Sjkim struct addrinfo *res, hint; 682238405Sjkim 683280297Sjkim if (p_getaddrinfo.p == NULL) { 684280297Sjkim if ((p_getaddrinfo.p = DSO_global_lookup("getaddrinfo")) == NULL 685280297Sjkim || (p_freeaddrinfo.p = 686280297Sjkim DSO_global_lookup("freeaddrinfo")) == NULL) 687280297Sjkim p_getaddrinfo.p = (void *)-1; 688280297Sjkim } 689280297Sjkim if (p_getaddrinfo.p == (void *)-1) 690280297Sjkim break; 69155714Skris 692280297Sjkim /* 693280297Sjkim * '::port' enforces IPv6 wildcard listener. Some OSes, e.g. Solaris, 694280297Sjkim * default to IPv6 without any hint. Also note that commonly IPv6 695280297Sjkim * wildchard socket can service IPv4 connections just as well... 696280297Sjkim */ 697280297Sjkim memset(&hint, 0, sizeof(hint)); 698280297Sjkim hint.ai_flags = AI_PASSIVE; 699280297Sjkim if (h) { 700280297Sjkim if (strchr(h, ':')) { 701280297Sjkim if (h[1] == '\0') 702280297Sjkim h = NULL; 703280297Sjkim# if OPENSSL_USE_IPV6 704280297Sjkim hint.ai_family = AF_INET6; 705280297Sjkim# else 706280297Sjkim h = NULL; 707280297Sjkim# endif 708280297Sjkim } else if (h[0] == '*' && h[1] == '\0') { 709280297Sjkim hint.ai_family = AF_INET; 710280297Sjkim h = NULL; 711280297Sjkim } 712280297Sjkim } 713238405Sjkim 714280297Sjkim if ((*p_getaddrinfo.f) (h, p, &hint, &res)) 715280297Sjkim break; 716238405Sjkim 717280297Sjkim addrlen = res->ai_addrlen <= sizeof(server) ? 718280297Sjkim res->ai_addrlen : sizeof(server); 719280297Sjkim memcpy(&server, res->ai_addr, addrlen); 720238405Sjkim 721280297Sjkim (*p_freeaddrinfo.f) (res); 722280297Sjkim goto again; 723280297Sjkim } while (0); 724280297Sjkim# endif 725238405Sjkim 726280297Sjkim if (!BIO_get_port(p, &port)) 727280297Sjkim goto err; 72855714Skris 729280297Sjkim memset((char *)&server, 0, sizeof(server)); 730280297Sjkim server.sa_in.sin_family = AF_INET; 731280297Sjkim server.sa_in.sin_port = htons(port); 732280297Sjkim addrlen = sizeof(server.sa_in); 73355714Skris 734280297Sjkim if (h == NULL || strcmp(h, "*") == 0) 735280297Sjkim server.sa_in.sin_addr.s_addr = INADDR_ANY; 736280297Sjkim else { 737280297Sjkim if (!BIO_get_host_ip(h, &(ip[0]))) 738280297Sjkim goto err; 739280297Sjkim l = (unsigned long) 740280297Sjkim ((unsigned long)ip[0] << 24L) | 741280297Sjkim ((unsigned long)ip[1] << 16L) | 742280297Sjkim ((unsigned long)ip[2] << 8L) | ((unsigned long)ip[3]); 743280297Sjkim server.sa_in.sin_addr.s_addr = htonl(l); 744280297Sjkim } 74555714Skris 746280297Sjkim again: 747280297Sjkim s = socket(server.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL); 748280297Sjkim if (s == INVALID_SOCKET) { 749280297Sjkim SYSerr(SYS_F_SOCKET, get_last_socket_error()); 750280297Sjkim ERR_add_error_data(3, "port='", host, "'"); 751280297Sjkim BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET); 752280297Sjkim goto err; 753280297Sjkim } 754280297Sjkim# ifdef SO_REUSEADDR 755280297Sjkim if (bind_mode == BIO_BIND_REUSEADDR) { 756280297Sjkim int i = 1; 75755714Skris 758280297Sjkim ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i)); 759280297Sjkim bind_mode = BIO_BIND_NORMAL; 760280297Sjkim } 761280297Sjkim# endif 762280297Sjkim if (bind(s, &server.sa, addrlen) == -1) { 763280297Sjkim# ifdef SO_REUSEADDR 764280297Sjkim err_num = get_last_socket_error(); 765280297Sjkim if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) && 766280297Sjkim# ifdef OPENSSL_SYS_WINDOWS 767280297Sjkim /* 768280297Sjkim * Some versions of Windows define EADDRINUSE to a dummy value. 769280297Sjkim */ 770280297Sjkim (err_num == WSAEADDRINUSE)) 771280297Sjkim# else 772280297Sjkim (err_num == EADDRINUSE)) 773280297Sjkim# endif 774280297Sjkim { 775280297Sjkim client = server; 776280297Sjkim if (h == NULL || strcmp(h, "*") == 0) { 777280297Sjkim# if OPENSSL_USE_IPV6 778280297Sjkim if (client.sa.sa_family == AF_INET6) { 779280297Sjkim memset(&client.sa_in6.sin6_addr, 0, 780280297Sjkim sizeof(client.sa_in6.sin6_addr)); 781280297Sjkim client.sa_in6.sin6_addr.s6_addr[15] = 1; 782280297Sjkim } else 783280297Sjkim# endif 784280297Sjkim if (client.sa.sa_family == AF_INET) { 785280297Sjkim client.sa_in.sin_addr.s_addr = htonl(0x7F000001); 786280297Sjkim } else 787280297Sjkim goto err; 788280297Sjkim } 789280297Sjkim cs = socket(client.sa.sa_family, SOCK_STREAM, SOCKET_PROTOCOL); 790280297Sjkim if (cs != INVALID_SOCKET) { 791280297Sjkim int ii; 792280297Sjkim ii = connect(cs, &client.sa, addrlen); 793280297Sjkim closesocket(cs); 794280297Sjkim if (ii == INVALID_SOCKET) { 795280297Sjkim bind_mode = BIO_BIND_REUSEADDR; 796280297Sjkim closesocket(s); 797280297Sjkim goto again; 798280297Sjkim } 799280297Sjkim /* else error */ 800280297Sjkim } 801280297Sjkim /* else error */ 802280297Sjkim } 803280297Sjkim# endif 804280297Sjkim SYSerr(SYS_F_BIND, err_num); 805280297Sjkim ERR_add_error_data(3, "port='", host, "'"); 806280297Sjkim BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_BIND_SOCKET); 807280297Sjkim goto err; 808280297Sjkim } 809280297Sjkim if (listen(s, MAX_LISTEN) == -1) { 810280297Sjkim SYSerr(SYS_F_BIND, get_last_socket_error()); 811280297Sjkim ERR_add_error_data(3, "port='", host, "'"); 812280297Sjkim BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET, BIO_R_UNABLE_TO_LISTEN_SOCKET); 813280297Sjkim goto err; 814280297Sjkim } 815280297Sjkim ret = 1; 816280297Sjkim err: 817280297Sjkim if (str != NULL) 818280297Sjkim OPENSSL_free(str); 819280297Sjkim if ((ret == 0) && (s != INVALID_SOCKET)) { 820280297Sjkim closesocket(s); 821280297Sjkim s = INVALID_SOCKET; 822280297Sjkim } 823280297Sjkim return (s); 824280297Sjkim} 82555714Skris 82655714Skrisint BIO_accept(int sock, char **addr) 827280297Sjkim{ 828280297Sjkim int ret = INVALID_SOCKET; 829280297Sjkim unsigned long l; 830280297Sjkim unsigned short port; 831280297Sjkim char *p; 83255714Skris 833280297Sjkim struct { 834280297Sjkim /* 835280297Sjkim * As for following union. Trouble is that there are platforms 836280297Sjkim * that have socklen_t and there are platforms that don't, on 837280297Sjkim * some platforms socklen_t is int and on some size_t. So what 838280297Sjkim * one can do? One can cook #ifdef spaghetti, which is nothing 839280297Sjkim * but masochistic. Or one can do union between int and size_t. 840280297Sjkim * One naturally does it primarily for 64-bit platforms where 841280297Sjkim * sizeof(int) != sizeof(size_t). But would it work? Note that 842280297Sjkim * if size_t member is initialized to 0, then later int member 843280297Sjkim * assignment naturally does the job on little-endian platforms 844280297Sjkim * regardless accept's expectations! What about big-endians? 845280297Sjkim * If accept expects int*, then it works, and if size_t*, then 846280297Sjkim * length value would appear as unreasonably large. But this 847280297Sjkim * won't prevent it from filling in the address structure. The 848280297Sjkim * trouble of course would be if accept returns more data than 849280297Sjkim * actual buffer can accomodate and overwrite stack... That's 850280297Sjkim * where early OPENSSL_assert comes into picture. Besides, the 851280297Sjkim * only 64-bit big-endian platform found so far that expects 852280297Sjkim * size_t* is HP-UX, where stack grows towards higher address. 853280297Sjkim * <appro> 854280297Sjkim */ 855280297Sjkim union { 856280297Sjkim size_t s; 857280297Sjkim int i; 858280297Sjkim } len; 859280297Sjkim union { 860280297Sjkim struct sockaddr sa; 861280297Sjkim struct sockaddr_in sa_in; 862280297Sjkim# if OPENSSL_USE_IPV6 863280297Sjkim struct sockaddr_in6 sa_in6; 864280297Sjkim# endif 865280297Sjkim } from; 866280297Sjkim } sa; 867238405Sjkim 868280297Sjkim sa.len.s = 0; 869280297Sjkim sa.len.i = sizeof(sa.from); 870280297Sjkim memset(&sa.from, 0, sizeof(sa.from)); 871280297Sjkim ret = accept(sock, &sa.from.sa, (void *)&sa.len); 872280297Sjkim if (sizeof(sa.len.i) != sizeof(sa.len.s) && sa.len.i == 0) { 873280297Sjkim OPENSSL_assert(sa.len.s <= sizeof(sa.from)); 874280297Sjkim sa.len.i = (int)sa.len.s; 875280297Sjkim /* use sa.len.i from this point */ 876280297Sjkim } 877280297Sjkim if (ret == INVALID_SOCKET) { 878280297Sjkim if (BIO_sock_should_retry(ret)) 879280297Sjkim return -2; 880280297Sjkim SYSerr(SYS_F_ACCEPT, get_last_socket_error()); 881280297Sjkim BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR); 882280297Sjkim goto end; 883280297Sjkim } 88455714Skris 885280297Sjkim if (addr == NULL) 886280297Sjkim goto end; 88755714Skris 888280297Sjkim# ifdef EAI_FAMILY 889280297Sjkim do { 890280297Sjkim char h[NI_MAXHOST], s[NI_MAXSERV]; 891280297Sjkim size_t nl; 892280297Sjkim static union { 893280297Sjkim void *p; 894280297Sjkim int (WSAAPI *f) (const struct sockaddr *, size_t /* socklen_t */ , 895280297Sjkim char *, size_t, char *, size_t, int); 896280297Sjkim } p_getnameinfo = { 897280297Sjkim NULL 898280297Sjkim }; 899280297Sjkim /* 900280297Sjkim * 2nd argument to getnameinfo is specified to be socklen_t. 901280297Sjkim * Unfortunately there is a number of environments where socklen_t is 902280297Sjkim * not defined. As it's passed by value, it's safe to pass it as 903280297Sjkim * size_t... <appro> 904280297Sjkim */ 905238405Sjkim 906280297Sjkim if (p_getnameinfo.p == NULL) { 907280297Sjkim if ((p_getnameinfo.p = DSO_global_lookup("getnameinfo")) == NULL) 908280297Sjkim p_getnameinfo.p = (void *)-1; 909280297Sjkim } 910280297Sjkim if (p_getnameinfo.p == (void *)-1) 911280297Sjkim break; 912238405Sjkim 913280297Sjkim if ((*p_getnameinfo.f) (&sa.from.sa, sa.len.i, h, sizeof(h), s, 914280297Sjkim sizeof(s), NI_NUMERICHOST | NI_NUMERICSERV)) 915280297Sjkim break; 916280297Sjkim nl = strlen(h) + strlen(s) + 2; 917280297Sjkim p = *addr; 918280297Sjkim if (p) { 919280297Sjkim *p = '\0'; 920280297Sjkim p = OPENSSL_realloc(p, nl); 921280297Sjkim } else { 922280297Sjkim p = OPENSSL_malloc(nl); 923280297Sjkim } 924280297Sjkim if (p == NULL) { 925280297Sjkim BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); 926280297Sjkim goto end; 927280297Sjkim } 928280297Sjkim *addr = p; 929280297Sjkim BIO_snprintf(*addr, nl, "%s:%s", h, s); 930280297Sjkim goto end; 931280297Sjkim } while (0); 932280297Sjkim# endif 933280297Sjkim if (sa.from.sa.sa_family != AF_INET) 934280297Sjkim goto end; 935280297Sjkim l = ntohl(sa.from.sa_in.sin_addr.s_addr); 936280297Sjkim port = ntohs(sa.from.sa_in.sin_port); 937280297Sjkim if (*addr == NULL) { 938280297Sjkim if ((p = OPENSSL_malloc(24)) == NULL) { 939280297Sjkim BIOerr(BIO_F_BIO_ACCEPT, ERR_R_MALLOC_FAILURE); 940280297Sjkim goto end; 941280297Sjkim } 942280297Sjkim *addr = p; 943280297Sjkim } 944280297Sjkim BIO_snprintf(*addr, 24, "%d.%d.%d.%d:%d", 945280297Sjkim (unsigned char)(l >> 24L) & 0xff, 946280297Sjkim (unsigned char)(l >> 16L) & 0xff, 947280297Sjkim (unsigned char)(l >> 8L) & 0xff, 948280297Sjkim (unsigned char)(l) & 0xff, port); 949280297Sjkim end: 950280297Sjkim return (ret); 951280297Sjkim} 95255714Skris 95355714Skrisint BIO_set_tcp_ndelay(int s, int on) 954280297Sjkim{ 955280297Sjkim int ret = 0; 956280297Sjkim# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP)) 957280297Sjkim int opt; 95855714Skris 959280297Sjkim# ifdef SOL_TCP 960280297Sjkim opt = SOL_TCP; 961280297Sjkim# else 962280297Sjkim# ifdef IPPROTO_TCP 963280297Sjkim opt = IPPROTO_TCP; 964280297Sjkim# endif 965280297Sjkim# endif 96655714Skris 967280297Sjkim ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on)); 968280297Sjkim# endif 969280297Sjkim return (ret == 0); 970280297Sjkim} 971280297Sjkim 97255714Skrisint BIO_socket_nbio(int s, int mode) 973280297Sjkim{ 974280297Sjkim int ret = -1; 975280297Sjkim int l; 97655714Skris 977280297Sjkim l = mode; 978280297Sjkim# ifdef FIONBIO 979280297Sjkim ret = BIO_socket_ioctl(s, FIONBIO, &l); 980280297Sjkim# endif 981280297Sjkim return (ret == 0); 982280297Sjkim} 98355714Skris#endif 984