os/ossrv/ssl/libcrypto/src/crypto/bio/bss_conn.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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