Make the BIO_ADDR param optional.
[openssl.git] / crypto / bio / b_sock.c
index adab62135e7ddbf6da275a3bf77b26e50b577eb0..50bd27dabd3b6ace326cf9ebe04b9ebe42147dd4 100644 (file)
@@ -1,25 +1,24 @@
-/* crypto/bio/b_sock.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
- * 
+ *
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
+ *
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
+ * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * 
+ *
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
 
-#ifndef NO_SOCK
-
 #include <stdio.h>
+#include <stdlib.h>
 #include <errno.h>
-#define USE_SOCKETS
-#include "cryptlib.h"
-#include "bio.h"
-
-/*     BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */
-
-#ifdef WIN16
-#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
-#else
-#define SOCKET_PROTOCOL IPPROTO_TCP
-#endif
-
-#ifdef WINDOWS
-static int wsa_init_done=0;
+#include "bio_lcl.h"
+#if defined(NETWARE_CLIB)
+# include <sys/ioctl.h>
+NETDB_DEFINE_CONTEXT
 #endif
+#ifndef OPENSSL_NO_SOCK
+# define SOCKET_PROTOCOL IPPROTO_TCP
+# ifdef SO_MAXCONN
+#  define MAX_LISTEN  SO_MAXCONN
+# elif defined(SOMAXCONN)
+#  define MAX_LISTEN  SOMAXCONN
+# else
+#  define MAX_LISTEN  32
+# endif
+# if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
+static int wsa_init_done = 0;
+# endif
+
+# if OPENSSL_API_COMPAT < 0x10100000L
+int BIO_get_host_ip(const char *str, unsigned char *ip)
+{
+    BIO_ADDRINFO *res = NULL;
+    int ret = 0;
+
+    if (BIO_sock_init() != 1)
+        return 0;               /* don't generate another error code here */
+
+    if (BIO_lookup(str, NULL, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
+        size_t l;
+
+        if (BIO_ADDRINFO_family(res) != AF_INET) {
+            BIOerr(BIO_F_BIO_GET_HOST_IP,
+                   BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
+        } else {
+            BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), NULL, &l);
+            /* Because only AF_INET addresses will reach this far,
+               we can assert that l should be 4 */
+            OPENSSL_assert(l == 4);
+
+            BIO_ADDR_rawaddress(BIO_ADDRINFO_address(res), ip, &l);
+            ret = 1;
+        }
+        BIO_ADDRINFO_free(res);
+    } else {
+        ERR_add_error_data(2, "host=", str);
+    }
+
+    return ret;
+}
+
+int BIO_get_port(const char *str, unsigned short *port_ptr)
+{
+    BIO_ADDRINFO *res = NULL;
+    int ret = 0;
+
+    if (str == NULL) {
+        BIOerr(BIO_F_BIO_GET_PORT, BIO_R_NO_PORT_DEFINED);
+        return (0);
+    }
+
+    if (BIO_sock_init() != 1)
+        return 0;               /* don't generate another error code here */
+
+    if (BIO_lookup(NULL, str, BIO_LOOKUP_CLIENT, AF_INET, SOCK_STREAM, &res)) {
+        if (BIO_ADDRINFO_family(res) != AF_INET) {
+            BIOerr(BIO_F_BIO_GET_PORT,
+                   BIO_R_ADDRINFO_ADDR_IS_NOT_AF_INET);
+        } else {
+            *port_ptr = ntohs(BIO_ADDR_rawport(BIO_ADDRINFO_address(res)));
+            ret = 1;
+        }
+        BIO_ADDRINFO_free(res);
+    } else {
+        ERR_add_error_data(2, "host=", str);
+    }
+
+    return ret;
+}
+# endif
+
+int BIO_sock_error(int sock)
+{
+    int j = 0, i;
+    socklen_t size = 0;
+
+    /*
+     * Note: under Windows the third parameter is of type (char *) whereas
+     * under other systems it is (void *) if you don't have a cast it will
+     * choke the compiler: if you do have a cast then you can either go for
+     * (char *) or (void *).
+     */
+    i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, &size);
+    if (i < 0)
+        return (1);
+    else
+        return (j);
+}
+
+# if OPENSSL_API_COMPAT < 0x10100000L
+struct hostent *BIO_gethostbyname(const char *name)
+{
+    /*
+     * Caching gethostbyname() results forever is wrong, so we have to let
+     * the true gethostbyname() worry about this
+     */
+#  if (defined(NETWARE_BSDSOCK) && !defined(__NOVELL_LIBC__))
+    return gethostbyname((char *)name);
+#  else
+    return gethostbyname(name);
+#  endif
+}
+# endif
+
+int BIO_sock_init(void)
+{
+# ifdef OPENSSL_SYS_WINDOWS
+    static struct WSAData wsa_state;
+
+    if (!wsa_init_done) {
+        int err;
+
+        wsa_init_done = 1;
+        memset(&wsa_state, 0, sizeof(wsa_state));
+        /*
+         * Not making wsa_state available to the rest of the code is formally
+         * wrong. But the structures we use are [believed to be] invariable
+         * among Winsock DLLs, while API availability is [expected to be]
+         * probed at run-time with DSO_global_lookup.
+         */
+        if (WSAStartup(0x0202, &wsa_state) != 0) {
+            err = WSAGetLastError();
+            SYSerr(SYS_F_WSASTARTUP, err);
+            BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP);
+            return (-1);
+        }
+    }
+# endif                         /* OPENSSL_SYS_WINDOWS */
+# ifdef WATT32
+    extern int _watt_do_exit;
+    _watt_do_exit = 0;          /* don't make sock_init() call exit() */
+    if (sock_init())
+        return (-1);
+# endif
+
+# if defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
+    WORD wVerReq;
+    WSADATA wsaData;
+    int err;
+
+    if (!wsa_init_done) {
+        wsa_init_done = 1;
+        wVerReq = MAKEWORD(2, 0);
+        err = WSAStartup(wVerReq, &wsaData);
+        if (err != 0) {
+            SYSerr(SYS_F_WSASTARTUP, err);
+            BIOerr(BIO_F_BIO_SOCK_INIT, BIO_R_WSASTARTUP);
+            return (-1);
+        }
+    }
+# endif
+
+    return (1);
+}
+
+void BIO_sock_cleanup(void)
+{
+# ifdef OPENSSL_SYS_WINDOWS
+    if (wsa_init_done) {
+        wsa_init_done = 0;
+        WSACleanup();
+    }
+# elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
+    if (wsa_init_done) {
+        wsa_init_done = 0;
+        WSACleanup();
+    }
+# endif
+}
+
+# if !defined(OPENSSL_SYS_VMS) || __VMS_VER >= 70000000
+
+int BIO_socket_ioctl(int fd, long type, void *arg)
+{
+    int i;
+
+#  ifdef __DJGPP__
+    i = ioctlsocket(fd, type, (char *)arg);
+#  else
+#   if defined(OPENSSL_SYS_VMS)
+    /*-
+     * 2011-02-18 SMS.
+     * VMS ioctl() can't tolerate a 64-bit "void *arg", but we
+     * observe that all the consumers pass in an "unsigned long *",
+     * so we arrange a local copy with a short pointer, and use
+     * that, instead.
+     */
+#    if __INITIAL_POINTER_SIZE == 64
+#     define ARG arg_32p
+#     pragma pointer_size save
+#     pragma pointer_size 32
+    unsigned long arg_32;
+    unsigned long *arg_32p;
+#     pragma pointer_size restore
+    arg_32p = &arg_32;
+    arg_32 = *((unsigned long *)arg);
+#    else                       /* __INITIAL_POINTER_SIZE == 64 */
+#     define ARG arg
+#    endif                      /* __INITIAL_POINTER_SIZE == 64 [else] */
+#   else                        /* defined(OPENSSL_SYS_VMS) */
+#    define ARG arg
+#   endif                       /* defined(OPENSSL_SYS_VMS) [else] */
+
+    i = ioctlsocket(fd, type, ARG);
+#  endif                        /* __DJGPP__ */
+    if (i < 0)
+        SYSerr(SYS_F_IOCTLSOCKET, get_last_socket_error());
+    return (i);
+}
+# endif                         /* __VMS_VER */
+
+# if OPENSSL_API_COMPAT < 0x10100000L
+int BIO_get_accept_socket(char *host, int bind_mode)
+{
+    int s = INVALID_SOCKET;
+    char *h = NULL, *p = NULL;
+    BIO_ADDRINFO *res = NULL;
+
+    if (!BIO_parse_hostserv(host, &h, &p, BIO_PARSE_PRIO_SERV))
+        return INVALID_SOCKET;
+
+    if (BIO_sock_init() != 1)
+        return INVALID_SOCKET;
+
+    if (BIO_lookup(h, p, BIO_LOOKUP_SERVER, AF_UNSPEC, SOCK_STREAM, &res) != 0)
+        goto err;
+
+    if ((s = BIO_socket(BIO_ADDRINFO_family(res), BIO_ADDRINFO_socktype(res),
+                        BIO_ADDRINFO_protocol(res), 0)) == INVALID_SOCKET) {
+        s = INVALID_SOCKET;
+        goto err;
+    }
+
+    if (!BIO_listen(s, BIO_ADDRINFO_address(res),
+                    bind_mode ? BIO_SOCK_REUSEADDR : 0)) {
+        BIO_closesocket(s);
+        s = INVALID_SOCKET;
+    }
+
+ err:
+    BIO_ADDRINFO_free(res);
+    OPENSSL_free(h);
+    OPENSSL_free(p);
+
+    return s;
+}
+
+int BIO_accept(int sock, char **ip_port)
+{
+    BIO_ADDR res;
+    int ret = -1;
+
+    ret = BIO_accept_ex(sock, &res, 0);
+    if (ret == (int)INVALID_SOCKET) {
+        if (BIO_sock_should_retry(ret)) {
+            ret = -2;
+            goto end;
+        }
+        SYSerr(SYS_F_ACCEPT, get_last_socket_error());
+        BIOerr(BIO_F_BIO_ACCEPT, BIO_R_ACCEPT_ERROR);
+        goto end;
+    }
+
+    if (ip_port != NULL) {
+        char *host = BIO_ADDR_hostname_string(&res, 1);
+        char *port = BIO_ADDR_service_string(&res, 1);
+        *ip_port = OPENSSL_zalloc(strlen(host) + strlen(port) + 2);
+        strcpy(*ip_port, host);
+        strcat(*ip_port, ":");
+        strcat(*ip_port, port);
+        OPENSSL_free(host);
+        OPENSSL_free(port);
+    }
+
+ end:
+    return ret;
+}
+# endif
+
+int BIO_set_tcp_ndelay(int s, int on)
+{
+    int ret = 0;
+# if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
+    int opt;
+
+#  ifdef SOL_TCP
+    opt = SOL_TCP;
+#  else
+#   ifdef IPPROTO_TCP
+    opt = IPPROTO_TCP;
+#   endif
+#  endif
+
+    ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
+# endif
+    return (ret == 0);
+}
+
+int BIO_socket_nbio(int s, int mode)
+{
+    int ret = -1;
+    int l;
+
+    l = mode;
+# ifdef FIONBIO
+    l = mode;
+
+    ret = BIO_socket_ioctl(s, FIONBIO, &l);
+# elif defined(F_GETFL) && defined(F_SETFL) && (defined(O_NONBLOCK) || defined(FNDELAY))
+    /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
+
+    l = fcntl(s, F_GETFL, 0);
+    if (l == -1) {
+        SYSerr(SYS_F_FCNTL, get_last_rtl_error());
+        ret = -1;
+    } else {
+#  if defined(O_NONBLOCK)
+        l &= ~O_NONBLOCK;
+#  else
+        l &= ~FNDELAY; /* BSD4.x */
+#  endif
+        if (mode) {
+#  if defined(O_NONBLOCK)
+            l |= O_NONBLOCK;
+#  else
+            l |= FNDELAY; /* BSD4.x */
+#  endif
+        }
+        ret = fcntl(s, F_SETFL, l);
+
+        if (ret < 0) {
+            SYSerr(SYS_F_FCNTL, get_last_rtl_error());
+        }
+    }
+# else
+    /* make sure this call always pushes an error level; BIO_socket_ioctl() does so, so we do too. */
+    BIOerr(BIO_F_BIO_SOCKET_NBIO, ERR_R_PASSED_INVALID_ARGUMENT);
+# endif
+
+    return (ret == 0);
+}
+
+int BIO_sock_info(int sock,
+                  enum BIO_sock_info_type type, union BIO_sock_info_u *info)
+{
+    switch (type) {
+    case BIO_SOCK_INFO_ADDRESS:
+        {
+            socklen_t addr_len;
+            int ret = 0;
+            addr_len = sizeof(*info->addr);
+            ret = getsockname(sock, BIO_ADDR_sockaddr_noconst(info->addr),
+                              &addr_len);
+            if (ret == -1) {
+                SYSerr(SYS_F_GETSOCKNAME, get_last_socket_error());
+                BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_ERROR);
+                return 0;
+            }
+            if ((size_t)addr_len > sizeof(*info->addr)) {
+                BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_GETSOCKNAME_TRUNCATED_ADDRESS);
+                return 0;
+            }
+        }
+        break;
+    default:
+        BIOerr(BIO_F_BIO_SOCK_INFO, BIO_R_UNKNOWN_INFO_TYPE);
+        return 0;
+    }
+    return 1;
+}
 
