ssl/libcrypto/src/crypto/bio/bss_conn.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* crypto/bio/bss_conn.c */
       
     2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
       
     3  * All rights reserved.
       
     4  *
       
     5  * This package is an SSL implementation written
       
     6  * by Eric Young (eay@cryptsoft.com).
       
     7  * The implementation was written so as to conform with Netscapes SSL.
       
     8  * 
       
     9  * This library is free for commercial and non-commercial use as long as
       
    10  * the following conditions are aheared to.  The following conditions
       
    11  * apply to all code found in this distribution, be it the RC4, RSA,
       
    12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
       
    13  * included with this distribution is covered by the same copyright terms
       
    14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
       
    15  * 
       
    16  * Copyright remains Eric Young's, and as such any Copyright notices in
       
    17  * the code are not to be removed.
       
    18  * If this package is used in a product, Eric Young should be given attribution
       
    19  * as the author of the parts of the library used.
       
    20  * This can be in the form of a textual message at program startup or
       
    21  * in documentation (online or textual) provided with the package.
       
    22  * 
       
    23  * Redistribution and use in source and binary forms, with or without
       
    24  * modification, are permitted provided that the following conditions
       
    25  * are met:
       
    26  * 1. Redistributions of source code must retain the copyright
       
    27  *    notice, this list of conditions and the following disclaimer.
       
    28  * 2. Redistributions in binary form must reproduce the above copyright
       
    29  *    notice, this list of conditions and the following disclaimer in the
       
    30  *    documentation and/or other materials provided with the distribution.
       
    31  * 3. All advertising materials mentioning features or use of this software
       
    32  *    must display the following acknowledgement:
       
    33  *    "This product includes cryptographic software written by
       
    34  *     Eric Young (eay@cryptsoft.com)"
       
    35  *    The word 'cryptographic' can be left out if the rouines from the library
       
    36  *    being used are not cryptographic related :-).
       
    37  * 4. If you include any Windows specific code (or a derivative thereof) from 
       
    38  *    the apps directory (application code) you must include an acknowledgement:
       
    39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
       
    40  * 
       
    41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
       
    42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
       
    45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    51  * SUCH DAMAGE.
       
    52  * 
       
    53  * The licence and distribution terms for any publically available version or
       
    54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
       
    55  * copied and put under another distribution licence
       
    56  * [including the GNU Public Licence.]
       
    57  */
       
    58 /*
       
    59  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
    60  */
       
    61 
       
    62 
       
    63 #include <stdio.h>
       
    64 #include <errno.h>
       
    65 #define USE_SOCKETS
       
    66 #include "cryptlib.h"
       
    67 #include <openssl/bio.h>
       
    68 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
       
    69 #include "libcrypto_wsd_macros.h"
       
    70 #include "libcrypto_wsd.h"
       
    71 #endif
       
    72 
       
    73 #ifndef OPENSSL_NO_SOCK
       
    74 
       
    75 #ifdef OPENSSL_SYS_WIN16
       
    76 #define SOCKET_PROTOCOL 0 /* more microsoft stupidity */
       
    77 #else
       
    78 #define SOCKET_PROTOCOL IPPROTO_TCP
       
    79 #endif
       
    80 
       
    81 #if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000)
       
    82 /* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */
       
    83 #undef FIONBIO
       
    84 #endif
       
    85 
       
    86 
       
    87 typedef struct bio_connect_st
       
    88 	{
       
    89 	int state;
       
    90 
       
    91 	char *param_hostname;
       
    92 	char *param_port;
       
    93 	int nbio;
       
    94 
       
    95 	unsigned char ip[4];
       
    96 	unsigned short port;
       
    97 
       
    98 	struct sockaddr_in them;
       
    99 
       
   100 	/* int socket; this will be kept in bio->num so that it is
       
   101 	 * compatible with the bss_sock bio */ 
       
   102 
       
   103 	/* called when the connection is initially made
       
   104 	 *  callback(BIO,state,ret);  The callback should return
       
   105 	 * 'ret'.  state is for compatibility with the ssl info_callback */
       
   106 	int (*info_callback)(const BIO *bio,int state,int ret);
       
   107 	} BIO_CONNECT;
       
   108 
       
   109 static int conn_write(BIO *h, const char *buf, int num);
       
   110 static int conn_read(BIO *h, char *buf, int size);
       
   111 static int conn_puts(BIO *h, const char *str);
       
   112 static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
       
   113 static int conn_new(BIO *h);
       
   114 static int conn_free(BIO *data);
       
   115 static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *);
       
   116 
       
   117 static int conn_state(BIO *b, BIO_CONNECT *c);
       
   118 static void conn_close_socket(BIO *data);
       
   119 BIO_CONNECT *BIO_CONNECT_new(void );
       
   120 void BIO_CONNECT_free(BIO_CONNECT *a);
       
   121 
       
   122 #ifndef EMULATOR
       
   123 static BIO_METHOD methods_connectp=
       
   124 	{
       
   125 	BIO_TYPE_CONNECT,
       
   126 	"socket connect",
       
   127 	conn_write,
       
   128 	conn_read,
       
   129 	conn_puts,
       
   130 	NULL, /* connect_gets, */
       
   131 	conn_ctrl,
       
   132 	conn_new,
       
   133 	conn_free,
       
   134 	conn_callback_ctrl,
       
   135 	};
       
   136 #else
       
   137 
       
   138 GET_STATIC_VAR_FROM_TLS(methods_connectp,bss_conn,BIO_METHOD)
       
   139 #define methods_connectp (*GET_WSD_VAR_NAME(methods_connectp,bss_conn,s)())
       
   140 const BIO_METHOD temp_s_methods_connectp=
       
   141 	{
       
   142 	BIO_TYPE_CONNECT,
       
   143 	"socket connect",
       
   144 	conn_write,
       
   145 	conn_read,
       
   146 	conn_puts,
       
   147 	NULL, /* connect_gets, */
       
   148 	conn_ctrl,
       
   149 	conn_new,
       
   150 	conn_free,
       
   151 	conn_callback_ctrl,
       
   152 	};
       
   153 #endif		
       
   154 
       
   155 static int conn_state(BIO *b, BIO_CONNECT *c)
       
   156 	{
       
   157 	int ret= -1,i;
       
   158 	unsigned long l;
       
   159 	char *p,*q;
       
   160 	int (*cb)(const BIO *,int,int)=NULL;
       
   161 
       
   162 	if (c->info_callback != NULL)
       
   163 		cb=c->info_callback;
       
   164 
       
   165 	for (;;)
       
   166 		{
       
   167 		switch (c->state)
       
   168 			{
       
   169 		case BIO_CONN_S_BEFORE:
       
   170 			p=c->param_hostname;
       
   171 			if (p == NULL)
       
   172 				{
       
   173 				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED);
       
   174 				goto exit_loop;
       
   175 				}
       
   176 			for ( ; *p != '\0'; p++)
       
   177 				{
       
   178 				if ((*p == ':') || (*p == '/')) break;
       
   179 				}
       
   180 
       
   181 			i= *p;
       
   182 			if ((i == ':') || (i == '/'))
       
   183 				{
       
   184 
       
   185 				*(p++)='\0';
       
   186 				if (i == ':')
       
   187 					{
       
   188 					for (q=p; *q; q++)
       
   189 						if (*q == '/')
       
   190 							{
       
   191 							*q='\0';
       
   192 							break;
       
   193 							}
       
   194 					if (c->param_port != NULL)
       
   195 						OPENSSL_free(c->param_port);
       
   196 					c->param_port=BUF_strdup(p);
       
   197 					}
       
   198 				}
       
   199 
       
   200 			if (c->param_port == NULL)
       
   201 				{
       
   202 				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
       
   203 				ERR_add_error_data(2,"host=",c->param_hostname);
       
   204 				goto exit_loop;
       
   205 				}
       
   206 			c->state=BIO_CONN_S_GET_IP;
       
   207 			break;
       
   208 
       
   209 		case BIO_CONN_S_GET_IP:
       
   210 			if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
       
   211 				goto exit_loop;
       
   212 			c->state=BIO_CONN_S_GET_PORT;
       
   213 			break;
       
   214 
       
   215 		case BIO_CONN_S_GET_PORT:
       
   216 			if (c->param_port == NULL)
       
   217 				{
       
   218 				/* abort(); */
       
   219 				goto exit_loop;
       
   220 				}
       
   221 			else if (BIO_get_port(c->param_port,&c->port) <= 0)
       
   222 				goto exit_loop;
       
   223 			c->state=BIO_CONN_S_CREATE_SOCKET;
       
   224 			break;
       
   225 
       
   226 		case BIO_CONN_S_CREATE_SOCKET:
       
   227 			/* now setup address */
       
   228 			memset((char *)&c->them,0,sizeof(c->them));
       
   229 			c->them.sin_family=AF_INET;
       
   230 			c->them.sin_port=htons((unsigned short)c->port);
       
   231 			l=(unsigned long)
       
   232 				((unsigned long)c->ip[0]<<24L)|
       
   233 				((unsigned long)c->ip[1]<<16L)|
       
   234 				((unsigned long)c->ip[2]<< 8L)|
       
   235 				((unsigned long)c->ip[3]);
       
   236 			c->them.sin_addr.s_addr=htonl(l);
       
   237 			c->state=BIO_CONN_S_CREATE_SOCKET;
       
   238 
       
   239 			ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
       
   240 			if (ret == INVALID_SOCKET)
       
   241 				{
       
   242 				SYSerr(SYS_F_SOCKET,get_last_socket_error());
       
   243 				ERR_add_error_data(4,"host=",c->param_hostname,
       
   244 					":",c->param_port);
       
   245 				BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
       
   246 				goto exit_loop;
       
   247 				}
       
   248 			b->num=ret;
       
   249 			c->state=BIO_CONN_S_NBIO;
       
   250 			break;
       
   251 
       
   252 		case BIO_CONN_S_NBIO:
       
   253 			if (c->nbio)
       
   254 				{
       
   255 				if (!BIO_socket_nbio(b->num,1))
       
   256 					{
       
   257 					BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
       
   258 					ERR_add_error_data(4,"host=",
       
   259 						c->param_hostname,
       
   260 						":",c->param_port);
       
   261 					goto exit_loop;
       
   262 					}
       
   263 				}
       
   264 			c->state=BIO_CONN_S_CONNECT;
       
   265 
       
   266 #if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
       
   267 			i=1;
       
   268 			i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
       
   269 			if (i < 0)
       
   270 				{
       
   271 				SYSerr(SYS_F_SOCKET,get_last_socket_error());
       
   272 				ERR_add_error_data(4,"host=",c->param_hostname,
       
   273 					":",c->param_port);
       
   274 				BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE);
       
   275 				goto exit_loop;
       
   276 				}
       
   277 #endif
       
   278 			break;
       
   279 
       
   280 		case BIO_CONN_S_CONNECT:
       
   281 			BIO_clear_retry_flags(b);
       
   282 			ret=connect(b->num,
       
   283 				(struct sockaddr *)&c->them,
       
   284 				sizeof(c->them));
       
   285 			b->retry_reason=0;
       
   286 			if (ret < 0)
       
   287 				{
       
   288 				if (BIO_sock_should_retry(ret))
       
   289 					{
       
   290 					BIO_set_retry_special(b);
       
   291 					c->state=BIO_CONN_S_BLOCKED_CONNECT;
       
   292 					b->retry_reason=BIO_RR_CONNECT;
       
   293 					}
       
   294 				else
       
   295 					{
       
   296 					SYSerr(SYS_F_CONNECT,get_last_socket_error());
       
   297 					ERR_add_error_data(4,"host=",
       
   298 						c->param_hostname,
       
   299 						":",c->param_port);
       
   300 					BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
       
   301 					}
       
   302 				goto exit_loop;
       
   303 				}
       
   304 			else
       
   305 				c->state=BIO_CONN_S_OK;
       
   306 			break;
       
   307 
       
   308 		case BIO_CONN_S_BLOCKED_CONNECT:
       
   309 			i=BIO_sock_error(b->num);
       
   310 			if (i)
       
   311 				{
       
   312 				BIO_clear_retry_flags(b);
       
   313 				SYSerr(SYS_F_CONNECT,i);
       
   314 				ERR_add_error_data(4,"host=",
       
   315 					c->param_hostname,
       
   316 					":",c->param_port);
       
   317 				BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
       
   318 				ret=0;
       
   319 				goto exit_loop;
       
   320 				}
       
   321 			else
       
   322 				c->state=BIO_CONN_S_OK;
       
   323 			break;
       
   324 
       
   325 		case BIO_CONN_S_OK:
       
   326 			ret=1;
       
   327 			goto exit_loop;
       
   328 		default:
       
   329 			/* abort(); */
       
   330 			goto exit_loop;
       
   331 			}
       
   332 
       
   333 		if (cb != NULL)
       
   334 			{
       
   335 			if (!(ret=cb((BIO *)b,c->state,ret)))
       
   336 				goto end;
       
   337 			}
       
   338 		}
       
   339 
       
   340 	/* Loop does not exit */
       
   341 exit_loop:
       
   342 	if (cb != NULL)
       
   343 		ret=cb((BIO *)b,c->state,ret);
       
   344 end:
       
   345 	return(ret);
       
   346 	}
       
   347 
       
   348 EXPORT_C BIO_CONNECT *BIO_CONNECT_new(void)
       
   349 	{
       
   350 	BIO_CONNECT *ret;
       
   351 
       
   352 	if ((ret=(BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL)
       
   353 		return(NULL);
       
   354 	ret->state=BIO_CONN_S_BEFORE;
       
   355 	ret->param_hostname=NULL;
       
   356 	ret->param_port=NULL;
       
   357 	ret->info_callback=NULL;
       
   358 	ret->nbio=0;
       
   359 	ret->ip[0]=0;
       
   360 	ret->ip[1]=0;
       
   361 	ret->ip[2]=0;
       
   362 	ret->ip[3]=0;
       
   363 	ret->port=0;
       
   364 	memset((char *)&ret->them,0,sizeof(ret->them));
       
   365 	return(ret);
       
   366 	}
       
   367 
       
   368 EXPORT_C void BIO_CONNECT_free(BIO_CONNECT *a)
       
   369 	{
       
   370 	if(a == NULL)
       
   371 	    return;
       
   372 
       
   373 	if (a->param_hostname != NULL)
       
   374 		OPENSSL_free(a->param_hostname);
       
   375 	if (a->param_port != NULL)
       
   376 		OPENSSL_free(a->param_port);
       
   377 	OPENSSL_free(a);
       
   378 	}
       
   379 
       
   380 EXPORT_C BIO_METHOD *BIO_s_connect(void)
       
   381 	{
       
   382 	return(&methods_connectp);
       
   383 	}
       
   384 
       
   385 static int conn_new(BIO *bi)
       
   386 	{
       
   387 	bi->init=0;
       
   388 	bi->num=INVALID_SOCKET;
       
   389 	bi->flags=0;
       
   390 	if ((bi->ptr=(char *)BIO_CONNECT_new()) == NULL)
       
   391 		return(0);
       
   392 	else
       
   393 		return(1);
       
   394 	}
       
   395 
       
   396 static void conn_close_socket(BIO *bio)
       
   397 	{
       
   398 	BIO_CONNECT *c;
       
   399 
       
   400 	c=(BIO_CONNECT *)bio->ptr;
       
   401 	if (bio->num != INVALID_SOCKET)
       
   402 		{
       
   403 		/* Only do a shutdown if things were established */
       
   404 		if (c->state == BIO_CONN_S_OK)
       
   405 			shutdown(bio->num,2);
       
   406 		closesocket(bio->num);
       
   407 		bio->num=INVALID_SOCKET;
       
   408 		}
       
   409 	}
       
   410 
       
   411 static int conn_free(BIO *a)
       
   412 	{
       
   413 	BIO_CONNECT *data;
       
   414 
       
   415 	if (a == NULL) return(0);
       
   416 	data=(BIO_CONNECT *)a->ptr;
       
   417 	 
       
   418 	if (a->shutdown)
       
   419 		{
       
   420 		conn_close_socket(a);
       
   421 		BIO_CONNECT_free(data);
       
   422 		a->ptr=NULL;
       
   423 		a->flags=0;
       
   424 		a->init=0;
       
   425 		}
       
   426 	return(1);
       
   427 	}
       
   428 	
       
   429 static int conn_read(BIO *b, char *out, int outl)
       
   430 	{
       
   431 	int ret=0;
       
   432 	BIO_CONNECT *data;
       
   433 
       
   434 	data=(BIO_CONNECT *)b->ptr;
       
   435 	if (data->state != BIO_CONN_S_OK)
       
   436 		{
       
   437 		ret=conn_state(b,data);
       
   438 		if (ret <= 0)
       
   439 				return(ret);
       
   440 		}
       
   441 
       
   442 	if (out != NULL)
       
   443 		{
       
   444 		clear_socket_error();
       
   445 		ret=readsocket(b->num,out,outl);
       
   446 		BIO_clear_retry_flags(b);
       
   447 		if (ret <= 0)
       
   448 			{
       
   449 			if (BIO_sock_should_retry(ret))
       
   450 				BIO_set_retry_read(b);
       
   451 			}
       
   452 		}
       
   453 	return(ret);
       
   454 	}
       
   455 
       
   456 static int conn_write(BIO *b, const char *in, int inl)
       
   457 	{
       
   458 	int ret;
       
   459 	BIO_CONNECT *data;
       
   460 
       
   461 	data=(BIO_CONNECT *)b->ptr;
       
   462 	if (data->state != BIO_CONN_S_OK)
       
   463 		{
       
   464 		ret=conn_state(b,data);
       
   465 		if (ret <= 0) return(ret);
       
   466 		}
       
   467 
       
   468 	clear_socket_error();
       
   469 	ret=writesocket(b->num,in,inl);
       
   470 	BIO_clear_retry_flags(b);
       
   471 	if (ret <= 0)
       
   472 		{
       
   473 		if (BIO_sock_should_retry(ret))
       
   474 			BIO_set_retry_write(b);
       
   475 		}
       
   476 	return(ret);
       
   477 	}
       
   478 
       
   479 static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
       
   480 	{
       
   481 	BIO *dbio;
       
   482 	int *ip;
       
   483 	const char **pptr;
       
   484 	long ret=1;
       
   485 	BIO_CONNECT *data;
       
   486 
       
   487 	data=(BIO_CONNECT *)b->ptr;
       
   488 
       
   489 	switch (cmd)
       
   490 		{
       
   491 	case BIO_CTRL_RESET:
       
   492 		ret=0;
       
   493 		data->state=BIO_CONN_S_BEFORE;
       
   494 		conn_close_socket(b);
       
   495 		b->flags=0;
       
   496 		break;
       
   497 	case BIO_C_DO_STATE_MACHINE:
       
   498 		/* use this one to start the connection */
       
   499 		if (data->state != BIO_CONN_S_OK)
       
   500 		ret=(long)conn_state(b,data);
       
   501 		else
       
   502 			ret=1;
       
   503 		break;
       
   504 	case BIO_C_GET_CONNECT:
       
   505 		if (ptr != NULL)
       
   506 			{
       
   507 			pptr=(const char **)ptr;
       
   508 			if (num == 0)
       
   509 				{
       
   510 				*pptr=data->param_hostname;
       
   511 
       
   512 				}
       
   513 			else if (num == 1)
       
   514 				{
       
   515 				*pptr=data->param_port;
       
   516 				}
       
   517 			else if (num == 2)
       
   518 				{
       
   519 				*pptr= (char *)&(data->ip[0]);
       
   520 				}
       
   521 			else if (num == 3)
       
   522 				{
       
   523 				*((int *)ptr)=data->port;
       
   524 				}
       
   525 			if ((!b->init) || (ptr == NULL))
       
   526 				*pptr="not initialized";
       
   527 			ret=1;
       
   528 			}
       
   529 		break;
       
   530 	case BIO_C_SET_CONNECT:
       
   531 		if (ptr != NULL)
       
   532 			{
       
   533 			b->init=1;
       
   534 			if (num == 0)
       
   535 				{
       
   536 				if (data->param_hostname != NULL)
       
   537 					OPENSSL_free(data->param_hostname);
       
   538 				data->param_hostname=BUF_strdup(ptr);
       
   539 				}
       
   540 			else if (num == 1)
       
   541 				{
       
   542 				if (data->param_port != NULL)
       
   543 					OPENSSL_free(data->param_port);
       
   544 				data->param_port=BUF_strdup(ptr);
       
   545 				}
       
   546 			else if (num == 2)
       
   547 				{
       
   548 				char buf[16];
       
   549 				unsigned char *p = ptr;
       
   550 
       
   551 				BIO_snprintf(buf,sizeof buf,"%d.%d.%d.%d",
       
   552 					     p[0],p[1],p[2],p[3]);
       
   553 				if (data->param_hostname != NULL)
       
   554 					OPENSSL_free(data->param_hostname);
       
   555 				data->param_hostname=BUF_strdup(buf);
       
   556 				memcpy(&(data->ip[0]),ptr,4);
       
   557 				}
       
   558 			else if (num == 3)
       
   559 				{
       
   560 				char buf[DECIMAL_SIZE(int)+1];
       
   561 
       
   562 				BIO_snprintf(buf,sizeof buf,"%d",*(int *)ptr);
       
   563 				if (data->param_port != NULL)
       
   564 					OPENSSL_free(data->param_port);
       
   565 				data->param_port=BUF_strdup(buf);
       
   566 				data->port= *(int *)ptr;
       
   567 				}
       
   568 			}
       
   569 		break;
       
   570 	case BIO_C_SET_NBIO:
       
   571 		data->nbio=(int)num;
       
   572 		break;
       
   573 	case BIO_C_GET_FD:
       
   574 		if (b->init)
       
   575 			{
       
   576 			ip=(int *)ptr;
       
   577 			if (ip != NULL)
       
   578 				*ip=b->num;
       
   579 			ret=b->num;
       
   580 			}
       
   581 		else
       
   582 			ret= -1;
       
   583 		break;
       
   584 	case BIO_CTRL_GET_CLOSE:
       
   585 		ret=b->shutdown;
       
   586 		break;
       
   587 	case BIO_CTRL_SET_CLOSE:
       
   588 		b->shutdown=(int)num;
       
   589 		break;
       
   590 	case BIO_CTRL_PENDING:
       
   591 	case BIO_CTRL_WPENDING:
       
   592 		ret=0;
       
   593 		break;
       
   594 	case BIO_CTRL_FLUSH:
       
   595 		break;
       
   596 	case BIO_CTRL_DUP:
       
   597 		{
       
   598 		dbio=(BIO *)ptr;
       
   599 		if (data->param_port)
       
   600 			BIO_set_conn_port(dbio,data->param_port);
       
   601 		if (data->param_hostname)
       
   602 			BIO_set_conn_hostname(dbio,data->param_hostname);
       
   603 		BIO_set_nbio(dbio,data->nbio);
       
   604 		/* FIXME: the cast of the function seems unlikely to be a good idea */
       
   605                 (void)BIO_set_info_callback(dbio,(bio_info_cb *)data->info_callback);
       
   606 		}
       
   607 		break;
       
   608 	case BIO_CTRL_SET_CALLBACK:
       
   609 		{
       
   610 #if 0 /* FIXME: Should this be used?  -- Richard Levitte */
       
   611 		BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
       
   612 		ret = -1;
       
   613 #else
       
   614 		ret=0;
       
   615 #endif
       
   616 		}
       
   617 		break;
       
   618 	case BIO_CTRL_GET_CALLBACK:
       
   619 		{
       
   620 		int (**fptr)(const BIO *bio,int state,int xret);
       
   621 
       
   622 		fptr=(int (**)(const BIO *bio,int state,int xret))ptr;
       
   623 		*fptr=data->info_callback;
       
   624 		}
       
   625 		break;
       
   626 	default:
       
   627 		ret=0;
       
   628 		break;
       
   629 		}
       
   630 	return(ret);
       
   631 	}
       
   632 
       
   633 static long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
       
   634 	{
       
   635 	long ret=1;
       
   636 	BIO_CONNECT *data;
       
   637 
       
   638 	data=(BIO_CONNECT *)b->ptr;
       
   639 
       
   640 	switch (cmd)
       
   641 		{
       
   642 	case BIO_CTRL_SET_CALLBACK:
       
   643 		{
       
   644 		data->info_callback=(int (*)(const struct bio_st *, int, int))fp;
       
   645 		}
       
   646 		break;
       
   647 	default:
       
   648 		ret=0;
       
   649 		break;
       
   650 		}
       
   651 	return(ret);
       
   652 	}
       
   653 
       
   654 static int conn_puts(BIO *bp, const char *str)
       
   655 	{
       
   656 	int n,ret;
       
   657 
       
   658 	n=strlen(str);
       
   659 	ret=conn_write(bp,str,n);
       
   660 	return(ret);
       
   661 	}
       
   662 
       
   663 EXPORT_C BIO *BIO_new_connect(char *str)
       
   664 	{
       
   665 	BIO *ret;
       
   666 
       
   667 	ret=BIO_new(BIO_s_connect());
       
   668 	if (ret == NULL) return(NULL);
       
   669 	if (BIO_set_conn_hostname(ret,str))
       
   670 		return(ret);
       
   671 	else
       
   672 		{
       
   673 		BIO_free(ret);
       
   674 		return(NULL);
       
   675 		}
       
   676 	}
       
   677 
       
   678 #endif
       
   679