ssl/libcrypto/src/crypto/bio/bio_lib.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* crypto/bio/bio_lib.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 #include <stdio.h>
       
    60 #include <errno.h>
       
    61 #include <openssl/crypto.h>
       
    62 #include "cryptlib.h"
       
    63 #include <openssl/bio.h>
       
    64 #include <openssl/stack.h>
       
    65 
       
    66 EXPORT_C BIO *BIO_new(BIO_METHOD *method)
       
    67 	{
       
    68 	BIO *ret=NULL;
       
    69 
       
    70 	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
       
    71 	if (ret == NULL)
       
    72 		{
       
    73 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
       
    74 		return(NULL);
       
    75 		}
       
    76 #ifdef SYMBIAN
       
    77    memset(ret,0,sizeof(BIO));
       
    78 #endif		
       
    79 	if (!BIO_set(ret,method))
       
    80 		{
       
    81 		OPENSSL_free(ret);
       
    82 		ret=NULL;
       
    83 		}
       
    84 	return(ret);
       
    85 	}
       
    86 
       
    87 EXPORT_C int BIO_set(BIO *bio, BIO_METHOD *method)
       
    88 	{
       
    89 	bio->method=method;
       
    90 	bio->callback=NULL;
       
    91 	bio->cb_arg=NULL;
       
    92 	bio->init=0;
       
    93 	bio->shutdown=1;
       
    94 	bio->flags=0;
       
    95 	bio->retry_reason=0;
       
    96 	bio->num=0;
       
    97 	bio->ptr=NULL;
       
    98 	bio->prev_bio=NULL;
       
    99 	bio->next_bio=NULL;
       
   100 	bio->references=1;
       
   101 	bio->num_read=0L;
       
   102 	bio->num_write=0L;
       
   103 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
       
   104 	if (method->create != NULL)
       
   105 		if (!method->create(bio))
       
   106 			{
       
   107 			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
       
   108 					&bio->ex_data);
       
   109 			return(0);
       
   110 			}
       
   111 	return(1);
       
   112 	}
       
   113 
       
   114 EXPORT_C int BIO_free(BIO *a)
       
   115 	{
       
   116 	int ret=0,i;
       
   117 
       
   118 	if (a == NULL) return(0);
       
   119 
       
   120 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
       
   121 #ifdef REF_PRINT
       
   122 	REF_PRINT("BIO",a);
       
   123 #endif
       
   124 	if (i > 0) return(1);
       
   125 #ifdef REF_CHECK
       
   126 	if (i < 0)
       
   127 		{
       
   128 		fprintf(stderr,"BIO_free, bad reference count\n");
       
   129 		abort();
       
   130 		}
       
   131 #endif
       
   132 	if ((a->callback != NULL) &&
       
   133 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
       
   134 			return(i);
       
   135 
       
   136 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
       
   137 
       
   138 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
       
   139 	ret=a->method->destroy(a);
       
   140 	OPENSSL_free(a);
       
   141 	return(1);
       
   142 	}
       
   143 
       
   144 EXPORT_C void BIO_vfree(BIO *a)
       
   145     { BIO_free(a); }
       
   146 
       
   147 EXPORT_C void BIO_clear_flags(BIO *b, int flags)
       
   148 	{
       
   149 	b->flags &= ~flags;
       
   150 	}
       
   151 
       
   152 EXPORT_C int	BIO_test_flags(const BIO *b, int flags)
       
   153 	{
       
   154 	return (b->flags & flags);
       
   155 	}
       
   156 
       
   157 EXPORT_C void	BIO_set_flags(BIO *b, int flags)
       
   158 	{
       
   159 	b->flags |= flags;
       
   160 	}
       
   161 
       
   162 EXPORT_C long (*BIO_get_callback(const BIO *b))(struct bio_st *,int,const char *,int, long,long)
       
   163 	{
       
   164 	return b->callback;
       
   165 	}
       
   166 
       
   167 EXPORT_C void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, long,long))
       
   168 	{
       
   169 	b->callback = cb;
       
   170 	}
       
   171 
       
   172 EXPORT_C void BIO_set_callback_arg(BIO *b, char *arg)
       
   173 	{
       
   174 	b->cb_arg = arg;
       
   175 	}
       
   176 
       
   177 EXPORT_C char * BIO_get_callback_arg(const BIO *b)
       
   178 	{
       
   179 	return b->cb_arg;
       
   180 	}
       
   181 
       
   182 EXPORT_C const char * BIO_method_name(const BIO *b)
       
   183 	{
       
   184 	return b->method->name;
       
   185 	}
       
   186 
       
   187 EXPORT_C int BIO_method_type(const BIO *b)
       
   188 	{
       
   189 	return b->method->type;
       
   190 	}
       
   191 EXPORT_C int BIO_read(BIO *b, void *out, int outl)
       
   192 	{
       
   193 	int i;
       
   194 	long (*cb)(BIO *,int,const char *,int,long,long);
       
   195 
       
   196 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
       
   197 		{
       
   198 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
       
   199 		return(-2);
       
   200 		}
       
   201 
       
   202 	cb=b->callback;
       
   203 	if ((cb != NULL) &&
       
   204 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
       
   205 			return(i);
       
   206 
       
   207 	if (!b->init)
       
   208 		{
       
   209 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
       
   210 		return(-2);
       
   211 		}
       
   212 
       
   213 	i=b->method->bread(b,out,outl);
       
   214 
       
   215 	if (i > 0) b->num_read+=(unsigned long)i;
       
   216 
       
   217 	if (cb != NULL)
       
   218 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
       
   219 			0L,(long)i);
       
   220 	return(i);
       
   221 	}
       
   222 
       
   223 EXPORT_C int BIO_write(BIO *b, const void *in, int inl)
       
   224 	{
       
   225 	int i;
       
   226 	long (*cb)(BIO *,int,const char *,int,long,long);
       
   227 
       
   228 	if (b == NULL)
       
   229 		return(0);
       
   230 
       
   231 	cb=b->callback;
       
   232 	if ((b->method == NULL) || (b->method->bwrite == NULL))
       
   233 		{
       
   234 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
       
   235 		return(-2);
       
   236 		}
       
   237 
       
   238 	if ((cb != NULL) &&
       
   239 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
       
   240 			return(i);
       
   241 
       
   242 	if (!b->init)
       
   243 		{
       
   244 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
       
   245 		return(-2);
       
   246 		}
       
   247 
       
   248 	i=b->method->bwrite(b,in,inl);
       
   249 
       
   250 	if (i > 0) b->num_write+=(unsigned long)i;
       
   251 
       
   252 	if (cb != NULL)
       
   253 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
       
   254 			0L,(long)i);
       
   255 	return(i);
       
   256 	}
       
   257 
       
   258 EXPORT_C int BIO_puts(BIO *b, const char *in)
       
   259 	{
       
   260 	int i;
       
   261 	long (*cb)(BIO *,int,const char *,int,long,long);
       
   262 
       
   263 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
       
   264 		{
       
   265 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
       
   266 		return(-2);
       
   267 		}
       
   268 
       
   269 	cb=b->callback;
       
   270 
       
   271 	if ((cb != NULL) &&
       
   272 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
       
   273 			return(i);
       
   274 
       
   275 	if (!b->init)
       
   276 		{
       
   277 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
       
   278 		return(-2);
       
   279 		}
       
   280 
       
   281 	i=b->method->bputs(b,in);
       
   282 
       
   283 	if (i > 0) b->num_write+=(unsigned long)i;
       
   284 
       
   285 	if (cb != NULL)
       
   286 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
       
   287 			0L,(long)i);
       
   288 	return(i);
       
   289 	}
       
   290 
       
   291 EXPORT_C int BIO_gets(BIO *b, char *in, int inl)
       
   292 	{
       
   293 	int i;
       
   294 	long (*cb)(BIO *,int,const char *,int,long,long);
       
   295 
       
   296 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
       
   297 		{
       
   298 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
       
   299 		return(-2);
       
   300 		}
       
   301 
       
   302 	cb=b->callback;
       
   303 
       
   304 	if ((cb != NULL) &&
       
   305 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
       
   306 			return(i);
       
   307 
       
   308 	if (!b->init)
       
   309 		{
       
   310 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
       
   311 		return(-2);
       
   312 		}
       
   313 
       
   314 	i=b->method->bgets(b,in,inl);
       
   315 
       
   316 	if (cb != NULL)
       
   317 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
       
   318 			0L,(long)i);
       
   319 	return(i);
       
   320 	}
       
   321 
       
   322 EXPORT_C int BIO_indent(BIO *b,int indent,int max)
       
   323 	{
       
   324 	if(indent < 0)
       
   325 		indent=0;
       
   326 	if(indent > max)
       
   327 		indent=max;
       
   328 	while(indent--)
       
   329 		if(BIO_puts(b," ") != 1)
       
   330 			return 0;
       
   331 	return 1;
       
   332 	}
       
   333 
       
   334 EXPORT_C long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
       
   335 	{
       
   336 	int i;
       
   337 
       
   338 	i=iarg;
       
   339 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
       
   340 	}
       
   341 
       
   342 EXPORT_C char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
       
   343 	{
       
   344 	char *p=NULL;
       
   345 
       
   346 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
       
   347 		return(NULL);
       
   348 	else
       
   349 		return(p);
       
   350 	}
       
   351 
       
   352 EXPORT_C long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
       
   353 	{
       
   354 	long ret;
       
   355 	long (*cb)(BIO *,int,const char *,int,long,long);
       
   356 
       
   357 	if (b == NULL) return(0);
       
   358 
       
   359 	if ((b->method == NULL) || (b->method->ctrl == NULL))
       
   360 		{
       
   361 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
       
   362 		return(-2);
       
   363 		}
       
   364 
       
   365 	cb=b->callback;
       
   366 
       
   367 	if ((cb != NULL) &&
       
   368 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
       
   369 		return(ret);
       
   370 
       
   371 	ret=b->method->ctrl(b,cmd,larg,parg);
       
   372 
       
   373 	if (cb != NULL)
       
   374 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
       
   375 			larg,ret);
       
   376 	return(ret);
       
   377 	}
       
   378 
       
   379 EXPORT_C long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
       
   380 	{
       
   381 	long ret;
       
   382 	long (*cb)(BIO *,int,const char *,int,long,long);
       
   383 
       
   384 	if (b == NULL) return(0);
       
   385 
       
   386 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
       
   387 		{
       
   388 		BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD);
       
   389 		return(-2);
       
   390 		}
       
   391 
       
   392 	cb=b->callback;
       
   393 
       
   394 	if ((cb != NULL) &&
       
   395 		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
       
   396 		return(ret);
       
   397 
       
   398 	ret=b->method->callback_ctrl(b,cmd,fp);
       
   399 
       
   400 	if (cb != NULL)
       
   401 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
       
   402 			0,ret);
       
   403 	return(ret);
       
   404 	}
       
   405 
       
   406 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
       
   407  * do; but those macros have inappropriate return type, and for interfacing
       
   408  * from other programming languages, C macros aren't much of a help anyway. */
       
   409 EXPORT_C size_t BIO_ctrl_pending(BIO *bio)
       
   410 	{
       
   411 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
       
   412 	}
       
   413 
       
   414 EXPORT_C size_t BIO_ctrl_wpending(BIO *bio)
       
   415 	{
       
   416 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
       
   417 	}
       
   418 
       
   419 
       
   420 /* put the 'bio' on the end of b's list of operators */
       
   421 EXPORT_C BIO *BIO_push(BIO *b, BIO *bio)
       
   422 	{
       
   423 	BIO *lb;
       
   424 
       
   425 	if (b == NULL) return(bio);
       
   426 	lb=b;
       
   427 	while (lb->next_bio != NULL)
       
   428 		lb=lb->next_bio;
       
   429 	lb->next_bio=bio;
       
   430 	if (bio != NULL)
       
   431 		bio->prev_bio=lb;
       
   432 	/* called to do internal processing */
       
   433 	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
       
   434 	return(b);
       
   435 	}
       
   436 
       
   437 /* Remove the first and return the rest */
       
   438 EXPORT_C BIO *BIO_pop(BIO *b)
       
   439 	{
       
   440 	BIO *ret;
       
   441 
       
   442 	if (b == NULL) return(NULL);
       
   443 	ret=b->next_bio;
       
   444 
       
   445 	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
       
   446 
       
   447 	if (b->prev_bio != NULL)
       
   448 		b->prev_bio->next_bio=b->next_bio;
       
   449 	if (b->next_bio != NULL)
       
   450 		b->next_bio->prev_bio=b->prev_bio;
       
   451 
       
   452 	b->next_bio=NULL;
       
   453 	b->prev_bio=NULL;
       
   454 	return(ret);
       
   455 	}
       
   456 
       
   457 EXPORT_C BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
       
   458 	{
       
   459 	BIO *b,*last;
       
   460 
       
   461 	b=last=bio;
       
   462 	for (;;)
       
   463 		{
       
   464 		if (!BIO_should_retry(b)) break;
       
   465 		last=b;
       
   466 		b=b->next_bio;
       
   467 		if (b == NULL) break;
       
   468 		}
       
   469 	if (reason != NULL) *reason=last->retry_reason;
       
   470 	return(last);
       
   471 	}
       
   472 
       
   473 EXPORT_C int BIO_get_retry_reason(BIO *bio)
       
   474 	{
       
   475 	return(bio->retry_reason);
       
   476 	}
       
   477 
       
   478 EXPORT_C BIO *BIO_find_type(BIO *bio, int type)
       
   479 	{
       
   480 	int mt,mask;
       
   481 
       
   482 	if(!bio) return NULL;
       
   483 	mask=type&0xff;
       
   484 	do	{
       
   485 		if (bio->method != NULL)
       
   486 			{
       
   487 			mt=bio->method->type;
       
   488 
       
   489 			if (!mask)
       
   490 				{
       
   491 				if (mt & type) return(bio);
       
   492 				}
       
   493 			else if (mt == type)
       
   494 				return(bio);
       
   495 			}
       
   496 		bio=bio->next_bio;
       
   497 		} while (bio != NULL);
       
   498 	return(NULL);
       
   499 	}
       
   500 
       
   501 EXPORT_C BIO *BIO_next(BIO *b)
       
   502 	{
       
   503 	if(!b) return NULL;
       
   504 	return b->next_bio;
       
   505 	}
       
   506 
       
   507 EXPORT_C void BIO_free_all(BIO *bio)
       
   508 	{
       
   509 	BIO *b;
       
   510 	int ref;
       
   511 
       
   512 	while (bio != NULL)
       
   513 		{
       
   514 		b=bio;
       
   515 		ref=b->references;
       
   516 		bio=bio->next_bio;
       
   517 		BIO_free(b);
       
   518 		/* Since ref count > 1, don't free anyone else. */
       
   519 		if (ref > 1) break;
       
   520 		}
       
   521 	}
       
   522 
       
   523 EXPORT_C BIO *BIO_dup_chain(BIO *in)
       
   524 	{
       
   525 	BIO *ret=NULL,*eoc=NULL,*bio,*new;
       
   526 
       
   527 	for (bio=in; bio != NULL; bio=bio->next_bio)
       
   528 		{
       
   529 		if ((new=BIO_new(bio->method)) == NULL) goto err;
       
   530 		new->callback=bio->callback;
       
   531 		new->cb_arg=bio->cb_arg;
       
   532 		new->init=bio->init;
       
   533 		new->shutdown=bio->shutdown;
       
   534 		new->flags=bio->flags;
       
   535 
       
   536 		/* This will let SSL_s_sock() work with stdin/stdout */
       
   537 		new->num=bio->num;
       
   538 
       
   539 		if (!BIO_dup_state(bio,(char *)new))
       
   540 			{
       
   541 			BIO_free(new);
       
   542 			goto err;
       
   543 			}
       
   544 
       
   545 		/* copy app data */
       
   546 		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
       
   547 					&bio->ex_data))
       
   548 			goto err;
       
   549 
       
   550 		if (ret == NULL)
       
   551 			{
       
   552 			eoc=new;
       
   553 			ret=eoc;
       
   554 			}
       
   555 		else
       
   556 			{
       
   557 			BIO_push(eoc,new);
       
   558 			eoc=new;
       
   559 			}
       
   560 		}
       
   561 	return(ret);
       
   562 err:
       
   563 	if (ret != NULL)
       
   564 		BIO_free(ret);
       
   565 	return(NULL);	
       
   566 	}
       
   567 
       
   568 EXPORT_C void BIO_copy_next_retry(BIO *b)
       
   569 	{
       
   570 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
       
   571 	b->retry_reason=b->next_bio->retry_reason;
       
   572 	}
       
   573 
       
   574 EXPORT_C int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
       
   575 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
       
   576 	{
       
   577 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
       
   578 				new_func, dup_func, free_func);
       
   579 	}
       
   580 
       
   581 EXPORT_C int BIO_set_ex_data(BIO *bio, int idx, void *data)
       
   582 	{
       
   583 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
       
   584 	}
       
   585 
       
   586 EXPORT_C void *BIO_get_ex_data(BIO *bio, int idx)
       
   587 	{
       
   588 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
       
   589 	}
       
   590 
       
   591 EXPORT_C unsigned long BIO_number_read(BIO *bio)
       
   592 {
       
   593 	if(bio) return bio->num_read;
       
   594 	return 0;
       
   595 }
       
   596 
       
   597 EXPORT_C unsigned long BIO_number_written(BIO *bio)
       
   598 {
       
   599 	if(bio) return bio->num_write;
       
   600 	return 0;
       
   601 }
       
   602 
       
   603 IMPLEMENT_STACK_OF(BIO)