-unsigned long BIO_ghbn_hits=0L;
-unsigned long BIO_ghbn_miss=0L;
-
-#ifndef NOPROTO
-static int get_ip(char *str,unsigned char *ip);
-#else
-static int get_ip();
-#endif
-
-int BIO_get_host_ip(str,ip)
-char *str;
-unsigned char *ip;
-       {
-       int i;
-       struct hostent *he;
-
-       i=get_ip(str,ip);
-       if (i > 0) return(1);
-       if (i < 0)
-               {
-               BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_INVALID_IP_ADDRESS);
-               return(0);
-               }
-       else
-               { /* do a gethostbyname */
-               if (!BIO_sock_init()) return(0);
-
-               he=BIO_gethostbyname(str);
-               if (he == NULL)
-                       {
-                       BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
-                       return(0);
-                       }
-
-               /* cast to short because of win16 winsock definition */
-               if ((short)he->h_addrtype != AF_INET)
-                       {
-                       BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET);
-                       return(0);
-                       }
-               for (i=0; i<4; i++)
-                       ip[i]=he->h_addr_list[0][i];
-               }
-       return(1);
-       }
-
-int BIO_get_port(str,port_ptr)
-char *str;
-short *port_ptr;
-       {
-       int i;
-       struct servent *s;
-
-       if (str == NULL)
-               {
-               BIOerr(BIO_F_BIO_GET_PORT,BIO_R_NO_PORT_DEFINED);
-               return(0);
-               }
-       i=atoi(str);
-       if (i != 0)
-               *port_ptr=(unsigned short)i;
-       else
-               {
-               s=getservbyname(str,"tcp");
-               if (s == NULL)
-                       {
-                       if (strcmp(str,"http") == 0)
-                               *port_ptr=80;
-                       else if (strcmp(str,"telnet") == 0)
-                               *port_ptr=23;
-                       else if (strcmp(str,"socks") == 0)
-                               *port_ptr=1080;
-                       else if (strcmp(str,"https") == 0)
-                               *port_ptr=443;
-                       else if (strcmp(str,"ssl") == 0)
-                               *port_ptr=443;
-                       else if (strcmp(str,"ftp") == 0)
-                               *port_ptr=21;
-                       else if (strcmp(str,"gopher") == 0)
-                               *port_ptr=70;
-#if 0
-                       else if (strcmp(str,"wais") == 0)
-                               *port_ptr=21;
-#endif
-                       else
-                               {
-                               SYSerr(SYS_F_GETSERVBYNAME,errno);
-                               return(0);
-                               }
-                       return(1);
-                       }
-               *port_ptr=htons((unsigned short)s->s_port);
-               }
-       return(1);
-       }
-
-int BIO_sock_error(sock)
-int sock;
-       {
-       int j,i,size;
-                
-       size=sizeof(int);
-
-       i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size);
-       if (i < 0)
-               return(1);
-       else
-               return(j);
-       }
-
-#define GHBN_NUM       4
-static struct ghbn_cache_st
-       {
-       char name[128];
-       struct hostent ent;
-       unsigned long order;
-       } ghbn_cache[GHBN_NUM];
-
-struct hostent *BIO_gethostbyname(name)
-char *name;
-       {
-       struct hostent *ret;
-       int i,lowi=0;
-       unsigned long low= (unsigned long)-1;
-
-       CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
-       if (strlen(name) < 128)
-               {
-               for (i=0; i<GHBN_NUM; i++)
-                       {
-                       if (low > ghbn_cache[i].order)
-                               {
-                               low=ghbn_cache[i].order;
-                               lowi=i;
-                               }
-                       if (ghbn_cache[i].order > 0)
-                               {
-                               if (strncmp(name,ghbn_cache[i].name,128) == 0)
-                                       break;
-                               }
-                       }
-               }
-       else
-               i=GHBN_NUM;
-
-       if (i == GHBN_NUM) /* no hit*/
-               {
-               BIO_ghbn_miss++;
-               ret=gethostbyname(name);
-               if (ret == NULL) return(NULL);
-               /* else add to cache */
-               strncpy(ghbn_cache[lowi].name,name,128);
-               memcpy((char *)&(ghbn_cache[lowi].ent),ret,sizeof(struct hostent));
-               ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
-               }
-       else
-               {
-               BIO_ghbn_hits++;
-               ret= &(ghbn_cache[i].ent);
-               ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
-               }
-       CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
-       return(ret);
-       }
-
-int BIO_sock_init()
-       {
-#ifdef WINDOWS
-       static struct WSAData wsa_state;
-
-       if (!wsa_init_done)
-               {
-               int err;
-         
-#ifdef SIGINT
-               signal(SIGINT,(void (*)(int))BIO_sock_cleanup);
 #endif
-               wsa_init_done=1;
-               memset(&wsa_state,0,sizeof(wsa_state));
-               if (WSAStartup(0x0101,&wsa_state)!=0)
-                       {
-                       err=WSAGetLastError();
-                       SYSerr(SYS_F_WSASTARTUP,err);
-                       BIOerr(BIO_F_BIO_SOCK_INIT,BIO_R_WSASTARTUP);
-                       return(-1);
-                       }
-               }
-#endif /* WINDOWS */
-       return(1);
-       }
-
-void BIO_sock_cleanup()
-       {
-#ifdef WINDOWS
-       if (wsa_init_done)
-               {
-               wsa_init_done=0;
-               WSACancelBlockingCall();
-               WSACleanup();
-               }
-#endif
-       }
-
-int BIO_socket_ioctl(fd,type,arg)
-int fd;
-long type;
-unsigned long *arg;
-       {
-       int i,err;
-
-#ifdef WINDOWS
-       i=ioctlsocket(fd,type,arg);
-#else
-       i=ioctl(fd,type,arg);
-#endif
-       if (i < 0)
-               {
-#ifdef WINDOWS
-               err=WSAGetLastError();
-#else
-               err=errno;
-#endif
-               SYSerr(SYS_F_IOCTLSOCKET,err);
-               }
-       return(i);
-       }
-
-/* The reason I have implemented this instead of using sscanf is because
- * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
-static int get_ip(str,ip)
-char *str;
-unsigned char ip[4];
-       {
-       unsigned int tmp[4];
-       int num=0,c,ok=0;
-
-       tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
-
-       for (;;)
-               {
-               c= *(str++);
-               if ((c >= '0') && (c <= '9'))
-                       {
-                       ok=1;
-                       tmp[num]=tmp[num]*10+c-'0';
-                       if (tmp[num] > 255) return(-1);
-                       }
-               else if (c == '.')
-                       {
-                       if (!ok) return(-1);
-                       if (num == 3) break;
-                       num++;
-                       ok=0;
-                       }
-               else if ((num == 3) && ok)
-                       break;
-               else
-                       return(0);
-               }
-       ip[0]=tmp[0];
-       ip[1]=tmp[1];
-       ip[2]=tmp[2];
-       ip[3]=tmp[3];
-       return(1);
-       }
-
-int BIO_get_accept_socket(host)
-char *host;
-       {
-       int ret=0;
-       struct sockaddr_in server;
-       int s= -1;
-       unsigned char ip[4];
-       short port;
-       char *str,*h,*p,*e;
-       unsigned long l;
-
-       if (!BIO_sock_init()) return(INVALID_SOCKET);
-
-       if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
-
-       h=p=NULL;
-       h=str;
-       for (e=str; *e; e++)
-               {
-               if (*e == ':')
-                       {
-                       p= &(e[1]);
-                       *e='\0';
-                       }
-               else if (*e == '/')
-                       {
-                       *e='\0';
-                       break;
-                       }
-               }
-
-       if (p == NULL)
-               {
-               p=h;
-               h="*";
-               }
-
-       if (!BIO_get_port(p,&port)) return(INVALID_SOCKET);
-
-       memset((char *)&server,0,sizeof(server));
-       server.sin_family=AF_INET;
-       server.sin_port=htons((unsigned short)port);
-
-       if (strcmp(h,"*") == 0)
-               server.sin_addr.s_addr=INADDR_ANY;
-       else
-               {
-               if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET);
-               l=(unsigned long)
-                       ((unsigned long)ip[0]<<24L)|
-                       ((unsigned long)ip[0]<<16L)|
-                       ((unsigned long)ip[0]<< 8L)|
-                       ((unsigned long)ip[0]);
-               server.sin_addr.s_addr=htonl(l);
-               }
-
-       s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
-       if (s == INVALID_SOCKET)
-               {
-#ifdef WINDOWS
-               errno=WSAGetLastError();
-#endif
-               SYSerr(SYS_F_SOCKET,errno);
-               BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
-               goto err;
-               }
-       if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
-               {
-#ifdef WINDOWS
-               errno=WSAGetLastError();
-#endif
-               SYSerr(SYS_F_BIND,errno);
-               BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
-               goto err;
-               }
-       if (listen(s,5) == -1)
-               {
-#ifdef WINDOWS
-               errno=WSAGetLastError();
-#endif
-               SYSerr(SYS_F_LISTEN,errno);
-               BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_LISTEN_SOCKET);
-               goto err;
-               }
-       ret=1;
-err:
-       if (str != NULL) Free(str);
-       if ((ret == 0) && (s != INVALID_SOCKET))
-               {
-#ifdef WINDOWS
-               closesocket(s);
-#else
-               close(s);
-#endif
-               s= INVALID_SOCKET;
-               }
-       return(s);
-       }
-
-int BIO_accept(sock,addr)
-int sock;
-char **addr;
-       {
-       int ret=INVALID_SOCKET;
-       static struct sockaddr_in from;
-       unsigned long l;
-       short port;
-       int len;
-       char *p;
-
-       memset((char *)&from,0,sizeof(from));
-       len=sizeof(from);
-       ret=accept(sock,(struct sockaddr *)&from,&len);
-       if (ret == INVALID_SOCKET)
-               {
-#ifdef WINDOWS
-               errno=WSAGetLastError();
-#endif
-               SYSerr(SYS_F_ACCEPT,errno);
-               BIOerr(BIO_F_BIO_ACCEPT,BIO_R_ACCEPT_ERROR);
-               goto end;
-               }
-
-       if (addr == NULL) goto end;
-
-       l=ntohl(from.sin_addr.s_addr);
-       port=ntohs(from.sin_port);
-       if (*addr == NULL)
-               {
-               if ((p=Malloc(24)) == NULL)
-                       {
-                       BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
-                       goto end;
-                       }
-               *addr=p;
-               }
-       sprintf(*addr,"%d.%d.%d.%d:%d",
-               (unsigned char)(l>>24L)&0xff,
-               (unsigned char)(l>>16L)&0xff,
-               (unsigned char)(l>> 8L)&0xff,
-               (unsigned char)(l     )&0xff,
-               port);
-end:
-       return(ret);
-       }
-
-int BIO_set_tcp_ndelay(s,on)
-int s;
-int on;
-       {
-       int ret=0;
-#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
-       int opt;
-
-#ifdef SOL_TCP
-       opt=SOL_TCP;
-#else
-#ifdef IPPROTO_TCP
-       opt=IPPROTO_TCP;
-#endif
-#endif
-       
-       ret=setsockopt(s,opt,TCP_NODELAY,(char *)&on,sizeof(on));
-#endif
-       return(ret == 0);
-       }
-#endif
-