bio_lib.c revision 167612
155714Skris/* crypto/bio/bio_lib.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include <errno.h>
6155714Skris#include <openssl/crypto.h>
6255714Skris#include "cryptlib.h"
6355714Skris#include <openssl/bio.h>
6455714Skris#include <openssl/stack.h>
6555714Skris
6655714SkrisBIO *BIO_new(BIO_METHOD *method)
6755714Skris	{
6855714Skris	BIO *ret=NULL;
6955714Skris
7068651Skris	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
7155714Skris	if (ret == NULL)
7255714Skris		{
7355714Skris		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
7455714Skris		return(NULL);
7555714Skris		}
7655714Skris	if (!BIO_set(ret,method))
7755714Skris		{
7868651Skris		OPENSSL_free(ret);
7955714Skris		ret=NULL;
8055714Skris		}
8155714Skris	return(ret);
8255714Skris	}
8355714Skris
8455714Skrisint BIO_set(BIO *bio, BIO_METHOD *method)
8555714Skris	{
8655714Skris	bio->method=method;
8755714Skris	bio->callback=NULL;
8855714Skris	bio->cb_arg=NULL;
8955714Skris	bio->init=0;
9055714Skris	bio->shutdown=1;
9155714Skris	bio->flags=0;
9255714Skris	bio->retry_reason=0;
9355714Skris	bio->num=0;
9455714Skris	bio->ptr=NULL;
9555714Skris	bio->prev_bio=NULL;
9655714Skris	bio->next_bio=NULL;
9755714Skris	bio->references=1;
9855714Skris	bio->num_read=0L;
9955714Skris	bio->num_write=0L;
100109998Smarkm	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
10155714Skris	if (method->create != NULL)
10255714Skris		if (!method->create(bio))
103109998Smarkm			{
104109998Smarkm			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
105109998Smarkm					&bio->ex_data);
10655714Skris			return(0);
107109998Smarkm			}
10855714Skris	return(1);
10955714Skris	}
11055714Skris
11155714Skrisint BIO_free(BIO *a)
11255714Skris	{
11355714Skris	int ret=0,i;
11455714Skris
11555714Skris	if (a == NULL) return(0);
11655714Skris
11755714Skris	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
11855714Skris#ifdef REF_PRINT
11955714Skris	REF_PRINT("BIO",a);
12055714Skris#endif
12155714Skris	if (i > 0) return(1);
12255714Skris#ifdef REF_CHECK
12355714Skris	if (i < 0)
12455714Skris		{
12555714Skris		fprintf(stderr,"BIO_free, bad reference count\n");
12655714Skris		abort();
12755714Skris		}
12855714Skris#endif
12955714Skris	if ((a->callback != NULL) &&
13055714Skris		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
13155714Skris			return(i);
13255714Skris
133109998Smarkm	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
13455714Skris
13555714Skris	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
13655714Skris	ret=a->method->destroy(a);
13768651Skris	OPENSSL_free(a);
13855714Skris	return(1);
13955714Skris	}
14055714Skris
14168651Skrisvoid BIO_vfree(BIO *a)
14268651Skris    { BIO_free(a); }
14368651Skris
144167612Ssimonvoid BIO_clear_flags(BIO *b, int flags)
145167612Ssimon	{
146167612Ssimon	b->flags &= ~flags;
147167612Ssimon	}
148167612Ssimon
149167612Ssimonint	BIO_test_flags(const BIO *b, int flags)
150167612Ssimon	{
151167612Ssimon	return (b->flags & flags);
152167612Ssimon	}
153167612Ssimon
154167612Ssimonvoid	BIO_set_flags(BIO *b, int flags)
155167612Ssimon	{
156167612Ssimon	b->flags |= flags;
157167612Ssimon	}
158167612Ssimon
159167612Ssimonlong (*BIO_get_callback(const BIO *b))(struct bio_st *,int,const char *,int, long,long)
160167612Ssimon	{
161167612Ssimon	return b->callback;
162167612Ssimon	}
163167612Ssimon
164167612Ssimonvoid BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, long,long))
165167612Ssimon	{
166167612Ssimon	b->callback = cb;
167167612Ssimon	}
168167612Ssimon
169167612Ssimonvoid BIO_set_callback_arg(BIO *b, char *arg)
170167612Ssimon	{
171167612Ssimon	b->cb_arg = arg;
172167612Ssimon	}
173167612Ssimon
174167612Ssimonchar * BIO_get_callback_arg(const BIO *b)
175167612Ssimon	{
176167612Ssimon	return b->cb_arg;
177167612Ssimon	}
178167612Ssimon
179167612Ssimonconst char * BIO_method_name(const BIO *b)
180167612Ssimon	{
181167612Ssimon	return b->method->name;
182167612Ssimon	}
183167612Ssimon
184167612Ssimonint BIO_method_type(const BIO *b)
185167612Ssimon	{
186167612Ssimon	return b->method->type;
187167612Ssimon	}
188167612Ssimon
189167612Ssimon
19055714Skrisint BIO_read(BIO *b, void *out, int outl)
19155714Skris	{
19255714Skris	int i;
193160814Ssimon	long (*cb)(BIO *,int,const char *,int,long,long);
19455714Skris
19555714Skris	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
19655714Skris		{
19755714Skris		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
19855714Skris		return(-2);
19955714Skris		}
20055714Skris
20155714Skris	cb=b->callback;
20255714Skris	if ((cb != NULL) &&
20355714Skris		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
20455714Skris			return(i);
20555714Skris
20655714Skris	if (!b->init)
20755714Skris		{
20855714Skris		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
20955714Skris		return(-2);
21055714Skris		}
21155714Skris
21255714Skris	i=b->method->bread(b,out,outl);
21355714Skris
21455714Skris	if (i > 0) b->num_read+=(unsigned long)i;
21555714Skris
21655714Skris	if (cb != NULL)
21755714Skris		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
21855714Skris			0L,(long)i);
21955714Skris	return(i);
22055714Skris	}
22155714Skris
22259191Skrisint BIO_write(BIO *b, const void *in, int inl)
22355714Skris	{
22455714Skris	int i;
225160814Ssimon	long (*cb)(BIO *,int,const char *,int,long,long);
22655714Skris
22755714Skris	if (b == NULL)
22855714Skris		return(0);
22955714Skris
23055714Skris	cb=b->callback;
23155714Skris	if ((b->method == NULL) || (b->method->bwrite == NULL))
23255714Skris		{
23355714Skris		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
23455714Skris		return(-2);
23555714Skris		}
23655714Skris
23755714Skris	if ((cb != NULL) &&
23855714Skris		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
23955714Skris			return(i);
24055714Skris
24155714Skris	if (!b->init)
24255714Skris		{
24355714Skris		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
24455714Skris		return(-2);
24555714Skris		}
24655714Skris
24755714Skris	i=b->method->bwrite(b,in,inl);
24855714Skris
24955714Skris	if (i > 0) b->num_write+=(unsigned long)i;
25055714Skris
25168651Skris	if (cb != NULL)
25255714Skris		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
25355714Skris			0L,(long)i);
25455714Skris	return(i);
25555714Skris	}
25655714Skris
25755714Skrisint BIO_puts(BIO *b, const char *in)
25855714Skris	{
25955714Skris	int i;
260160814Ssimon	long (*cb)(BIO *,int,const char *,int,long,long);
26155714Skris
26255714Skris	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
26355714Skris		{
26455714Skris		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
26555714Skris		return(-2);
26655714Skris		}
26755714Skris
26855714Skris	cb=b->callback;
26955714Skris
27055714Skris	if ((cb != NULL) &&
27155714Skris		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
27255714Skris			return(i);
27355714Skris
27455714Skris	if (!b->init)
27555714Skris		{
27655714Skris		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
27755714Skris		return(-2);
27855714Skris		}
27955714Skris
28055714Skris	i=b->method->bputs(b,in);
28155714Skris
28268651Skris	if (i > 0) b->num_write+=(unsigned long)i;
28368651Skris
28455714Skris	if (cb != NULL)
28555714Skris		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
28655714Skris			0L,(long)i);
28755714Skris	return(i);
28855714Skris	}
28955714Skris
29055714Skrisint BIO_gets(BIO *b, char *in, int inl)
29155714Skris	{
29255714Skris	int i;
293160814Ssimon	long (*cb)(BIO *,int,const char *,int,long,long);
29455714Skris
29555714Skris	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
29655714Skris		{
29755714Skris		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
29855714Skris		return(-2);
29955714Skris		}
30055714Skris
30155714Skris	cb=b->callback;
30255714Skris
30355714Skris	if ((cb != NULL) &&
30455714Skris		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
30555714Skris			return(i);
30655714Skris
30755714Skris	if (!b->init)
30855714Skris		{
30955714Skris		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
31055714Skris		return(-2);
31155714Skris		}
31255714Skris
31355714Skris	i=b->method->bgets(b,in,inl);
31455714Skris
31555714Skris	if (cb != NULL)
31655714Skris		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
31755714Skris			0L,(long)i);
31855714Skris	return(i);
31955714Skris	}
32055714Skris
321109998Smarkmint BIO_indent(BIO *b,int indent,int max)
322109998Smarkm	{
323109998Smarkm	if(indent < 0)
324109998Smarkm		indent=0;
325109998Smarkm	if(indent > max)
326109998Smarkm		indent=max;
327109998Smarkm	while(indent--)
328109998Smarkm		if(BIO_puts(b," ") != 1)
329109998Smarkm			return 0;
330109998Smarkm	return 1;
331109998Smarkm	}
332109998Smarkm
33355714Skrislong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
33455714Skris	{
33555714Skris	int i;
33655714Skris
33755714Skris	i=iarg;
33855714Skris	return(BIO_ctrl(b,cmd,larg,(char *)&i));
33955714Skris	}
34055714Skris
34155714Skrischar *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
34255714Skris	{
34355714Skris	char *p=NULL;
34455714Skris
34555714Skris	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
34655714Skris		return(NULL);
34755714Skris	else
34855714Skris		return(p);
34955714Skris	}
35055714Skris
35155714Skrislong BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
35255714Skris	{
35355714Skris	long ret;
354160814Ssimon	long (*cb)(BIO *,int,const char *,int,long,long);
35555714Skris
35655714Skris	if (b == NULL) return(0);
35755714Skris
35855714Skris	if ((b->method == NULL) || (b->method->ctrl == NULL))
35955714Skris		{
36055714Skris		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
36155714Skris		return(-2);
36255714Skris		}
36355714Skris
36455714Skris	cb=b->callback;
36555714Skris
36655714Skris	if ((cb != NULL) &&
36755714Skris		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
36855714Skris		return(ret);
36955714Skris
37055714Skris	ret=b->method->ctrl(b,cmd,larg,parg);
37155714Skris
37255714Skris	if (cb != NULL)
37355714Skris		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
37455714Skris			larg,ret);
37555714Skris	return(ret);
37655714Skris	}
37755714Skris
37868651Skrislong BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
37959191Skris	{
38059191Skris	long ret;
381160814Ssimon	long (*cb)(BIO *,int,const char *,int,long,long);
38259191Skris
38359191Skris	if (b == NULL) return(0);
38459191Skris
38559191Skris	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
38659191Skris		{
387160814Ssimon		BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD);
38859191Skris		return(-2);
38959191Skris		}
39059191Skris
39159191Skris	cb=b->callback;
39259191Skris
39359191Skris	if ((cb != NULL) &&
39459191Skris		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
39559191Skris		return(ret);
39659191Skris
39759191Skris	ret=b->method->callback_ctrl(b,cmd,fp);
39859191Skris
39959191Skris	if (cb != NULL)
40059191Skris		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
40159191Skris			0,ret);
40259191Skris	return(ret);
40359191Skris	}
40459191Skris
40555714Skris/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
40655714Skris * do; but those macros have inappropriate return type, and for interfacing
40755714Skris * from other programming languages, C macros aren't much of a help anyway. */
40855714Skrissize_t BIO_ctrl_pending(BIO *bio)
40959191Skris	{
41055714Skris	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
41155714Skris	}
41255714Skris
41355714Skrissize_t BIO_ctrl_wpending(BIO *bio)
41459191Skris	{
41555714Skris	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
41655714Skris	}
41755714Skris
41855714Skris
41955714Skris/* put the 'bio' on the end of b's list of operators */
42055714SkrisBIO *BIO_push(BIO *b, BIO *bio)
42155714Skris	{
42255714Skris	BIO *lb;
42355714Skris
42455714Skris	if (b == NULL) return(bio);
42555714Skris	lb=b;
42655714Skris	while (lb->next_bio != NULL)
42755714Skris		lb=lb->next_bio;
42855714Skris	lb->next_bio=bio;
42955714Skris	if (bio != NULL)
43055714Skris		bio->prev_bio=lb;
43155714Skris	/* called to do internal processing */
43255714Skris	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
43355714Skris	return(b);
43455714Skris	}
43555714Skris
43655714Skris/* Remove the first and return the rest */
43755714SkrisBIO *BIO_pop(BIO *b)
43855714Skris	{
43955714Skris	BIO *ret;
44055714Skris
44155714Skris	if (b == NULL) return(NULL);
44255714Skris	ret=b->next_bio;
44355714Skris
444111147Snectar	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
445111147Snectar
44655714Skris	if (b->prev_bio != NULL)
44755714Skris		b->prev_bio->next_bio=b->next_bio;
44855714Skris	if (b->next_bio != NULL)
44955714Skris		b->next_bio->prev_bio=b->prev_bio;
45055714Skris
45155714Skris	b->next_bio=NULL;
45255714Skris	b->prev_bio=NULL;
45355714Skris	return(ret);
45455714Skris	}
45555714Skris
45655714SkrisBIO *BIO_get_retry_BIO(BIO *bio, int *reason)
45755714Skris	{
45855714Skris	BIO *b,*last;
45955714Skris
46055714Skris	b=last=bio;
46155714Skris	for (;;)
46255714Skris		{
46355714Skris		if (!BIO_should_retry(b)) break;
46455714Skris		last=b;
46555714Skris		b=b->next_bio;
46655714Skris		if (b == NULL) break;
46755714Skris		}
46855714Skris	if (reason != NULL) *reason=last->retry_reason;
46955714Skris	return(last);
47055714Skris	}
47155714Skris
47255714Skrisint BIO_get_retry_reason(BIO *bio)
47355714Skris	{
47455714Skris	return(bio->retry_reason);
47555714Skris	}
47655714Skris
47755714SkrisBIO *BIO_find_type(BIO *bio, int type)
47855714Skris	{
47955714Skris	int mt,mask;
48055714Skris
48168651Skris	if(!bio) return NULL;
48255714Skris	mask=type&0xff;
48355714Skris	do	{
48455714Skris		if (bio->method != NULL)
48555714Skris			{
48655714Skris			mt=bio->method->type;
48755714Skris
48855714Skris			if (!mask)
48955714Skris				{
49055714Skris				if (mt & type) return(bio);
49155714Skris				}
49255714Skris			else if (mt == type)
49355714Skris				return(bio);
49455714Skris			}
49555714Skris		bio=bio->next_bio;
49655714Skris		} while (bio != NULL);
49755714Skris	return(NULL);
49855714Skris	}
49955714Skris
50068651SkrisBIO *BIO_next(BIO *b)
50168651Skris	{
50268651Skris	if(!b) return NULL;
50368651Skris	return b->next_bio;
50468651Skris	}
50568651Skris
50655714Skrisvoid BIO_free_all(BIO *bio)
50755714Skris	{
50855714Skris	BIO *b;
50955714Skris	int ref;
51055714Skris
51155714Skris	while (bio != NULL)
51255714Skris		{
51355714Skris		b=bio;
51455714Skris		ref=b->references;
51555714Skris		bio=bio->next_bio;
51655714Skris		BIO_free(b);
51755714Skris		/* Since ref count > 1, don't free anyone else. */
51855714Skris		if (ref > 1) break;
51955714Skris		}
52055714Skris	}
52155714Skris
52255714SkrisBIO *BIO_dup_chain(BIO *in)
52355714Skris	{
52455714Skris	BIO *ret=NULL,*eoc=NULL,*bio,*new;
52555714Skris
52655714Skris	for (bio=in; bio != NULL; bio=bio->next_bio)
52755714Skris		{
52855714Skris		if ((new=BIO_new(bio->method)) == NULL) goto err;
52955714Skris		new->callback=bio->callback;
53055714Skris		new->cb_arg=bio->cb_arg;
53155714Skris		new->init=bio->init;
53255714Skris		new->shutdown=bio->shutdown;
53355714Skris		new->flags=bio->flags;
53455714Skris
53555714Skris		/* This will let SSL_s_sock() work with stdin/stdout */
53655714Skris		new->num=bio->num;
53755714Skris
53855714Skris		if (!BIO_dup_state(bio,(char *)new))
53955714Skris			{
54055714Skris			BIO_free(new);
54155714Skris			goto err;
54255714Skris			}
54355714Skris
54455714Skris		/* copy app data */
545109998Smarkm		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
546109998Smarkm					&bio->ex_data))
54755714Skris			goto err;
54855714Skris
54955714Skris		if (ret == NULL)
55055714Skris			{
55155714Skris			eoc=new;
55255714Skris			ret=eoc;
55355714Skris			}
55455714Skris		else
55555714Skris			{
55655714Skris			BIO_push(eoc,new);
55755714Skris			eoc=new;
55855714Skris			}
55955714Skris		}
56055714Skris	return(ret);
56155714Skriserr:
56255714Skris	if (ret != NULL)
56355714Skris		BIO_free(ret);
56455714Skris	return(NULL);
56555714Skris	}
56655714Skris
56755714Skrisvoid BIO_copy_next_retry(BIO *b)
56855714Skris	{
56955714Skris	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
57055714Skris	b->retry_reason=b->next_bio->retry_reason;
57155714Skris	}
57255714Skris
57359191Skrisint BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
57459191Skris	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
57555714Skris	{
576109998Smarkm	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
577109998Smarkm				new_func, dup_func, free_func);
57855714Skris	}
57955714Skris
58059191Skrisint BIO_set_ex_data(BIO *bio, int idx, void *data)
58155714Skris	{
58255714Skris	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
58355714Skris	}
58455714Skris
58559191Skrisvoid *BIO_get_ex_data(BIO *bio, int idx)
58655714Skris	{
58755714Skris	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
58855714Skris	}
58955714Skris
59059191Skrisunsigned long BIO_number_read(BIO *bio)
59159191Skris{
59259191Skris	if(bio) return bio->num_read;
59359191Skris	return 0;
59459191Skris}
59559191Skris
59659191Skrisunsigned long BIO_number_written(BIO *bio)
59759191Skris{
59859191Skris	if(bio) return bio->num_write;
59959191Skris	return 0;
60059191Skris}
60168651Skris
60268651SkrisIMPLEMENT_STACK_OF(BIO)
603