xref: /freebsd/crypto/openssl/crypto/bio/bio_lib.c (revision ddd58736)
174664626SKris Kennaway /* crypto/bio/bio_lib.c */
274664626SKris Kennaway /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
374664626SKris Kennaway  * All rights reserved.
474664626SKris Kennaway  *
574664626SKris Kennaway  * This package is an SSL implementation written
674664626SKris Kennaway  * by Eric Young (eay@cryptsoft.com).
774664626SKris Kennaway  * The implementation was written so as to conform with Netscapes SSL.
874664626SKris Kennaway  *
974664626SKris Kennaway  * This library is free for commercial and non-commercial use as long as
1074664626SKris Kennaway  * the following conditions are aheared to.  The following conditions
1174664626SKris Kennaway  * apply to all code found in this distribution, be it the RC4, RSA,
1274664626SKris Kennaway  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1374664626SKris Kennaway  * included with this distribution is covered by the same copyright terms
1474664626SKris Kennaway  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1574664626SKris Kennaway  *
1674664626SKris Kennaway  * Copyright remains Eric Young's, and as such any Copyright notices in
1774664626SKris Kennaway  * the code are not to be removed.
1874664626SKris Kennaway  * If this package is used in a product, Eric Young should be given attribution
1974664626SKris Kennaway  * as the author of the parts of the library used.
2074664626SKris Kennaway  * This can be in the form of a textual message at program startup or
2174664626SKris Kennaway  * in documentation (online or textual) provided with the package.
2274664626SKris Kennaway  *
2374664626SKris Kennaway  * Redistribution and use in source and binary forms, with or without
2474664626SKris Kennaway  * modification, are permitted provided that the following conditions
2574664626SKris Kennaway  * are met:
2674664626SKris Kennaway  * 1. Redistributions of source code must retain the copyright
2774664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer.
2874664626SKris Kennaway  * 2. Redistributions in binary form must reproduce the above copyright
2974664626SKris Kennaway  *    notice, this list of conditions and the following disclaimer in the
3074664626SKris Kennaway  *    documentation and/or other materials provided with the distribution.
3174664626SKris Kennaway  * 3. All advertising materials mentioning features or use of this software
3274664626SKris Kennaway  *    must display the following acknowledgement:
3374664626SKris Kennaway  *    "This product includes cryptographic software written by
3474664626SKris Kennaway  *     Eric Young (eay@cryptsoft.com)"
3574664626SKris Kennaway  *    The word 'cryptographic' can be left out if the rouines from the library
3674664626SKris Kennaway  *    being used are not cryptographic related :-).
3774664626SKris Kennaway  * 4. If you include any Windows specific code (or a derivative thereof) from
3874664626SKris Kennaway  *    the apps directory (application code) you must include an acknowledgement:
3974664626SKris Kennaway  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4074664626SKris Kennaway  *
4174664626SKris Kennaway  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4274664626SKris Kennaway  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4374664626SKris Kennaway  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4474664626SKris Kennaway  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4574664626SKris Kennaway  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4674664626SKris Kennaway  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4774664626SKris Kennaway  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4874664626SKris Kennaway  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4974664626SKris Kennaway  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5074664626SKris Kennaway  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5174664626SKris Kennaway  * SUCH DAMAGE.
5274664626SKris Kennaway  *
5374664626SKris Kennaway  * The licence and distribution terms for any publically available version or
5474664626SKris Kennaway  * derivative of this code cannot be changed.  i.e. this code cannot simply be
5574664626SKris Kennaway  * copied and put under another distribution licence
5674664626SKris Kennaway  * [including the GNU Public Licence.]
5774664626SKris Kennaway  */
5874664626SKris Kennaway 
5974664626SKris Kennaway #include <stdio.h>
6074664626SKris Kennaway #include <errno.h>
6174664626SKris Kennaway #include <openssl/crypto.h>
6274664626SKris Kennaway #include "cryptlib.h"
6374664626SKris Kennaway #include <openssl/bio.h>
6474664626SKris Kennaway #include <openssl/stack.h>
6574664626SKris Kennaway 
66f579bf8eSKris Kennaway static STACK_OF(CRYPTO_EX_DATA_FUNCS) *bio_meth=NULL;
6774664626SKris Kennaway static int bio_meth_num=0;
6874664626SKris Kennaway 
6974664626SKris Kennaway BIO *BIO_new(BIO_METHOD *method)
7074664626SKris Kennaway 	{
7174664626SKris Kennaway 	BIO *ret=NULL;
7274664626SKris Kennaway 
73ddd58736SKris Kennaway 	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
7474664626SKris Kennaway 	if (ret == NULL)
7574664626SKris Kennaway 		{
7674664626SKris Kennaway 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
7774664626SKris Kennaway 		return(NULL);
7874664626SKris Kennaway 		}
7974664626SKris Kennaway 	if (!BIO_set(ret,method))
8074664626SKris Kennaway 		{
81ddd58736SKris Kennaway 		OPENSSL_free(ret);
8274664626SKris Kennaway 		ret=NULL;
8374664626SKris Kennaway 		}
8474664626SKris Kennaway 	return(ret);
8574664626SKris Kennaway 	}
8674664626SKris Kennaway 
8774664626SKris Kennaway int BIO_set(BIO *bio, BIO_METHOD *method)
8874664626SKris Kennaway 	{
8974664626SKris Kennaway 	bio->method=method;
9074664626SKris Kennaway 	bio->callback=NULL;
9174664626SKris Kennaway 	bio->cb_arg=NULL;
9274664626SKris Kennaway 	bio->init=0;
9374664626SKris Kennaway 	bio->shutdown=1;
9474664626SKris Kennaway 	bio->flags=0;
9574664626SKris Kennaway 	bio->retry_reason=0;
9674664626SKris Kennaway 	bio->num=0;
9774664626SKris Kennaway 	bio->ptr=NULL;
9874664626SKris Kennaway 	bio->prev_bio=NULL;
9974664626SKris Kennaway 	bio->next_bio=NULL;
10074664626SKris Kennaway 	bio->references=1;
10174664626SKris Kennaway 	bio->num_read=0L;
10274664626SKris Kennaway 	bio->num_write=0L;
103f579bf8eSKris Kennaway 	CRYPTO_new_ex_data(bio_meth,bio,&bio->ex_data);
10474664626SKris Kennaway 	if (method->create != NULL)
10574664626SKris Kennaway 		if (!method->create(bio))
10674664626SKris Kennaway 			return(0);
10774664626SKris Kennaway 	return(1);
10874664626SKris Kennaway 	}
10974664626SKris Kennaway 
11074664626SKris Kennaway int BIO_free(BIO *a)
11174664626SKris Kennaway 	{
11274664626SKris Kennaway 	int ret=0,i;
11374664626SKris Kennaway 
11474664626SKris Kennaway 	if (a == NULL) return(0);
11574664626SKris Kennaway 
11674664626SKris Kennaway 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
11774664626SKris Kennaway #ifdef REF_PRINT
11874664626SKris Kennaway 	REF_PRINT("BIO",a);
11974664626SKris Kennaway #endif
12074664626SKris Kennaway 	if (i > 0) return(1);
12174664626SKris Kennaway #ifdef REF_CHECK
12274664626SKris Kennaway 	if (i < 0)
12374664626SKris Kennaway 		{
12474664626SKris Kennaway 		fprintf(stderr,"BIO_free, bad reference count\n");
12574664626SKris Kennaway 		abort();
12674664626SKris Kennaway 		}
12774664626SKris Kennaway #endif
12874664626SKris Kennaway 	if ((a->callback != NULL) &&
12974664626SKris Kennaway 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
13074664626SKris Kennaway 			return(i);
13174664626SKris Kennaway 
132f579bf8eSKris Kennaway 	CRYPTO_free_ex_data(bio_meth,a,&a->ex_data);
13374664626SKris Kennaway 
13474664626SKris Kennaway 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
13574664626SKris Kennaway 	ret=a->method->destroy(a);
136ddd58736SKris Kennaway 	OPENSSL_free(a);
13774664626SKris Kennaway 	return(1);
13874664626SKris Kennaway 	}
13974664626SKris Kennaway 
140ddd58736SKris Kennaway void BIO_vfree(BIO *a)
141ddd58736SKris Kennaway     { BIO_free(a); }
142ddd58736SKris Kennaway 
14374664626SKris Kennaway int BIO_read(BIO *b, void *out, int outl)
14474664626SKris Kennaway 	{
14574664626SKris Kennaway 	int i;
14674664626SKris Kennaway 	long (*cb)();
14774664626SKris Kennaway 
14874664626SKris Kennaway 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
14974664626SKris Kennaway 		{
15074664626SKris Kennaway 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
15174664626SKris Kennaway 		return(-2);
15274664626SKris Kennaway 		}
15374664626SKris Kennaway 
15474664626SKris Kennaway 	cb=b->callback;
15574664626SKris Kennaway 	if ((cb != NULL) &&
15674664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
15774664626SKris Kennaway 			return(i);
15874664626SKris Kennaway 
15974664626SKris Kennaway 	if (!b->init)
16074664626SKris Kennaway 		{
16174664626SKris Kennaway 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
16274664626SKris Kennaway 		return(-2);
16374664626SKris Kennaway 		}
16474664626SKris Kennaway 
16574664626SKris Kennaway 	i=b->method->bread(b,out,outl);
16674664626SKris Kennaway 
16774664626SKris Kennaway 	if (i > 0) b->num_read+=(unsigned long)i;
16874664626SKris Kennaway 
16974664626SKris Kennaway 	if (cb != NULL)
17074664626SKris Kennaway 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
17174664626SKris Kennaway 			0L,(long)i);
17274664626SKris Kennaway 	return(i);
17374664626SKris Kennaway 	}
17474664626SKris Kennaway 
175f579bf8eSKris Kennaway int BIO_write(BIO *b, const void *in, int inl)
17674664626SKris Kennaway 	{
17774664626SKris Kennaway 	int i;
17874664626SKris Kennaway 	long (*cb)();
17974664626SKris Kennaway 
18074664626SKris Kennaway 	if (b == NULL)
18174664626SKris Kennaway 		return(0);
18274664626SKris Kennaway 
18374664626SKris Kennaway 	cb=b->callback;
18474664626SKris Kennaway 	if ((b->method == NULL) || (b->method->bwrite == NULL))
18574664626SKris Kennaway 		{
18674664626SKris Kennaway 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
18774664626SKris Kennaway 		return(-2);
18874664626SKris Kennaway 		}
18974664626SKris Kennaway 
19074664626SKris Kennaway 	if ((cb != NULL) &&
19174664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
19274664626SKris Kennaway 			return(i);
19374664626SKris Kennaway 
19474664626SKris Kennaway 	if (!b->init)
19574664626SKris Kennaway 		{
19674664626SKris Kennaway 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
19774664626SKris Kennaway 		return(-2);
19874664626SKris Kennaway 		}
19974664626SKris Kennaway 
20074664626SKris Kennaway 	i=b->method->bwrite(b,in,inl);
20174664626SKris Kennaway 
20274664626SKris Kennaway 	if (i > 0) b->num_write+=(unsigned long)i;
20374664626SKris Kennaway 
204ddd58736SKris Kennaway 	if (cb != NULL)
20574664626SKris Kennaway 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
20674664626SKris Kennaway 			0L,(long)i);
20774664626SKris Kennaway 	return(i);
20874664626SKris Kennaway 	}
20974664626SKris Kennaway 
21074664626SKris Kennaway int BIO_puts(BIO *b, const char *in)
21174664626SKris Kennaway 	{
21274664626SKris Kennaway 	int i;
21374664626SKris Kennaway 	long (*cb)();
21474664626SKris Kennaway 
21574664626SKris Kennaway 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
21674664626SKris Kennaway 		{
21774664626SKris Kennaway 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
21874664626SKris Kennaway 		return(-2);
21974664626SKris Kennaway 		}
22074664626SKris Kennaway 
22174664626SKris Kennaway 	cb=b->callback;
22274664626SKris Kennaway 
22374664626SKris Kennaway 	if ((cb != NULL) &&
22474664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
22574664626SKris Kennaway 			return(i);
22674664626SKris Kennaway 
22774664626SKris Kennaway 	if (!b->init)
22874664626SKris Kennaway 		{
22974664626SKris Kennaway 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
23074664626SKris Kennaway 		return(-2);
23174664626SKris Kennaway 		}
23274664626SKris Kennaway 
23374664626SKris Kennaway 	i=b->method->bputs(b,in);
23474664626SKris Kennaway 
235ddd58736SKris Kennaway 	if (i > 0) b->num_write+=(unsigned long)i;
236ddd58736SKris Kennaway 
23774664626SKris Kennaway 	if (cb != NULL)
23874664626SKris Kennaway 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
23974664626SKris Kennaway 			0L,(long)i);
24074664626SKris Kennaway 	return(i);
24174664626SKris Kennaway 	}
24274664626SKris Kennaway 
24374664626SKris Kennaway int BIO_gets(BIO *b, char *in, int inl)
24474664626SKris Kennaway 	{
24574664626SKris Kennaway 	int i;
24674664626SKris Kennaway 	long (*cb)();
24774664626SKris Kennaway 
24874664626SKris Kennaway 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
24974664626SKris Kennaway 		{
25074664626SKris Kennaway 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
25174664626SKris Kennaway 		return(-2);
25274664626SKris Kennaway 		}
25374664626SKris Kennaway 
25474664626SKris Kennaway 	cb=b->callback;
25574664626SKris Kennaway 
25674664626SKris Kennaway 	if ((cb != NULL) &&
25774664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
25874664626SKris Kennaway 			return(i);
25974664626SKris Kennaway 
26074664626SKris Kennaway 	if (!b->init)
26174664626SKris Kennaway 		{
26274664626SKris Kennaway 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
26374664626SKris Kennaway 		return(-2);
26474664626SKris Kennaway 		}
26574664626SKris Kennaway 
26674664626SKris Kennaway 	i=b->method->bgets(b,in,inl);
26774664626SKris Kennaway 
26874664626SKris Kennaway 	if (cb != NULL)
26974664626SKris Kennaway 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
27074664626SKris Kennaway 			0L,(long)i);
27174664626SKris Kennaway 	return(i);
27274664626SKris Kennaway 	}
27374664626SKris Kennaway 
27474664626SKris Kennaway long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
27574664626SKris Kennaway 	{
27674664626SKris Kennaway 	int i;
27774664626SKris Kennaway 
27874664626SKris Kennaway 	i=iarg;
27974664626SKris Kennaway 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
28074664626SKris Kennaway 	}
28174664626SKris Kennaway 
28274664626SKris Kennaway char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
28374664626SKris Kennaway 	{
28474664626SKris Kennaway 	char *p=NULL;
28574664626SKris Kennaway 
28674664626SKris Kennaway 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
28774664626SKris Kennaway 		return(NULL);
28874664626SKris Kennaway 	else
28974664626SKris Kennaway 		return(p);
29074664626SKris Kennaway 	}
29174664626SKris Kennaway 
29274664626SKris Kennaway long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
29374664626SKris Kennaway 	{
29474664626SKris Kennaway 	long ret;
29574664626SKris Kennaway 	long (*cb)();
29674664626SKris Kennaway 
29774664626SKris Kennaway 	if (b == NULL) return(0);
29874664626SKris Kennaway 
29974664626SKris Kennaway 	if ((b->method == NULL) || (b->method->ctrl == NULL))
30074664626SKris Kennaway 		{
30174664626SKris Kennaway 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
30274664626SKris Kennaway 		return(-2);
30374664626SKris Kennaway 		}
30474664626SKris Kennaway 
30574664626SKris Kennaway 	cb=b->callback;
30674664626SKris Kennaway 
30774664626SKris Kennaway 	if ((cb != NULL) &&
30874664626SKris Kennaway 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
30974664626SKris Kennaway 		return(ret);
31074664626SKris Kennaway 
31174664626SKris Kennaway 	ret=b->method->ctrl(b,cmd,larg,parg);
31274664626SKris Kennaway 
31374664626SKris Kennaway 	if (cb != NULL)
31474664626SKris Kennaway 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
31574664626SKris Kennaway 			larg,ret);
31674664626SKris Kennaway 	return(ret);
31774664626SKris Kennaway 	}
31874664626SKris Kennaway 
319ddd58736SKris Kennaway long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
320f579bf8eSKris Kennaway 	{
321f579bf8eSKris Kennaway 	long ret;
322f579bf8eSKris Kennaway 	long (*cb)();
323f579bf8eSKris Kennaway 
324f579bf8eSKris Kennaway 	if (b == NULL) return(0);
325f579bf8eSKris Kennaway 
326f579bf8eSKris Kennaway 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
327f579bf8eSKris Kennaway 		{
328f579bf8eSKris Kennaway 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
329f579bf8eSKris Kennaway 		return(-2);
330f579bf8eSKris Kennaway 		}
331f579bf8eSKris Kennaway 
332f579bf8eSKris Kennaway 	cb=b->callback;
333f579bf8eSKris Kennaway 
334f579bf8eSKris Kennaway 	if ((cb != NULL) &&
335f579bf8eSKris Kennaway 		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
336f579bf8eSKris Kennaway 		return(ret);
337f579bf8eSKris Kennaway 
338f579bf8eSKris Kennaway 	ret=b->method->callback_ctrl(b,cmd,fp);
339f579bf8eSKris Kennaway 
340f579bf8eSKris Kennaway 	if (cb != NULL)
341f579bf8eSKris Kennaway 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
342f579bf8eSKris Kennaway 			0,ret);
343f579bf8eSKris Kennaway 	return(ret);
344f579bf8eSKris Kennaway 	}
345f579bf8eSKris Kennaway 
34674664626SKris Kennaway /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
34774664626SKris Kennaway  * do; but those macros have inappropriate return type, and for interfacing
34874664626SKris Kennaway  * from other programming languages, C macros aren't much of a help anyway. */
34974664626SKris Kennaway size_t BIO_ctrl_pending(BIO *bio)
35074664626SKris Kennaway 	{
35174664626SKris Kennaway 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
35274664626SKris Kennaway 	}
35374664626SKris Kennaway 
35474664626SKris Kennaway size_t BIO_ctrl_wpending(BIO *bio)
35574664626SKris Kennaway 	{
35674664626SKris Kennaway 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
35774664626SKris Kennaway 	}
35874664626SKris Kennaway 
35974664626SKris Kennaway 
36074664626SKris Kennaway /* put the 'bio' on the end of b's list of operators */
36174664626SKris Kennaway BIO *BIO_push(BIO *b, BIO *bio)
36274664626SKris Kennaway 	{
36374664626SKris Kennaway 	BIO *lb;
36474664626SKris Kennaway 
36574664626SKris Kennaway 	if (b == NULL) return(bio);
36674664626SKris Kennaway 	lb=b;
36774664626SKris Kennaway 	while (lb->next_bio != NULL)
36874664626SKris Kennaway 		lb=lb->next_bio;
36974664626SKris Kennaway 	lb->next_bio=bio;
37074664626SKris Kennaway 	if (bio != NULL)
37174664626SKris Kennaway 		bio->prev_bio=lb;
37274664626SKris Kennaway 	/* called to do internal processing */
37374664626SKris Kennaway 	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
37474664626SKris Kennaway 	return(b);
37574664626SKris Kennaway 	}
37674664626SKris Kennaway 
37774664626SKris Kennaway /* Remove the first and return the rest */
37874664626SKris Kennaway BIO *BIO_pop(BIO *b)
37974664626SKris Kennaway 	{
38074664626SKris Kennaway 	BIO *ret;
38174664626SKris Kennaway 
38274664626SKris Kennaway 	if (b == NULL) return(NULL);
38374664626SKris Kennaway 	ret=b->next_bio;
38474664626SKris Kennaway 
38574664626SKris Kennaway 	if (b->prev_bio != NULL)
38674664626SKris Kennaway 		b->prev_bio->next_bio=b->next_bio;
38774664626SKris Kennaway 	if (b->next_bio != NULL)
38874664626SKris Kennaway 		b->next_bio->prev_bio=b->prev_bio;
38974664626SKris Kennaway 
39074664626SKris Kennaway 	b->next_bio=NULL;
39174664626SKris Kennaway 	b->prev_bio=NULL;
39274664626SKris Kennaway 	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
39374664626SKris Kennaway 	return(ret);
39474664626SKris Kennaway 	}
39574664626SKris Kennaway 
39674664626SKris Kennaway BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
39774664626SKris Kennaway 	{
39874664626SKris Kennaway 	BIO *b,*last;
39974664626SKris Kennaway 
40074664626SKris Kennaway 	b=last=bio;
40174664626SKris Kennaway 	for (;;)
40274664626SKris Kennaway 		{
40374664626SKris Kennaway 		if (!BIO_should_retry(b)) break;
40474664626SKris Kennaway 		last=b;
40574664626SKris Kennaway 		b=b->next_bio;
40674664626SKris Kennaway 		if (b == NULL) break;
40774664626SKris Kennaway 		}
40874664626SKris Kennaway 	if (reason != NULL) *reason=last->retry_reason;
40974664626SKris Kennaway 	return(last);
41074664626SKris Kennaway 	}
41174664626SKris Kennaway 
41274664626SKris Kennaway int BIO_get_retry_reason(BIO *bio)
41374664626SKris Kennaway 	{
41474664626SKris Kennaway 	return(bio->retry_reason);
41574664626SKris Kennaway 	}
41674664626SKris Kennaway 
41774664626SKris Kennaway BIO *BIO_find_type(BIO *bio, int type)
41874664626SKris Kennaway 	{
41974664626SKris Kennaway 	int mt,mask;
42074664626SKris Kennaway 
421ddd58736SKris Kennaway 	if(!bio) return NULL;
42274664626SKris Kennaway 	mask=type&0xff;
42374664626SKris Kennaway 	do	{
42474664626SKris Kennaway 		if (bio->method != NULL)
42574664626SKris Kennaway 			{
42674664626SKris Kennaway 			mt=bio->method->type;
42774664626SKris Kennaway 
42874664626SKris Kennaway 			if (!mask)
42974664626SKris Kennaway 				{
43074664626SKris Kennaway 				if (mt & type) return(bio);
43174664626SKris Kennaway 				}
43274664626SKris Kennaway 			else if (mt == type)
43374664626SKris Kennaway 				return(bio);
43474664626SKris Kennaway 			}
43574664626SKris Kennaway 		bio=bio->next_bio;
43674664626SKris Kennaway 		} while (bio != NULL);
43774664626SKris Kennaway 	return(NULL);
43874664626SKris Kennaway 	}
43974664626SKris Kennaway 
440ddd58736SKris Kennaway BIO *BIO_next(BIO *b)
441ddd58736SKris Kennaway 	{
442ddd58736SKris Kennaway 	if(!b) return NULL;
443ddd58736SKris Kennaway 	return b->next_bio;
444ddd58736SKris Kennaway 	}
445ddd58736SKris Kennaway 
44674664626SKris Kennaway void BIO_free_all(BIO *bio)
44774664626SKris Kennaway 	{
44874664626SKris Kennaway 	BIO *b;
44974664626SKris Kennaway 	int ref;
45074664626SKris Kennaway 
45174664626SKris Kennaway 	while (bio != NULL)
45274664626SKris Kennaway 		{
45374664626SKris Kennaway 		b=bio;
45474664626SKris Kennaway 		ref=b->references;
45574664626SKris Kennaway 		bio=bio->next_bio;
45674664626SKris Kennaway 		BIO_free(b);
45774664626SKris Kennaway 		/* Since ref count > 1, don't free anyone else. */
45874664626SKris Kennaway 		if (ref > 1) break;
45974664626SKris Kennaway 		}
46074664626SKris Kennaway 	}
46174664626SKris Kennaway 
46274664626SKris Kennaway BIO *BIO_dup_chain(BIO *in)
46374664626SKris Kennaway 	{
46474664626SKris Kennaway 	BIO *ret=NULL,*eoc=NULL,*bio,*new;
46574664626SKris Kennaway 
46674664626SKris Kennaway 	for (bio=in; bio != NULL; bio=bio->next_bio)
46774664626SKris Kennaway 		{
46874664626SKris Kennaway 		if ((new=BIO_new(bio->method)) == NULL) goto err;
46974664626SKris Kennaway 		new->callback=bio->callback;
47074664626SKris Kennaway 		new->cb_arg=bio->cb_arg;
47174664626SKris Kennaway 		new->init=bio->init;
47274664626SKris Kennaway 		new->shutdown=bio->shutdown;
47374664626SKris Kennaway 		new->flags=bio->flags;
47474664626SKris Kennaway 
47574664626SKris Kennaway 		/* This will let SSL_s_sock() work with stdin/stdout */
47674664626SKris Kennaway 		new->num=bio->num;
47774664626SKris Kennaway 
47874664626SKris Kennaway 		if (!BIO_dup_state(bio,(char *)new))
47974664626SKris Kennaway 			{
48074664626SKris Kennaway 			BIO_free(new);
48174664626SKris Kennaway 			goto err;
48274664626SKris Kennaway 			}
48374664626SKris Kennaway 
48474664626SKris Kennaway 		/* copy app data */
48574664626SKris Kennaway 		if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data))
48674664626SKris Kennaway 			goto err;
48774664626SKris Kennaway 
48874664626SKris Kennaway 		if (ret == NULL)
48974664626SKris Kennaway 			{
49074664626SKris Kennaway 			eoc=new;
49174664626SKris Kennaway 			ret=eoc;
49274664626SKris Kennaway 			}
49374664626SKris Kennaway 		else
49474664626SKris Kennaway 			{
49574664626SKris Kennaway 			BIO_push(eoc,new);
49674664626SKris Kennaway 			eoc=new;
49774664626SKris Kennaway 			}
49874664626SKris Kennaway 		}
49974664626SKris Kennaway 	return(ret);
50074664626SKris Kennaway err:
50174664626SKris Kennaway 	if (ret != NULL)
50274664626SKris Kennaway 		BIO_free(ret);
50374664626SKris Kennaway 	return(NULL);
50474664626SKris Kennaway 	}
50574664626SKris Kennaway 
50674664626SKris Kennaway void BIO_copy_next_retry(BIO *b)
50774664626SKris Kennaway 	{
50874664626SKris Kennaway 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
50974664626SKris Kennaway 	b->retry_reason=b->next_bio->retry_reason;
51074664626SKris Kennaway 	}
51174664626SKris Kennaway 
512f579bf8eSKris Kennaway int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
513f579bf8eSKris Kennaway 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
51474664626SKris Kennaway 	{
51574664626SKris Kennaway 	bio_meth_num++;
51674664626SKris Kennaway 	return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth,
51774664626SKris Kennaway 		argl,argp,new_func,dup_func,free_func));
51874664626SKris Kennaway 	}
51974664626SKris Kennaway 
520f579bf8eSKris Kennaway int BIO_set_ex_data(BIO *bio, int idx, void *data)
52174664626SKris Kennaway 	{
52274664626SKris Kennaway 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
52374664626SKris Kennaway 	}
52474664626SKris Kennaway 
525f579bf8eSKris Kennaway void *BIO_get_ex_data(BIO *bio, int idx)
52674664626SKris Kennaway 	{
52774664626SKris Kennaway 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
52874664626SKris Kennaway 	}
52974664626SKris Kennaway 
530f579bf8eSKris Kennaway unsigned long BIO_number_read(BIO *bio)
531f579bf8eSKris Kennaway {
532f579bf8eSKris Kennaway 	if(bio) return bio->num_read;
533f579bf8eSKris Kennaway 	return 0;
534f579bf8eSKris Kennaway }
535f579bf8eSKris Kennaway 
536f579bf8eSKris Kennaway unsigned long BIO_number_written(BIO *bio)
537f579bf8eSKris Kennaway {
538f579bf8eSKris Kennaway 	if(bio) return bio->num_write;
539f579bf8eSKris Kennaway 	return 0;
540f579bf8eSKris Kennaway }
541ddd58736SKris Kennaway 
542ddd58736SKris Kennaway IMPLEMENT_STACK_OF(BIO)
543