summaryrefslogtreecommitdiffstats
path: root/crypto/bio/bss_conn.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/bio/bss_conn.c')
-rw-r--r--crypto/bio/bss_conn.c348
1 files changed, 219 insertions, 129 deletions
diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c
index 4e31e3c1f8..6e547bf866 100644
--- a/crypto/bio/bss_conn.c
+++ b/crypto/bio/bss_conn.c
@@ -1,5 +1,5 @@
/* crypto/bio/bss_conn.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
@@ -88,6 +88,11 @@ typedef struct bio_connect_st
/* int socket; this will be kept in bio->num so that it is
* compatable with the bss_sock bio */
int error;
+
+ /* called when the connection is initially made
+ * callback(BIO,state,ret); The callback should return
+ * 'ret'. state is for compatablity with the ssl info_callback */
+ int (*info_callback)();
} BIO_CONNECT;
#ifndef NOPROTO
@@ -122,18 +127,10 @@ void BIO_CONNECT_free();
#endif
-#define CONN_S_BEFORE 1
-#define CONN_S_GET_IP 2
-#define CONN_S_GET_PORT 3
-#define CONN_S_CREATE_SOCKET 4
-#define CONN_S_CONNECT 5
-#define CONN_S_OK 6
-#define CONN_S_BLOCKED_CONNECT 7
-#define CONN_S_NBIO 8
-
static BIO_METHOD methods_connectp=
{
- BIO_TYPE_CONNECT,"socket connect",
+ BIO_TYPE_CONNECT,
+ "socket connect",
conn_write,
conn_read,
conn_puts,
@@ -150,143 +147,192 @@ BIO_CONNECT *c;
int ret= -1,i;
unsigned long l;
char *p,*q;
+ int (*cb)()=NULL;
- switch (c->state)
- {
- case CONN_S_BEFORE:
- p=c->param_hostname;
- if (p == NULL)
- {
- BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTHNAME_SPECIFIED);
- break;
- }
- for ( ; *p != '\0'; p++)
- {
- if ((*p == ':') || (*p == '/')) break;
- }
+ if (c->info_callback != NULL)
+ cb=c->info_callback;
- i= *p;
- if ((i == ':') || (i == '/'))
+ for (;;)
+ {
+ switch (c->state)
{
+ case BIO_CONN_S_BEFORE:
+ p=c->param_hostname;
+ if (p == NULL)
+ {
+ BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTHNAME_SPECIFIED);
+ goto exit_loop;
+ }
+ for ( ; *p != '\0'; p++)
+ {
+ if ((*p == ':') || (*p == '/')) break;
+ }
- *(p++)='\0';
- if (i == ':')
+ i= *p;
+ if ((i == ':') || (i == '/'))
{
- for (q=p; *q; q++)
- if (*q == '/')
- {
- *q='\0';
- break;
- }
- if (c->param_port != NULL)
- Free(c->param_port);
- c->param_port=BUF_strdup(p);
+
+ *(p++)='\0';
+ if (i == ':')
+ {
+ for (q=p; *q; q++)
+ if (*q == '/')
+ {
+ *q='\0';
+ break;
+ }
+ if (c->param_port != NULL)
+ Free(c->param_port);
+ c->param_port=BUF_strdup(p);
+ }
}
- }
- if (p == NULL)
- {
- BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
+ if (p == NULL)
+ {
+ BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
+ ERR_add_error_data(2,"host=",c->param_hostname);
+ goto exit_loop;
+ }
+ c->state=BIO_CONN_S_GET_IP;
break;
- }
- c->state=CONN_S_GET_IP;
- case CONN_S_GET_IP:
- if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
+ case BIO_CONN_S_GET_IP:
+ if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
+ goto exit_loop;
+ c->state=BIO_CONN_S_GET_PORT;
break;
- c->state=CONN_S_GET_PORT;
- case CONN_S_GET_PORT:
- if (BIO_get_port(c->param_port,&c->port) <= 0)
+ case BIO_CONN_S_GET_PORT:
+ if (BIO_get_port(c->param_port,&c->port) <= 0)
+ goto exit_loop;
+ c->state=BIO_CONN_S_CREATE_SOCKET;
break;
- c->state=CONN_S_CREATE_SOCKET;
-
- case CONN_S_CREATE_SOCKET:
- /* now setup address */
- memset((char *)&c->them,0,sizeof(c->them));
- c->them.sin_family=AF_INET;
- c->them.sin_port=htons((unsigned short)c->port);
- l=(unsigned long)
- ((unsigned long)c->ip[0]<<24L)|
- ((unsigned long)c->ip[1]<<16L)|
- ((unsigned long)c->ip[2]<< 8L)|
- ((unsigned long)c->ip[3]);
- c->them.sin_addr.s_addr=htonl(l);
- c->state=CONN_S_CREATE_SOCKET;
-
- ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
- if (ret == INVALID_SOCKET)
- {
- SYSerr(SYS_F_SOCKET,errno);
- BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
+
+ case BIO_CONN_S_CREATE_SOCKET:
+ /* now setup address */
+ memset((char *)&c->them,0,sizeof(c->them));
+ c->them.sin_family=AF_INET;
+ c->them.sin_port=htons((unsigned short)c->port);
+ l=(unsigned long)
+ ((unsigned long)c->ip[0]<<24L)|
+ ((unsigned long)c->ip[1]<<16L)|
+ ((unsigned long)c->ip[2]<< 8L)|
+ ((unsigned long)c->ip[3]);
+ c->them.sin_addr.s_addr=htonl(l);
+ c->state=BIO_CONN_S_CREATE_SOCKET;
+
+ ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
+ if (ret == INVALID_SOCKET)
+ {
+ SYSerr(SYS_F_SOCKET,get_last_socket_error());
+ ERR_add_error_data(4,"host=",c->param_hostname,
+ ":",c->param_port);
+ BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
+ goto exit_loop;
+ }
+ b->num=ret;
+ c->state=BIO_CONN_S_NBIO;
break;
- }
- b->num=ret;
- c->state=CONN_S_NBIO;
- case CONN_S_NBIO:
+ case BIO_CONN_S_NBIO:
#ifdef FIONBIO
- if (c->nbio)
- {
- l=1;
- ret=BIO_socket_ioctl(b->num,FIONBIO,&l);
- if (ret < 0)
+ if (c->nbio)
{
- BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
- break;
+ l=1;
+ ret=BIO_socket_ioctl(b->num,FIONBIO,&l);
+ if (ret < 0)
+ {
+ BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
+ ERR_add_error_data(4,"host=",
+ c->param_hostname,
+ ":",c->param_port);
+ goto exit_loop;
+ }
}
- }
#endif
- c->state=CONN_S_CONNECT;
+ c->state=BIO_CONN_S_CONNECT;
- case CONN_S_CONNECT:
- BIO_clear_retry_flags(b);
- ret=connect(b->num,
- (struct sockaddr *)&c->them,
- sizeof(c->them));
- b->retry_reason=0;
- if (ret < 0)
- {
- if (BIO_sock_should_retry(ret))
+#ifdef SO_KEEPALIVE
+ i=1;
+ i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
+ if (i < 0)
{
- BIO_set_retry_special(b);
- c->state=CONN_S_BLOCKED_CONNECT;
- b->retry_reason=BIO_RR_CONNECT;
+ SYSerr(SYS_F_SOCKET,get_last_socket_error());
+ ERR_add_error_data(4,"host=",c->param_hostname,
+ ":",c->param_port);
+ BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE);
+ goto exit_loop;
+ }
+#endif
+ break;
+
+ case BIO_CONN_S_CONNECT:
+ BIO_clear_retry_flags(b);
+ ret=connect(b->num,
+ (struct sockaddr *)&c->them,
+ sizeof(c->them));
+ b->retry_reason=0;
+ if (ret < 0)
+ {
+ if (BIO_sock_should_retry(ret))
+ {
+ BIO_set_retry_special(b);
+ c->state=BIO_CONN_S_BLOCKED_CONNECT;
+ b->retry_reason=BIO_RR_CONNECT;
+ }
+ else
+ {
+ SYSerr(SYS_F_CONNECT,get_last_socket_error());
+ ERR_add_error_data(4,"host=",
+ c->param_hostname,
+ ":",c->param_port);
+ BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
+ }
+ goto exit_loop;
}
else
+ c->state=BIO_CONN_S_OK;
+ break;
+
+ case BIO_CONN_S_BLOCKED_CONNECT:
+ i=BIO_sock_error(b->num);
+ if (i)
{
- SYSerr(SYS_F_CONNECT,errno);
- BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
+ BIO_clear_retry_flags(b);
+ SYSerr(SYS_F_CONNECT,i);
+ ERR_add_error_data(4,"host=",
+ c->param_hostname,
+ ":",c->param_port);
+ BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
+ ret=0;
+ goto exit_loop;
}
- }
- else
- {
+ else
+ c->state=BIO_CONN_S_OK;
+ break;
+
+ case BIO_CONN_S_OK:
ret=1;
- c->state=CONN_S_OK;
+ goto exit_loop;
+ default:
+ abort();
+ goto exit_loop;
}
- break;
- case CONN_S_BLOCKED_CONNECT:
- BIO_clear_retry_flags(b);
- i=BIO_sock_error(b->num);
- if (i)
+ if (cb != NULL)
{
- SYSerr(SYS_F_CONNECT,i);
- BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
+ if (!(ret=cb((BIO *)b,c->state,ret)))
+ goto end;
}
- else
- {
- c->state=CONN_S_OK;
- ret=1;
- }
- break;
+ }
- case CONN_S_OK:
- ret=1;
- break;
- default:
- abort();
+ if (1)
+ {
+exit_loop:
+ if (cb != NULL)
+ ret=cb((BIO *)b,c->state,ret);
}
+end:
return(ret);
}
@@ -296,9 +342,10 @@ BIO_CONNECT *BIO_CONNECT_new()
if ((ret=(BIO_CONNECT *)Malloc(sizeof(BIO_CONNECT))) == NULL)
return(NULL);
- ret->state=CONN_S_BEFORE;
+ ret->state=BIO_CONN_S_BEFORE;
ret->param_hostname=NULL;
ret->param_port=NULL;
+ ret->info_callback=NULL;
ret->nbio=0;
ret->ip[0]=0;
ret->ip[1]=0;
@@ -346,7 +393,7 @@ BIO *bio;
if (bio->num != INVALID_SOCKET)
{
/* Only do a shutdown if things were established */
- if (c->state == CONN_S_OK)
+ if (c->state == BIO_CONN_S_OK)
shutdown(bio->num,2);
# ifdef WINDOWS
closesocket(bio->num);
@@ -385,15 +432,16 @@ int outl;
BIO_CONNECT *data;
data=(BIO_CONNECT *)b->ptr;
- if (data->state != CONN_S_OK)
+ if (data->state != BIO_CONN_S_OK)
{
ret=conn_state(b,data);
- if (ret <= 0) return(ret);
+ if (ret <= 0)
+ return(ret);
}
if (out != NULL)
{
- errno=0;
+ clear_socket_error();
#if defined(WINDOWS)
ret=recv(b->num,out,outl,0);
#else
@@ -418,13 +466,13 @@ int inl;
BIO_CONNECT *data;
data=(BIO_CONNECT *)b->ptr;
- if (data->state != CONN_S_OK)
+ if (data->state != BIO_CONN_S_OK)
{
ret=conn_state(b,data);
if (ret <= 0) return(ret);
}
- errno=0;
+ clear_socket_error();
#if defined(WINDOWS)
ret=send(b->num,in,inl,0);
#else
@@ -447,6 +495,7 @@ char *ptr;
{
BIO *dbio;
int *ip;
+ char **pptr;
long ret=1;
BIO_CONNECT *data;
@@ -456,17 +505,43 @@ char *ptr;
{
case BIO_CTRL_RESET:
ret=0;
- data->state=CONN_S_BEFORE;
+ data->state=BIO_CONN_S_BEFORE;
conn_close_socket(b);
b->flags=0;
break;
case BIO_C_DO_STATE_MACHINE:
/* use this one to start the connection */
- if (!data->state != CONN_S_OK)
+ if (!data->state != BIO_CONN_S_OK)
ret=(long)conn_state(b,data);
else
ret=1;
break;
+ case BIO_C_GET_CONNECT:
+ if (ptr != NULL)
+ {
+ pptr=(char **)ptr;
+ if (num == 0)
+ {
+ *pptr=data->param_hostname;
+
+ }
+ else if (num == 1)
+ {
+ *pptr=data->param_port;
+ }
+ else if (num == 2)
+ {
+ *pptr= (char *)&(data->ip[0]);
+ }
+ else if (num == 3)
+ {
+ *((int *)ptr)=data->port;
+ }
+ if ((!b->init) || (ptr == NULL))
+ *pptr="not initalised";
+ ret=1;
+ }
+ break;
case BIO_C_SET_CONNECT:
if (ptr != NULL)
{
@@ -483,6 +558,10 @@ char *ptr;
Free(data->param_port);
data->param_port=BUF_strdup(ptr);
}
+ else if (num == 2)
+ memcpy(data->ip,ptr,4);
+ else if (num == 3)
+ data->port= *(int *)ptr;
}
break;
case BIO_C_SET_NBIO:
@@ -514,12 +593,23 @@ char *ptr;
case BIO_CTRL_DUP:
dbio=(BIO *)ptr;
if (data->param_port)
- BIO_set_port(dbio,data->param_port);
+ BIO_set_conn_port(dbio,data->param_port);
if (data->param_hostname)
- BIO_set_hostname(dbio,data->param_hostname);
+ BIO_set_conn_hostname(dbio,data->param_hostname);
BIO_set_nbio(dbio,data->nbio);
+ BIO_set_info_callback(dbio,data->info_callback);
break;
+ case BIO_CTRL_SET_CALLBACK:
+ data->info_callback=(int (*)())ptr;
+ break;
+ case BIO_CTRL_GET_CALLBACK:
+ {
+ int (**fptr)();
+ fptr=(int (**)())ptr;
+ *fptr=data->info_callback;
+ }
+ break;
default:
ret=0;
break;
@@ -545,7 +635,7 @@ char *str;
ret=BIO_new(BIO_s_connect());
if (ret == NULL) return(NULL);
- if (BIO_set_hostname(ret,str))
+ if (BIO_set_conn_hostname(ret,str))
return(ret);
else
{