1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/bio/b_sock.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,796 @@
1.4 +/* crypto/bio/b_sock.c */
1.5 +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
1.6 + * All rights reserved.
1.7 + *
1.8 + * This package is an SSL implementation written
1.9 + * by Eric Young (eay@cryptsoft.com).
1.10 + * The implementation was written so as to conform with Netscapes SSL.
1.11 + *
1.12 + * This library is free for commercial and non-commercial use as long as
1.13 + * the following conditions are aheared to. The following conditions
1.14 + * apply to all code found in this distribution, be it the RC4, RSA,
1.15 + * lhash, DES, etc., code; not just the SSL code. The SSL documentation
1.16 + * included with this distribution is covered by the same copyright terms
1.17 + * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1.18 + *
1.19 + * Copyright remains Eric Young's, and as such any Copyright notices in
1.20 + * the code are not to be removed.
1.21 + * If this package is used in a product, Eric Young should be given attribution
1.22 + * as the author of the parts of the library used.
1.23 + * This can be in the form of a textual message at program startup or
1.24 + * in documentation (online or textual) provided with the package.
1.25 + *
1.26 + * Redistribution and use in source and binary forms, with or without
1.27 + * modification, are permitted provided that the following conditions
1.28 + * are met:
1.29 + * 1. Redistributions of source code must retain the copyright
1.30 + * notice, this list of conditions and the following disclaimer.
1.31 + * 2. Redistributions in binary form must reproduce the above copyright
1.32 + * notice, this list of conditions and the following disclaimer in the
1.33 + * documentation and/or other materials provided with the distribution.
1.34 + * 3. All advertising materials mentioning features or use of this software
1.35 + * must display the following acknowledgement:
1.36 + * "This product includes cryptographic software written by
1.37 + * Eric Young (eay@cryptsoft.com)"
1.38 + * The word 'cryptographic' can be left out if the rouines from the library
1.39 + * being used are not cryptographic related :-).
1.40 + * 4. If you include any Windows specific code (or a derivative thereof) from
1.41 + * the apps directory (application code) you must include an acknowledgement:
1.42 + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
1.43 + *
1.44 + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
1.45 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.46 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.47 + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1.48 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1.49 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1.50 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.51 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1.52 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1.53 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1.54 + * SUCH DAMAGE.
1.55 + *
1.56 + * The licence and distribution terms for any publically available version or
1.57 + * derivative of this code cannot be changed. i.e. this code cannot simply be
1.58 + * copied and put under another distribution licence
1.59 + * [including the GNU Public Licence.]
1.60 + */
1.61 +
1.62 +/*
1.63 + © Portions copyright (c) 2006 Nokia Corporation. All rights reserved.
1.64 + */
1.65 +
1.66 +
1.67 +#include <stdio.h>
1.68 +#include <stdlib.h>
1.69 +#include <errno.h>
1.70 +#define USE_SOCKETS
1.71 +#include "cryptlib.h"
1.72 +#include <openssl/bio.h>
1.73 +#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
1.74 +#include "netdb.h"
1.75 +#endif
1.76 +#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
1.77 +#include "libcrypto_wsd_macros.h"
1.78 +#include "libcrypto_wsd.h"
1.79 +#endif
1.80 +
1.81 +
1.82 +#ifndef OPENSSL_NO_SOCK
1.83 +
1.84 +#ifdef OPENSSL_SYS_WIN16
1.85 +#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
1.86 +#else
1.87 +#define SOCKET_PROTOCOL IPPROTO_TCP
1.88 +#endif
1.89 +
1.90 +#ifdef SO_MAXCONN
1.91 +#define MAX_LISTEN SO_MAXCONN
1.92 +#elif defined(SOMAXCONN)
1.93 +#define MAX_LISTEN SOMAXCONN
1.94 +#else
1.95 +#define MAX_LISTEN 32
1.96 +#endif
1.97 +
1.98 +#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
1.99 +static int wsa_init_done=0;
1.100 +#endif
1.101 +
1.102 +#if 0
1.103 +static unsigned long BIO_ghbn_hits=0L;
1.104 +static unsigned long BIO_ghbn_miss=0L;
1.105 +
1.106 +#define GHBN_NUM 4
1.107 +static struct ghbn_cache_st
1.108 + {
1.109 + char name[129];
1.110 + struct hostent *ent;
1.111 + unsigned long order;
1.112 + } ghbn_cache[GHBN_NUM];
1.113 +#endif
1.114 +
1.115 +static int get_ip(const char *str,unsigned char *ip);
1.116 +#if 0
1.117 +static void ghbn_free(struct hostent *a);
1.118 +static struct hostent *ghbn_dup(struct hostent *a);
1.119 +#endif
1.120 +EXPORT_C int BIO_get_host_ip(const char *str, unsigned char *ip)
1.121 + {
1.122 + int i;
1.123 + int err = 1;
1.124 + int locked = 0;
1.125 + struct hostent *he;
1.126 +
1.127 + i=get_ip(str,ip);
1.128 + if (i < 0)
1.129 + {
1.130 + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
1.131 + goto err;
1.132 + }
1.133 +
1.134 + /* At this point, we have something that is most probably correct
1.135 + in some way, so let's init the socket. */
1.136 + if (BIO_sock_init() != 1)
1.137 + return 0; /* don't generate another error code here */
1.138 +
1.139 + /* If the string actually contained an IP address, we need not do
1.140 + anything more */
1.141 + if (i > 0) return(1);
1.142 +
1.143 + /* do a gethostbyname */
1.144 + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
1.145 + locked = 1;
1.146 + he=BIO_gethostbyname(str);
1.147 + if (he == NULL)
1.148 + {
1.149 + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
1.150 + goto err;
1.151 + }
1.152 +
1.153 + /* cast to short because of win16 winsock definition */
1.154 + if ((short)he->h_addrtype != AF_INET)
1.155 + {
1.156 + BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
1.157 + goto err;
1.158 + }
1.159 + for (i=0; i<4; i++)
1.160 + ip[i]=he->h_addr_list[0][i];
1.161 + err = 0;
1.162 +
1.163 + err:
1.164 + if (locked)
1.165 + CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
1.166 + if (err)
1.167 + {
1.168 + ERR_add_error_data(2,"host=",str);
1.169 + return 0;
1.170 + }
1.171 + else
1.172 + return 1;
1.173 + }
1.174 +
1.175 +EXPORT_C int BIO_get_port(const char *str, unsigned short *port_ptr)
1.176 + {
1.177 + int i;
1.178 + struct servent *s;
1.179 +
1.180 + if (str == NULL)
1.181 + {
1.182 + BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
1.183 + return(0);
1.184 + }
1.185 + i=atoi(str);
1.186 + if (i != 0)
1.187 + *port_ptr=(unsigned short)i;
1.188 + else
1.189 + {
1.190 + CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
1.191 + /* Note: under VMS with SOCKETSHR, it seems like the first
1.192 + * parameter is 'char *', instead of 'const char *'
1.193 + */
1.194 + s=getservbyname(
1.195 +#ifndef CONST_STRICT
1.196 + (char *)
1.197 +#endif
1.198 + str,"tcp");
1.199 + if(s != NULL)
1.200 + *port_ptr=ntohs((unsigned short)s->s_port);
1.201 + CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
1.202 + if(s == NULL)
1.203 + {
1.204 + if (strcmp(str,"http") == 0)
1.205 + *port_ptr=80;
1.206 + else if (strcmp(str,"telnet") == 0)
1.207 + *port_ptr=23;
1.208 + else if (strcmp(str,"socks") == 0)
1.209 + *port_ptr=1080;
1.210 + else if (strcmp(str,"https") == 0)
1.211 + *port_ptr=443;
1.212 + else if (strcmp(str,"ssl") == 0)
1.213 + *port_ptr=443;
1.214 + else if (strcmp(str,"ftp") == 0)
1.215 + *port_ptr=21;
1.216 + else if (strcmp(str,"gopher") == 0)
1.217 + *port_ptr=70;
1.218 +#if 0
1.219 + else if (strcmp(str,"wais") == 0)
1.220 + *port_ptr=21;
1.221 +#endif
1.222 + else
1.223 + {
1.224 + SYSerr(SYS_F_GETSERVBYNAME,get_last_socket_error());
1.225 + ERR_add_error_data(3,"service='",str,"'");
1.226 + return(0);
1.227 + }
1.228 + }
1.229 + }
1.230 + return(1);
1.231 + }
1.232 +
1.233 +EXPORT_C int BIO_sock_error(int sock)
1.234 + {
1.235 + int j,i;
1.236 + int size;
1.237 +
1.238 + size=sizeof(int);
1.239 + /* Note: under Windows the third parameter is of type (char *)
1.240 + * whereas under other systems it is (void *) if you don't have
1.241 + * a cast it will choke the compiler: if you do have a cast then
1.242 + * you can either go for (char *) or (void *).
1.243 + */
1.244 + i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(void *)&j,(void *)&size);
1.245 + if (i < 0)
1.246 + return(1);
1.247 + else
1.248 + return(j);
1.249 + }
1.250 +
1.251 +#if 0
1.252 +long BIO_ghbn_ctrl(int cmd, int iarg, char *parg)
1.253 + {
1.254 + int i;
1.255 + char **p;
1.256 +
1.257 + switch (cmd)
1.258 + {
1.259 + case BIO_GHBN_CTRL_HITS:
1.260 + return(BIO_ghbn_hits);
1.261 + /* break; */
1.262 + case BIO_GHBN_CTRL_MISSES:
1.263 + return(BIO_ghbn_miss);
1.264 + /* break; */
1.265 + case BIO_GHBN_CTRL_CACHE_SIZE:
1.266 + return(GHBN_NUM);
1.267 + /* break; */
1.268 + case BIO_GHBN_CTRL_GET_ENTRY:
1.269 + if ((iarg >= 0) && (iarg <GHBN_NUM) &&
1.270 + (ghbn_cache[iarg].order > 0))
1.271 + {
1.272 + p=(char **)parg;
1.273 + if (p == NULL) return(0);
1.274 + *p=ghbn_cache[iarg].name;
1.275 + ghbn_cache[iarg].name[128]='\0';
1.276 + return(1);
1.277 + }
1.278 + return(0);
1.279 + /* break; */
1.280 + case BIO_GHBN_CTRL_FLUSH:
1.281 + for (i=0; i<GHBN_NUM; i++)
1.282 + ghbn_cache[i].order=0;
1.283 + break;
1.284 + default:
1.285 + return(0);
1.286 + }
1.287 + return(1);
1.288 + }
1.289 +#endif
1.290 +
1.291 +#if 0
1.292 +static struct hostent *ghbn_dup(struct hostent *a)
1.293 + {
1.294 + struct hostent *ret;
1.295 + int i,j;
1.296 +
1.297 + MemCheck_off();
1.298 + ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent));
1.299 + if (ret == NULL) return(NULL);
1.300 + memset(ret,0,sizeof(struct hostent));
1.301 +
1.302 + for (i=0; a->h_aliases[i] != NULL; i++)
1.303 + ;
1.304 + i++;
1.305 + ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *));
1.306 + if (ret->h_aliases == NULL)
1.307 + goto err;
1.308 + memset(ret->h_aliases, 0, i*sizeof(char *));
1.309 +
1.310 + for (i=0; a->h_addr_list[i] != NULL; i++)
1.311 + ;
1.312 + i++;
1.313 + ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *));
1.314 + if (ret->h_addr_list == NULL)
1.315 + goto err;
1.316 + memset(ret->h_addr_list, 0, i*sizeof(char *));
1.317 +
1.318 + j=strlen(a->h_name)+1;
1.319 + if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err;
1.320 + memcpy((char *)ret->h_name,a->h_name,j);
1.321 + for (i=0; a->h_aliases[i] != NULL; i++)
1.322 + {
1.323 + j=strlen(a->h_aliases[i])+1;
1.324 + if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err;
1.325 + memcpy(ret->h_aliases[i],a->h_aliases[i],j);
1.326 + }
1.327 + ret->h_length=a->h_length;
1.328 + ret->h_addrtype=a->h_addrtype;
1.329 + for (i=0; a->h_addr_list[i] != NULL; i++)
1.330 + {
1.331 + if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL)
1.332 + goto err;
1.333 + memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
1.334 + }
1.335 + if (0)
1.336 + {
1.337 +err:
1.338 + if (ret != NULL)
1.339 + ghbn_free(ret);
1.340 + ret=NULL;
1.341 + }
1.342 + MemCheck_on();
1.343 + return(ret);
1.344 + }
1.345 +
1.346 +static void ghbn_free(struct hostent *a)
1.347 + {
1.348 + int i;
1.349 +
1.350 + if(a == NULL)
1.351 + return;
1.352 +
1.353 + if (a->h_aliases != NULL)
1.354 + {
1.355 + for (i=0; a->h_aliases[i] != NULL; i++)
1.356 + OPENSSL_free(a->h_aliases[i]);
1.357 + OPENSSL_free(a->h_aliases);
1.358 + }
1.359 + if (a->h_addr_list != NULL)
1.360 + {
1.361 + for (i=0; a->h_addr_list[i] != NULL; i++)
1.362 + OPENSSL_free(a->h_addr_list[i]);
1.363 + OPENSSL_free(a->h_addr_list);
1.364 + }
1.365 + if (a->h_name != NULL) OPENSSL_free(a->h_name);
1.366 + OPENSSL_free(a);
1.367 + }
1.368 +
1.369 +#endif
1.370 +
1.371 +EXPORT_C struct hostent *BIO_gethostbyname(const char *name)
1.372 + {
1.373 +#if 1
1.374 + /* Caching gethostbyname() results forever is wrong,
1.375 + * so we have to let the true gethostbyname() worry about this */
1.376 + return gethostbyname(name);
1.377 +#else
1.378 + struct hostent *ret;
1.379 + int i,lowi=0,j;
1.380 + unsigned long low= (unsigned long)-1;
1.381 +
1.382 +
1.383 +# if 0
1.384 + /* It doesn't make sense to use locking here: The function interface
1.385 + * is not thread-safe, because threads can never be sure when
1.386 + * some other thread destroys the data they were given a pointer to.
1.387 + */
1.388 + CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
1.389 +# endif
1.390 + j=strlen(name);
1.391 + if (j < 128)
1.392 + {
1.393 + for (i=0; i<GHBN_NUM; i++)
1.394 + {
1.395 + if (low > ghbn_cache[i].order)
1.396 + {
1.397 + low=ghbn_cache[i].order;
1.398 + lowi=i;
1.399 + }
1.400 + if (ghbn_cache[i].order > 0)
1.401 + {
1.402 + if (strncmp(name,ghbn_cache[i].name,128) == 0)
1.403 + break;
1.404 + }
1.405 + }
1.406 + }
1.407 + else
1.408 + i=GHBN_NUM;
1.409 +
1.410 + if (i == GHBN_NUM) /* no hit*/
1.411 + {
1.412 + BIO_ghbn_miss++;
1.413 + /* Note: under VMS with SOCKETSHR, it seems like the first
1.414 + * parameter is 'char *', instead of 'const char *'
1.415 + */
1.416 + ret=gethostbyname(
1.417 +# ifndef CONST_STRICT
1.418 + (char *)
1.419 +# endif
1.420 + name);
1.421 +
1.422 + if (ret == NULL)
1.423 + goto end;
1.424 + if (j > 128) /* too big to cache */
1.425 + {
1.426 +# if 0
1.427 + /* If we were trying to make this function thread-safe (which
1.428 + * is bound to fail), we'd have to give up in this case
1.429 + * (or allocate more memory). */
1.430 + ret = NULL;
1.431 +# endif
1.432 + goto end;
1.433 + }
1.434 +
1.435 + /* else add to cache */
1.436 + if (ghbn_cache[lowi].ent != NULL)
1.437 + ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */
1.438 + ghbn_cache[lowi].name[0] = '\0';
1.439 +
1.440 + if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
1.441 + {
1.442 + BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
1.443 + goto end;
1.444 + }
1.445 + strncpy(ghbn_cache[lowi].name,name,128);
1.446 + ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
1.447 + }
1.448 + else
1.449 + {
1.450 + BIO_ghbn_hits++;
1.451 + ret= ghbn_cache[i].ent;
1.452 + ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
1.453 + }
1.454 +end:
1.455 +# if 0
1.456 + CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
1.457 +# endif
1.458 + return(ret);
1.459 +#endif
1.460 + }
1.461 +
1.462 +
1.463 +EXPORT_C int BIO_sock_init(void)
1.464 + {
1.465 +#ifdef OPENSSL_SYS_WINDOWS
1.466 + static struct WSAData wsa_state;
1.467 +
1.468 + if (!wsa_init_done)
1.469 + {
1.470 + int err;
1.471 +
1.472 + wsa_init_done=1;
1.473 + memset(&wsa_state,0,sizeof(wsa_state));
1.474 + if (WSAStartup(0x0101,&wsa_state)!=0)
1.475 + {
1.476 + err=WSAGetLastError();
1.477 + SYSerr(SYS_F_WSASTARTUP,err);
1.478 + BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
1.479 + return(-1);
1.480 + }
1.481 + }
1.482 +#endif /* OPENSSL_SYS_WINDOWS */
1.483 +#ifdef WATT32
1.484 + extern int _watt_do_exit;
1.485 + _watt_do_exit = 0; /* don't make sock_init() call exit() */
1.486 + if (sock_init())
1.487 + return (-1);
1.488 +#endif
1.489 +
1.490 +#if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
1.491 + WORD wVerReq;
1.492 + WSADATA wsaData;
1.493 + int err;
1.494 +
1.495 + if (!wsa_init_done)
1.496 + {
1.497 +
1.498 +
1.499 + wsa_init_done=1;
1.500 + wVerReq = MAKEWORD( 2, 0 );
1.501 + err = WSAStartup(wVerReq,&wsaData);
1.502 + if (err != 0)
1.503 + {
1.504 + SYSerr(SYS_F_WSASTARTUP,err);
1.505 + BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
1.506 + return(-1);
1.507 + }
1.508 + }
1.509 +#endif
1.510 +
1.511 + return(1);
1.512 + }
1.513 +
1.514 +EXPORT_C void BIO_sock_cleanup(void)
1.515 + {
1.516 +#ifdef OPENSSL_SYS_WINDOWS
1.517 + if (wsa_init_done)
1.518 + {
1.519 + wsa_init_done=0;
1.520 +#ifndef OPENSSL_SYS_WINCE
1.521 + WSACancelBlockingCall();
1.522 +#endif
1.523 + WSACleanup();
1.524 + }
1.525 +#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
1.526 + if (wsa_init_done)
1.527 + {
1.528 + wsa_init_done=0;
1.529 + WSACleanup();
1.530 + }
1.531 +#endif
1.532 + }
1.533 +
1.534 +#if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000
1.535 +
1.536 +EXPORT_C int BIO_socket_ioctl(int fd, long type, void *arg)
1.537 + {
1.538 + int i;
1.539 +
1.540 +#ifdef __DJGPP__
1.541 + i=ioctlsocket(fd,type,(char *)arg);
1.542 +#else
1.543 + i=ioctlsocket(fd,type,arg);
1.544 +#endif /* __DJGPP__ */
1.545 + if (i < 0)
1.546 + SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
1.547 + return(i);
1.548 + }
1.549 +#endif /* __VMS_VER */
1.550 +
1.551 +/* The reason I have implemented this instead of using sscanf is because
1.552 + * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
1.553 +static int get_ip(const char *str, unsigned char ip[4])
1.554 + {
1.555 + unsigned int tmp[4];
1.556 + int num=0,c,ok=0;
1.557 +
1.558 + tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
1.559 +
1.560 + for (;;)
1.561 + {
1.562 + c= *(str++);
1.563 + if ((c >= '0') && (c <= '9'))
1.564 + {
1.565 + ok=1;
1.566 + tmp[num]=tmp[num]*10+c-'0';
1.567 + if (tmp[num] > 255) return(0);
1.568 + }
1.569 + else if (c == '.')
1.570 + {
1.571 + if (!ok) return(-1);
1.572 + if (num == 3) return(0);
1.573 + num++;
1.574 + ok=0;
1.575 + }
1.576 + else if (c == '\0' && (num == 3) && ok)
1.577 + break;
1.578 + else
1.579 + return(0);
1.580 + }
1.581 + ip[0]=tmp[0];
1.582 + ip[1]=tmp[1];
1.583 + ip[2]=tmp[2];
1.584 + ip[3]=tmp[3];
1.585 + return(1);
1.586 + }
1.587 +
1.588 +EXPORT_C int BIO_get_accept_socket(char *host, int bind_mode)
1.589 + {
1.590 + int ret=0;
1.591 + struct sockaddr_in server,client;
1.592 + int s=INVALID_SOCKET,cs;
1.593 + unsigned char ip[4];
1.594 + unsigned short port;
1.595 + char *str=NULL,*e;
1.596 + const char *h,*p;
1.597 + unsigned long l;
1.598 + int err_num;
1.599 +
1.600 + if (BIO_sock_init() != 1) return(INVALID_SOCKET);
1.601 +
1.602 + if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
1.603 +
1.604 + h=p=NULL;
1.605 + h=str;
1.606 + for (e=str; *e; e++)
1.607 + {
1.608 + if (*e == ':')
1.609 + {
1.610 + p= &(e[1]);
1.611 + *e='\0';
1.612 + }
1.613 + else if (*e == '/')
1.614 + {
1.615 + *e='\0';
1.616 + break;
1.617 + }
1.618 + }
1.619 +
1.620 + if (p == NULL)
1.621 + {
1.622 + p=h;
1.623 + h="*";
1.624 + }
1.625 +
1.626 + if (!BIO_get_port(p,&port)) goto err;
1.627 +
1.628 + memset((char *)&server,0,sizeof(server));
1.629 + server.sin_family=AF_INET;
1.630 + server.sin_port=htons(port);
1.631 +
1.632 + if (strcmp(h,"*") == 0)
1.633 + server.sin_addr.s_addr=INADDR_ANY;
1.634 + else
1.635 + {
1.636 + if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
1.637 + l=(unsigned long)
1.638 + ((unsigned long)ip[0]<<24L)|
1.639 + ((unsigned long)ip[1]<<16L)|
1.640 + ((unsigned long)ip[2]<< 8L)|
1.641 + ((unsigned long)ip[3]);
1.642 + server.sin_addr.s_addr=htonl(l);
1.643 + }
1.644 +
1.645 +again:
1.646 + s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
1.647 + if (s == INVALID_SOCKET)
1.648 + {
1.649 + SYSerr(SYS_F_SOCKET,get_last_socket_error());
1.650 + ERR_add_error_data(3,"port='",host,"'");
1.651 + BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
1.652 + goto err;
1.653 + }
1.654 +
1.655 +#ifdef SO_REUSEADDR
1.656 + if (bind_mode == BIO_BIND_REUSEADDR)
1.657 + {
1.658 + int i=1;
1.659 +
1.660 + ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
1.661 + bind_mode=BIO_BIND_NORMAL;
1.662 + }
1.663 +#endif
1.664 + if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
1.665 + {
1.666 +#ifdef SO_REUSEADDR
1.667 + err_num=get_last_socket_error();
1.668 + if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
1.669 + (err_num == EADDRINUSE))
1.670 + {
1.671 + memcpy((char *)&client,(char *)&server,sizeof(server));
1.672 + if (strcmp(h,"*") == 0)
1.673 + client.sin_addr.s_addr=htonl(0x7F000001);
1.674 + cs=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
1.675 + if (cs != INVALID_SOCKET)
1.676 + {
1.677 + int ii;
1.678 + ii=connect(cs,(struct sockaddr *)&client,
1.679 + sizeof(client));
1.680 + closesocket(cs);
1.681 + if (ii == INVALID_SOCKET)
1.682 + {
1.683 + bind_mode=BIO_BIND_REUSEADDR;
1.684 + closesocket(s);
1.685 + goto again;
1.686 + }
1.687 + /* else error */
1.688 + }
1.689 + /* else error */
1.690 + }
1.691 +#endif
1.692 + SYSerr(SYS_F_BIND,err_num);
1.693 + ERR_add_error_data(3,"port='",host,"'");
1.694 + BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
1.695 + goto err;
1.696 + }
1.697 + if (listen(s,MAX_LISTEN) == -1)
1.698 + {
1.699 + SYSerr(SYS_F_BIND,get_last_socket_error());
1.700 + ERR_add_error_data(3,"port='",host,"'");
1.701 + BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
1.702 + goto err;
1.703 + }
1.704 + ret=1;
1.705 +err:
1.706 + if (str != NULL) OPENSSL_free(str);
1.707 + if ((ret == 0) && (s != INVALID_SOCKET))
1.708 + {
1.709 + closesocket(s);
1.710 + s= INVALID_SOCKET;
1.711 + }
1.712 + return(s);
1.713 + }
1.714 +#ifdef EMULATOR
1.715 +GET_STATIC_VAR_FROM_TLS(from,b_sock,struct sockaddr_in)
1.716 +#define from (*GET_WSD_VAR_NAME(from,b_sock, s)())
1.717 +#endif
1.718 +
1.719 +EXPORT_C int BIO_accept(int sock, char **addr)
1.720 + {
1.721 + int ret=INVALID_SOCKET;
1.722 +#ifndef EMULATOR
1.723 + static struct sockaddr_in from;
1.724 +#endif
1.725 + unsigned long l;
1.726 + unsigned short port;
1.727 + int len;
1.728 + char *p;
1.729 +
1.730 + memset((char *)&from,0,sizeof(from));
1.731 + len=sizeof(from);
1.732 + /* Note: under VMS with SOCKETSHR the fourth parameter is currently
1.733 + * of type (int *) whereas under other systems it is (void *) if
1.734 + * you don't have a cast it will choke the compiler: if you do
1.735 + * have a cast then you can either go for (int *) or (void *).
1.736 + */
1.737 + ret=accept(sock,(struct sockaddr *)&from,(void *)&len);
1.738 + if (ret == INVALID_SOCKET)
1.739 + {
1.740 + if(BIO_sock_should_retry(ret)) return -2;
1.741 + SYSerr(SYS_F_ACCEPT,get_last_socket_error());
1.742 + BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
1.743 + goto end;
1.744 + }
1.745 +
1.746 + if (addr == NULL) goto end;
1.747 +
1.748 + l=ntohl(from.sin_addr.s_addr);
1.749 + port=ntohs(from.sin_port);
1.750 + if (*addr == NULL)
1.751 + {
1.752 + if ((p=OPENSSL_malloc(24)) == NULL)
1.753 + {
1.754 + BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
1.755 + goto end;
1.756 + }
1.757 + *addr=p;
1.758 + }
1.759 + BIO_snprintf(*addr,24,"%d.%d.%d.%d:%d",
1.760 + (unsigned char)(l>>24L)&0xff,
1.761 + (unsigned char)(l>>16L)&0xff,
1.762 + (unsigned char)(l>> 8L)&0xff,
1.763 + (unsigned char)(l )&0xff,
1.764 + port);
1.765 +end:
1.766 + return(ret);
1.767 + }
1.768 +
1.769 +EXPORT_C int BIO_set_tcp_ndelay(int s, int on)
1.770 + {
1.771 + int ret=0;
1.772 +#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
1.773 + int opt;
1.774 +
1.775 +#ifdef SOL_TCP
1.776 + opt=SOL_TCP;
1.777 +#else
1.778 +#ifdef IPPROTO_TCP
1.779 + opt=IPPROTO_TCP;
1.780 +#endif
1.781 +#endif
1.782 +
1.783 + ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
1.784 +#endif
1.785 + return(ret == 0);
1.786 + }
1.787 +#endif
1.788 +
1.789 +EXPORT_C int BIO_socket_nbio(int s, int mode)
1.790 + {
1.791 + int ret= -1;
1.792 + int l;
1.793 +
1.794 + l=mode;
1.795 +#ifdef FIONBIO
1.796 + ret=BIO_socket_ioctl(s,FIONBIO,&l);
1.797 +#endif
1.798 + return(ret == 0);
1.799 + }