* [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"
+#include <openssl/bio.h>
+#if defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_BSDSOCK)
+#include <netdb.h>
+#if defined(NETWARE_CLIB)
+#include <sys/ioctl.h>
+NETDB_DEFINE_CONTEXT
+#endif
+#endif
-/* BIOerr(BIO_F_WSASTARTUP,BIO_R_WSASTARTUP ); */
+#ifndef OPENSSL_NO_SOCK
+
+#include <openssl/dso.h>
-#ifdef WIN16
-#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
-#else
#define SOCKET_PROTOCOL IPPROTO_TCP
-#endif
#ifdef SO_MAXCONN
-#define MAX_LISTEN SOMAXCONN
-#elif defined(SO_MAXCONN)
#define MAX_LISTEN SO_MAXCONN
+#elif defined(SOMAXCONN)
+#define MAX_LISTEN SOMAXCONN
#else
#define MAX_LISTEN 32
#endif
-#ifdef WINDOWS
+#if defined(OPENSSL_SYS_WINDOWS) || (defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK))
static int wsa_init_done=0;
#endif
+#if defined(OPENSSL_SYS_BEOS_BONE)
+/* BONE's IP6 support is incomplete */
+#undef AF_INET6
+#endif
+
+#if 0
static unsigned long BIO_ghbn_hits=0L;
static unsigned long BIO_ghbn_miss=0L;
struct hostent *ent;
unsigned long order;
} ghbn_cache[GHBN_NUM];
+#endif
-#ifndef NOPROTO
-static int get_ip(char *str,unsigned char *ip);
+static int get_ip(const char *str,unsigned char *ip);
+#if 0
static void ghbn_free(struct hostent *a);
static struct hostent *ghbn_dup(struct hostent *a);
-#else
-static int get_ip();
-static void ghbn_free();
-static struct hostent *ghbn_dup();
#endif
-
-int BIO_get_host_ip(str,ip)
-char *str;
-unsigned char *ip;
+int BIO_get_host_ip(const char *str, unsigned char *ip)
{
int i;
+ int err = 1;
+ int locked = 0;
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);
- ERR_add_error_data(2,"host=",str);
- return(0);
+ goto err;
}
- 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);
- ERR_add_error_data(2,"host=",str);
- return(0);
- }
+ /* At this point, we have something that is most probably correct
+ in some way, so let's init the socket. */
+ if (BIO_sock_init() != 1)
+ return 0; /* don't generate another error code here */
- /* 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);
- ERR_add_error_data(2,"host=",str);
- return(0);
- }
- for (i=0; i<4; i++)
- ip[i]=he->h_addr_list[0][i];
+ /* If the string actually contained an IP address, we need not do
+ anything more */
+ if (i > 0) return(1);
+
+ /* do a gethostbyname */
+ CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
+ locked = 1;
+ he=BIO_gethostbyname(str);
+ if (he == NULL)
+ {
+ BIOerr(BIO_F_BIO_GET_HOST_IP,BIO_R_BAD_HOSTNAME_LOOKUP);
+ goto err;
}
- return(1);
+
+ /* 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);
+ goto err;
+ }
+ for (i=0; i<4; i++)
+ ip[i]=he->h_addr_list[0][i];
+ err = 0;
+
+ err:
+ if (locked)
+ CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
+ if (err)
+ {
+ ERR_add_error_data(2,"host=",str);
+ return 0;
+ }
+ else
+ return 1;
}
-int BIO_get_port(str,port_ptr)
-char *str;
-short *port_ptr;
+int BIO_get_port(const char *str, unsigned short *port_ptr)
{
int i;
struct servent *s;
*port_ptr=(unsigned short)i;
else
{
+ CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
+ /* Note: under VMS with SOCKETSHR, it seems like the first
+ * parameter is 'char *', instead of 'const char *'
+ */
+#ifndef CONST_STRICT
+ s=getservbyname((char *)str,"tcp");
+#else
s=getservbyname(str,"tcp");
- if (s == NULL)
+#endif
+ if(s != NULL)
+ *port_ptr=ntohs((unsigned short)s->s_port);
+ CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
+ if(s == NULL)
{
if (strcmp(str,"http") == 0)
*port_ptr=80;
ERR_add_error_data(3,"service='",str,"'");
return(0);
}
- return(1);
}
- *port_ptr=htons((unsigned short)s->s_port);
}
return(1);
}
-int BIO_sock_error(sock)
-int sock;
+int BIO_sock_error(int sock)
{
- int j,i,size;
+ int j,i;
+ int size;
+
+#if defined(OPENSSL_SYS_BEOS_R5)
+ return 0;
+#endif
size=sizeof(int);
-
- i=getsockopt(sock,SOL_SOCKET,SO_ERROR,(char *)&j,&size);
+ /* 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,(void *)&size);
if (i < 0)
return(1);
else
return(j);
}
-long BIO_ghbn_ctrl(cmd,iarg,parg)
-int cmd;
-int iarg;
-char *parg;
+#if 0
+long BIO_ghbn_ctrl(int cmd, int iarg, char *parg)
{
int i;
char **p;
{
case BIO_GHBN_CTRL_HITS:
return(BIO_ghbn_hits);
- break;
+ /* break; */
case BIO_GHBN_CTRL_MISSES:
return(BIO_ghbn_miss);
- break;
+ /* break; */
case BIO_GHBN_CTRL_CACHE_SIZE:
return(GHBN_NUM);
- break;
+ /* break; */
case BIO_GHBN_CTRL_GET_ENTRY:
if ((iarg >= 0) && (iarg <GHBN_NUM) &&
(ghbn_cache[iarg].order > 0))
return(1);
}
return(0);
- break;
+ /* break; */
case BIO_GHBN_CTRL_FLUSH:
for (i=0; i<GHBN_NUM; i++)
ghbn_cache[i].order=0;
}
return(1);
}
+#endif
-static struct hostent *ghbn_dup(a)
-struct hostent *a;
+#if 0
+static struct hostent *ghbn_dup(struct hostent *a)
{
struct hostent *ret;
int i,j;
- ret=(struct hostent *)malloc(sizeof(struct hostent));
+ MemCheck_off();
+ ret=(struct hostent *)OPENSSL_malloc(sizeof(struct hostent));
if (ret == NULL) return(NULL);
memset(ret,0,sizeof(struct hostent));
for (i=0; a->h_aliases[i] != NULL; i++)
;
i++;
- ret->h_aliases=(char **)malloc(sizeof(char *)*i);
- memset(ret->h_aliases,0,sizeof(char *)*i);
- if (ret == NULL) goto err;
+ ret->h_aliases = (char **)OPENSSL_malloc(i*sizeof(char *));
+ if (ret->h_aliases == NULL)
+ goto err;
+ memset(ret->h_aliases, 0, i*sizeof(char *));
for (i=0; a->h_addr_list[i] != NULL; i++)
;
i++;
- ret->h_addr_list=(char **)malloc(sizeof(char *)*i);
- memset(ret->h_addr_list,0,sizeof(char *)*i);
- if (ret->h_addr_list == NULL) goto err;
+ ret->h_addr_list=(char **)OPENSSL_malloc(i*sizeof(char *));
+ if (ret->h_addr_list == NULL)
+ goto err;
+ memset(ret->h_addr_list, 0, i*sizeof(char *));
j=strlen(a->h_name)+1;
- if ((ret->h_name=malloc(j)) == NULL) goto err;
+ if ((ret->h_name=OPENSSL_malloc(j)) == NULL) goto err;
memcpy((char *)ret->h_name,a->h_name,j);
for (i=0; a->h_aliases[i] != NULL; i++)
{
j=strlen(a->h_aliases[i])+1;
- if ((ret->h_aliases[i]=malloc(j)) == NULL) goto err;
+ if ((ret->h_aliases[i]=OPENSSL_malloc(j)) == NULL) goto err;
memcpy(ret->h_aliases[i],a->h_aliases[i],j);
}
ret->h_length=a->h_length;
ret->h_addrtype=a->h_addrtype;
for (i=0; a->h_addr_list[i] != NULL; i++)
{
- if ((ret->h_addr_list[i]=malloc(a->h_length)) == NULL)
+ if ((ret->h_addr_list[i]=OPENSSL_malloc(a->h_length)) == NULL)
goto err;
memcpy(ret->h_addr_list[i],a->h_addr_list[i],a->h_length);
}
- return(ret);
+ if (0)
+ {
err:
- if (ret != NULL)
- ghbn_free(ret);
- return(NULL);
+ if (ret != NULL)
+ ghbn_free(ret);
+ ret=NULL;
+ }
+ MemCheck_on();
+ return(ret);
}
-static void ghbn_free(a)
-struct hostent *a;
+static void ghbn_free(struct hostent *a)
{
int i;
+ if(a == NULL)
+ return;
+
if (a->h_aliases != NULL)
{
for (i=0; a->h_aliases[i] != NULL; i++)
- free(a->h_aliases[i]);
- free(a->h_aliases);
+ OPENSSL_free(a->h_aliases[i]);
+ OPENSSL_free(a->h_aliases);
}
if (a->h_addr_list != NULL)
{
for (i=0; a->h_addr_list[i] != NULL; i++)
- free(a->h_addr_list[i]);
- free(a->h_addr_list);
+ OPENSSL_free(a->h_addr_list[i]);
+ OPENSSL_free(a->h_addr_list);
}
- if (a->h_name != NULL) free((char *)a->h_name);
- free(a);
+ if (a->h_name != NULL) OPENSSL_free(a->h_name);
+ OPENSSL_free(a);
}
-struct hostent *BIO_gethostbyname(name)
-char *name;
+#endif
+
+struct hostent *BIO_gethostbyname(const char *name)
{
+#if 1
+ /* 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
+#else
struct hostent *ret;
int i,lowi=0,j;
unsigned long low= (unsigned long)-1;
-/* return(gethostbyname(name)); */
- CRYPTO_w_lock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
+# if 0
+ /* It doesn't make sense to use locking here: The function interface
+ * is not thread-safe, because threads can never be sure when
+ * some other thread destroys the data they were given a pointer to.
+ */
+ CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
+# endif
j=strlen(name);
if (j < 128)
{
if (i == GHBN_NUM) /* no hit*/
{
BIO_ghbn_miss++;
+ /* Note: under VMS with SOCKETSHR, it seems like the first
+ * parameter is 'char *', instead of 'const char *'
+ */
+# ifndef CONST_STRICT
+ ret=gethostbyname((char *)name);
+# else
ret=gethostbyname(name);
+# endif
- if (ret == NULL) return(NULL);
- if (j > 128) return(ret); /* too big to cache */
+ if (ret == NULL)
+ goto end;
+ if (j > 128) /* too big to cache */
+ {
+# if 0
+ /* If we were trying to make this function thread-safe (which
+ * is bound to fail), we'd have to give up in this case
+ * (or allocate more memory). */
+ ret = NULL;
+# endif
+ goto end;
+ }
/* else add to cache */
if (ghbn_cache[lowi].ent != NULL)
- ghbn_free(ghbn_cache[lowi].ent);
+ ghbn_free(ghbn_cache[lowi].ent); /* XXX not thread-safe */
+ ghbn_cache[lowi].name[0] = '\0';
+ if((ret=ghbn_cache[lowi].ent=ghbn_dup(ret)) == NULL)
+ {
+ BIOerr(BIO_F_BIO_GETHOSTBYNAME,ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
strncpy(ghbn_cache[lowi].name,name,128);
- ghbn_cache[lowi].ent=ghbn_dup(ret);
ghbn_cache[lowi].order=BIO_ghbn_miss+BIO_ghbn_hits;
}
else
ret= ghbn_cache[i].ent;
ghbn_cache[i].order=BIO_ghbn_miss+BIO_ghbn_hits;
}
- CRYPTO_w_unlock(CRYPTO_LOCK_BIO_GETHOSTBYNAME);
+end:
+# if 0
+ CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
+# endif
return(ret);
+#endif
}
-int BIO_sock_init()
+
+int BIO_sock_init(void)
{
-#ifdef WINDOWS
+#ifdef OPENSSL_SYS_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)
+ /* Not making wsa_state available to the rest of the
+ * code is formally wrong. But the structures we use
+ * are [beleived 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);
return(-1);
}
}
-#endif /* WINDOWS */
+#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 BIO_sock_cleanup(void)
{
-#ifdef WINDOWS
+#ifdef OPENSSL_SYS_WINDOWS
if (wsa_init_done)
{
wsa_init_done=0;
+#if 0 /* this call is claimed to be non-present in Winsock2 */
WSACancelBlockingCall();
+#endif
WSACleanup();
}
+#elif defined(OPENSSL_SYS_NETWARE) && !defined(NETWARE_BSDSOCK)
+ if (wsa_init_done)
+ {
+ wsa_init_done=0;
+ WSACleanup();
+ }
#endif
}
-int BIO_socket_ioctl(fd,type,arg)
-int fd;
-long type;
-unsigned long *arg;
+#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
i=ioctlsocket(fd,type,arg);
+#endif /* __DJGPP__ */
if (i < 0)
SYSerr(SYS_F_IOCTLSOCKET,get_last_socket_error());
return(i);
}
+#endif /* __VMS_VER */
/* 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];
+static int get_ip(const char *str, unsigned char ip[4])
{
unsigned int tmp[4];
int num=0,c,ok=0;
{
ok=1;
tmp[num]=tmp[num]*10+c-'0';
- if (tmp[num] > 255) return(-1);
+ if (tmp[num] > 255) return(0);
}
else if (c == '.')
{
if (!ok) return(-1);
- if (num == 3) break;
+ if (num == 3) return(0);
num++;
ok=0;
}
- else if ((num == 3) && ok)
+ else if (c == '\0' && (num == 3) && ok)
break;
else
return(0);
return(1);
}
-int BIO_get_accept_socket(host)
-char *host;
+int BIO_get_accept_socket(char *host, int bind_mode)
{
int ret=0;
- struct sockaddr_in server;
- int s= -1;
+ struct sockaddr server,client;
+ struct sockaddr_in *sa_in;
+ int s=INVALID_SOCKET,cs;
unsigned char ip[4];
- short port;
- char *str,*h,*p,*e;
+ unsigned short port;
+ char *str=NULL,*e;
+ char *h,*p;
unsigned long l;
+ int err_num;
- if (!BIO_sock_init()) return(INVALID_SOCKET);
+ if (BIO_sock_init() != 1) return(INVALID_SOCKET);
if ((str=BUF_strdup(host)) == NULL) return(INVALID_SOCKET);
{
if (*e == ':')
{
- p= &(e[1]);
- *e='\0';
+ p=e;
}
else if (*e == '/')
{
break;
}
}
-
- if (p == NULL)
+ if (p) *p++='\0'; /* points at last ':', '::port' is special [see below] */
+ else p=h,h=NULL;
+
+#ifdef EAI_FAMILY
+ do {
+ static union { void *p;
+ int (*f)(const char *,const char *,
+ const struct addrinfo *,
+ struct addrinfo **);
+ } p_getaddrinfo = {NULL};
+ static union { void *p;
+ void (*f)(struct addrinfo *);
+ } p_freeaddrinfo = {NULL};
+ struct addrinfo *res,hint;
+
+ if (p_getaddrinfo.p==NULL)
+ {
+ if ((p_getaddrinfo.p=DSO_global_lookup("getaddrinfo"))==NULL ||
+ (p_freeaddrinfo.p=DSO_global_lookup("freeaddrinfo"))==NULL)
+ p_getaddrinfo.p=(void*)-1;
+ }
+ if (p_getaddrinfo.p==(void *)-1) break;
+
+ /* '::port' enforces IPv6 wildcard listener. Some OSes,
+ * e.g. Solaris, default to IPv6 without any hint. Also
+ * note that commonly IPv6 wildchard socket can service
+ * IPv4 connections just as well... */
+ memset(&hint,0,sizeof(hint));
+ if (h)
{
- p=h;
- h="*";
+ if (strchr(h,':'))
+ {
+ if (h[1]=='\0') h=NULL;
+#ifdef AF_INET6
+ hint.ai_family = AF_INET6;
+#else
+ h=NULL;
+#endif
+ }
+ else if (h[0]=='*' && h[1]=='\0')
+ h=NULL;
}
- if (!BIO_get_port(p,&port)) return(INVALID_SOCKET);
+ if ((*p_getaddrinfo.f)(h,p,&hint,&res)) break;
+ server = *res->ai_addr;
+ (*p_freeaddrinfo.f)(res);
+ goto again;
+ } while (0);
+#endif
+
+ if (!BIO_get_port(p,&port)) goto err;
memset((char *)&server,0,sizeof(server));
- server.sin_family=AF_INET;
- server.sin_port=htons((unsigned short)port);
+ sa_in = (struct sockaddr_in *)&server;
+ sa_in->sin_family=AF_INET;
+ sa_in->sin_port=htons(port);
- if (strcmp(h,"*") == 0)
- server.sin_addr.s_addr=INADDR_ANY;
+ if (h == NULL || strcmp(h,"*") == 0)
+ sa_in->sin_addr.s_addr=INADDR_ANY;
else
{
- if (!BIO_get_host_ip(h,&(ip[0]))) return(INVALID_SOCKET);
+ if (!BIO_get_host_ip(h,&(ip[0]))) goto err;
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);
+ ((unsigned long)ip[1]<<16L)|
+ ((unsigned long)ip[2]<< 8L)|
+ ((unsigned long)ip[3]);
+ sa_in->sin_addr.s_addr=htonl(l);
}
- s=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+again:
+ s=socket(server.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
if (s == INVALID_SOCKET)
{
SYSerr(SYS_F_SOCKET,get_last_socket_error());
BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_CREATE_SOCKET);
goto err;
}
- if (bind(s,(struct sockaddr *)&server,sizeof(server)) == -1)
+
+#ifdef SO_REUSEADDR
+ if (bind_mode == BIO_BIND_REUSEADDR)
{
- SYSerr(SYS_F_BIND,get_last_socket_error());
+ int i=1;
+
+ ret=setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof(i));
+ bind_mode=BIO_BIND_NORMAL;
+ }
+#endif
+ if (bind(s,&server,sizeof(server)) == -1)
+ {
+#ifdef SO_REUSEADDR
+ err_num=get_last_socket_error();
+ if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
+ (err_num == EADDRINUSE))
+ {
+ client = server;
+ if (h == NULL || strcmp(h,"*") == 0)
+ {
+#ifdef AF_INET6
+ if (client.sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6 =
+ (struct sockaddr_in6 *)&client;
+ memset(&sin6->sin6_addr,0,sizeof(sin6->sin6_addr));
+ sin6->sin6_addr.s6_addr[15]=1;
+ }
+ else
+#endif
+ if (client.sa_family == AF_INET)
+ {
+ struct sockaddr_in *sin6 =
+ (struct sockaddr_in *)&client;
+ sin6->sin_addr.s_addr=htonl(0x7F000001);
+ }
+ else goto err;
+ }
+ cs=socket(client.sa_family,SOCK_STREAM,SOCKET_PROTOCOL);
+ if (cs != INVALID_SOCKET)
+ {
+ int ii;
+ ii=connect(cs,(struct sockaddr *)&client,
+ sizeof(client));
+ closesocket(cs);
+ if (ii == INVALID_SOCKET)
+ {
+ bind_mode=BIO_BIND_REUSEADDR;
+ closesocket(s);
+ goto again;
+ }
+ /* else error */
+ }
+ /* else error */
+ }
+#endif
+ SYSerr(SYS_F_BIND,err_num);
ERR_add_error_data(3,"port='",host,"'");
BIOerr(BIO_F_BIO_GET_ACCEPT_SOCKET,BIO_R_UNABLE_TO_BIND_SOCKET);
goto err;
}
ret=1;
err:
- if (str != NULL) Free(str);
+ if (str != NULL) OPENSSL_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 BIO_accept(int sock, char **addr)
{
int ret=INVALID_SOCKET;
- static struct sockaddr_in from;
+ struct sockaddr from;
+ struct sockaddr_in *sa_in;
unsigned long l;
- short port;
+ unsigned short port;
int len;
char *p;
- memset((char *)&from,0,sizeof(from));
+ memset(&from,0,sizeof(from));
len=sizeof(from);
- ret=accept(sock,(struct sockaddr *)&from,&len);
+ /* Note: under VMS with SOCKETSHR the fourth parameter is currently
+ * of type (int *) 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 (int *) or (void *).
+ */
+ ret=accept(sock,&from,(void *)&len);
if (ret == INVALID_SOCKET)
{
+ if(BIO_sock_should_retry(ret)) return -2;
SYSerr(SYS_F_ACCEPT,get_last_socket_error());
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);
+#ifdef EAI_FAMILY
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_BEOS_BONE) || defined(OPENSSL_SYS_MSDOS)
+# define SOCKLEN_T size_t
+# else
+# define SOCKLEN_T socklen_t
+#endif
+ do {
+ char h[NI_MAXHOST],s[NI_MAXSERV];
+ size_t nl;
+ static union { void *p;
+ int (*f)(const struct sockaddr *,SOCKLEN_T,
+ char *,size_t,char *,size_t,int);
+ } p_getnameinfo = {NULL};
+
+ if (p_getnameinfo.p==NULL)
+ {
+ if ((p_getnameinfo.p=DSO_global_lookup("getnameinfo"))==NULL)
+ p_getnameinfo.p=(void*)-1;
+ }
+ if (p_getnameinfo.p==(void *)-1) break;
+
+ if ((*p_getnameinfo.f)(&from,sizeof(from),h,sizeof(h),s,sizeof(s),
+ NI_NUMERICHOST|NI_NUMERICSERV)) break;
+ nl = strlen(h)+strlen(s)+2; if (len<24) len=24;
+ p = *addr;
+ if (p) { *p = '\0'; p = OPENSSL_realloc(p,nl); }
+ else { p = OPENSSL_malloc(nl); }
+ if (p==NULL)
+ {
+ BIOerr(BIO_F_BIO_ACCEPT,ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ *addr = p;
+ BIO_snprintf(*addr,nl,"%s:%s",h,s);
+ goto end;
+ } while(0);
+#endif
+ if (from.sa_family != AF_INET) goto end;
+ sa_in = (struct sockaddr_in *)&from;
+ l=ntohl(sa_in->sin_addr.s_addr);
+ port=ntohs(sa_in->sin_port);
if (*addr == NULL)
{
- if ((p=Malloc(24)) == NULL)
+ if ((p=OPENSSL_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);
+ BIO_snprintf(*addr,24,"%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 BIO_set_tcp_ndelay(int s, int on)
{
int ret=0;
#if defined(TCP_NODELAY) && (defined(IPPROTO_TCP) || defined(SOL_TCP))
}
#endif
+int BIO_socket_nbio(int s, int mode)
+ {
+ int ret= -1;
+ int l;
+
+ l=mode;
+#ifdef FIONBIO
+ ret=BIO_socket_ioctl(s,FIONBIO,&l);
+#endif
+ return(ret == 0);
+ }