xref: /freebsd/crypto/openssl/crypto/bio/bio_lib.c (revision fceca8a3)
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 
6674664626SKris Kennaway BIO *BIO_new(BIO_METHOD *method)
6774664626SKris Kennaway 	{
6874664626SKris Kennaway 	BIO *ret=NULL;
6974664626SKris Kennaway 
70ddd58736SKris Kennaway 	ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
7174664626SKris Kennaway 	if (ret == NULL)
7274664626SKris Kennaway 		{
7374664626SKris Kennaway 		BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
7474664626SKris Kennaway 		return(NULL);
7574664626SKris Kennaway 		}
7674664626SKris Kennaway 	if (!BIO_set(ret,method))
7774664626SKris Kennaway 		{
78ddd58736SKris Kennaway 		OPENSSL_free(ret);
7974664626SKris Kennaway 		ret=NULL;
8074664626SKris Kennaway 		}
8174664626SKris Kennaway 	return(ret);
8274664626SKris Kennaway 	}
8374664626SKris Kennaway 
8474664626SKris Kennaway int BIO_set(BIO *bio, BIO_METHOD *method)
8574664626SKris Kennaway 	{
8674664626SKris Kennaway 	bio->method=method;
8774664626SKris Kennaway 	bio->callback=NULL;
8874664626SKris Kennaway 	bio->cb_arg=NULL;
8974664626SKris Kennaway 	bio->init=0;
9074664626SKris Kennaway 	bio->shutdown=1;
9174664626SKris Kennaway 	bio->flags=0;
9274664626SKris Kennaway 	bio->retry_reason=0;
9374664626SKris Kennaway 	bio->num=0;
9474664626SKris Kennaway 	bio->ptr=NULL;
9574664626SKris Kennaway 	bio->prev_bio=NULL;
9674664626SKris Kennaway 	bio->next_bio=NULL;
9774664626SKris Kennaway 	bio->references=1;
9874664626SKris Kennaway 	bio->num_read=0L;
9974664626SKris Kennaway 	bio->num_write=0L;
1005c87c606SMark Murray 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
10174664626SKris Kennaway 	if (method->create != NULL)
10274664626SKris Kennaway 		if (!method->create(bio))
1035c87c606SMark Murray 			{
1045c87c606SMark Murray 			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
1055c87c606SMark Murray 					&bio->ex_data);
10674664626SKris Kennaway 			return(0);
1075c87c606SMark Murray 			}
10874664626SKris Kennaway 	return(1);
10974664626SKris Kennaway 	}
11074664626SKris Kennaway 
11174664626SKris Kennaway int BIO_free(BIO *a)
11274664626SKris Kennaway 	{
11374664626SKris Kennaway 	int ret=0,i;
11474664626SKris Kennaway 
11574664626SKris Kennaway 	if (a == NULL) return(0);
11674664626SKris Kennaway 
11774664626SKris Kennaway 	i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
11874664626SKris Kennaway #ifdef REF_PRINT
11974664626SKris Kennaway 	REF_PRINT("BIO",a);
12074664626SKris Kennaway #endif
12174664626SKris Kennaway 	if (i > 0) return(1);
12274664626SKris Kennaway #ifdef REF_CHECK
12374664626SKris Kennaway 	if (i < 0)
12474664626SKris Kennaway 		{
12574664626SKris Kennaway 		fprintf(stderr,"BIO_free, bad reference count\n");
12674664626SKris Kennaway 		abort();
12774664626SKris Kennaway 		}
12874664626SKris Kennaway #endif
12974664626SKris Kennaway 	if ((a->callback != NULL) &&
13074664626SKris Kennaway 		((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
13174664626SKris Kennaway 			return(i);
13274664626SKris Kennaway 
1335c87c606SMark Murray 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
13474664626SKris Kennaway 
13574664626SKris Kennaway 	if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
13674664626SKris Kennaway 	ret=a->method->destroy(a);
137ddd58736SKris Kennaway 	OPENSSL_free(a);
13874664626SKris Kennaway 	return(1);
13974664626SKris Kennaway 	}
14074664626SKris Kennaway 
141ddd58736SKris Kennaway void BIO_vfree(BIO *a)
142ddd58736SKris Kennaway     { BIO_free(a); }
143ddd58736SKris Kennaway 
14474664626SKris Kennaway int BIO_read(BIO *b, void *out, int outl)
14574664626SKris Kennaway 	{
14674664626SKris Kennaway 	int i;
14774664626SKris Kennaway 	long (*cb)();
14874664626SKris Kennaway 
14974664626SKris Kennaway 	if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
15074664626SKris Kennaway 		{
15174664626SKris Kennaway 		BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
15274664626SKris Kennaway 		return(-2);
15374664626SKris Kennaway 		}
15474664626SKris Kennaway 
15574664626SKris Kennaway 	cb=b->callback;
15674664626SKris Kennaway 	if ((cb != NULL) &&
15774664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
15874664626SKris Kennaway 			return(i);
15974664626SKris Kennaway 
16074664626SKris Kennaway 	if (!b->init)
16174664626SKris Kennaway 		{
16274664626SKris Kennaway 		BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
16374664626SKris Kennaway 		return(-2);
16474664626SKris Kennaway 		}
16574664626SKris Kennaway 
16674664626SKris Kennaway 	i=b->method->bread(b,out,outl);
16774664626SKris Kennaway 
16874664626SKris Kennaway 	if (i > 0) b->num_read+=(unsigned long)i;
16974664626SKris Kennaway 
17074664626SKris Kennaway 	if (cb != NULL)
17174664626SKris Kennaway 		i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
17274664626SKris Kennaway 			0L,(long)i);
17374664626SKris Kennaway 	return(i);
17474664626SKris Kennaway 	}
17574664626SKris Kennaway 
176f579bf8eSKris Kennaway int BIO_write(BIO *b, const void *in, int inl)
17774664626SKris Kennaway 	{
17874664626SKris Kennaway 	int i;
17974664626SKris Kennaway 	long (*cb)();
18074664626SKris Kennaway 
18174664626SKris Kennaway 	if (b == NULL)
18274664626SKris Kennaway 		return(0);
18374664626SKris Kennaway 
18474664626SKris Kennaway 	cb=b->callback;
18574664626SKris Kennaway 	if ((b->method == NULL) || (b->method->bwrite == NULL))
18674664626SKris Kennaway 		{
18774664626SKris Kennaway 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
18874664626SKris Kennaway 		return(-2);
18974664626SKris Kennaway 		}
19074664626SKris Kennaway 
19174664626SKris Kennaway 	if ((cb != NULL) &&
19274664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
19374664626SKris Kennaway 			return(i);
19474664626SKris Kennaway 
19574664626SKris Kennaway 	if (!b->init)
19674664626SKris Kennaway 		{
19774664626SKris Kennaway 		BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
19874664626SKris Kennaway 		return(-2);
19974664626SKris Kennaway 		}
20074664626SKris Kennaway 
20174664626SKris Kennaway 	i=b->method->bwrite(b,in,inl);
20274664626SKris Kennaway 
20374664626SKris Kennaway 	if (i > 0) b->num_write+=(unsigned long)i;
20474664626SKris Kennaway 
205ddd58736SKris Kennaway 	if (cb != NULL)
20674664626SKris Kennaway 		i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
20774664626SKris Kennaway 			0L,(long)i);
20874664626SKris Kennaway 	return(i);
20974664626SKris Kennaway 	}
21074664626SKris Kennaway 
21174664626SKris Kennaway int BIO_puts(BIO *b, const char *in)
21274664626SKris Kennaway 	{
21374664626SKris Kennaway 	int i;
21474664626SKris Kennaway 	long (*cb)();
21574664626SKris Kennaway 
21674664626SKris Kennaway 	if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
21774664626SKris Kennaway 		{
21874664626SKris Kennaway 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
21974664626SKris Kennaway 		return(-2);
22074664626SKris Kennaway 		}
22174664626SKris Kennaway 
22274664626SKris Kennaway 	cb=b->callback;
22374664626SKris Kennaway 
22474664626SKris Kennaway 	if ((cb != NULL) &&
22574664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
22674664626SKris Kennaway 			return(i);
22774664626SKris Kennaway 
22874664626SKris Kennaway 	if (!b->init)
22974664626SKris Kennaway 		{
23074664626SKris Kennaway 		BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
23174664626SKris Kennaway 		return(-2);
23274664626SKris Kennaway 		}
23374664626SKris Kennaway 
23474664626SKris Kennaway 	i=b->method->bputs(b,in);
23574664626SKris Kennaway 
236ddd58736SKris Kennaway 	if (i > 0) b->num_write+=(unsigned long)i;
237ddd58736SKris Kennaway 
23874664626SKris Kennaway 	if (cb != NULL)
23974664626SKris Kennaway 		i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
24074664626SKris Kennaway 			0L,(long)i);
24174664626SKris Kennaway 	return(i);
24274664626SKris Kennaway 	}
24374664626SKris Kennaway 
24474664626SKris Kennaway int BIO_gets(BIO *b, char *in, int inl)
24574664626SKris Kennaway 	{
24674664626SKris Kennaway 	int i;
24774664626SKris Kennaway 	long (*cb)();
24874664626SKris Kennaway 
24974664626SKris Kennaway 	if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
25074664626SKris Kennaway 		{
25174664626SKris Kennaway 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
25274664626SKris Kennaway 		return(-2);
25374664626SKris Kennaway 		}
25474664626SKris Kennaway 
25574664626SKris Kennaway 	cb=b->callback;
25674664626SKris Kennaway 
25774664626SKris Kennaway 	if ((cb != NULL) &&
25874664626SKris Kennaway 		((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
25974664626SKris Kennaway 			return(i);
26074664626SKris Kennaway 
26174664626SKris Kennaway 	if (!b->init)
26274664626SKris Kennaway 		{
26374664626SKris Kennaway 		BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
26474664626SKris Kennaway 		return(-2);
26574664626SKris Kennaway 		}
26674664626SKris Kennaway 
26774664626SKris Kennaway 	i=b->method->bgets(b,in,inl);
26874664626SKris Kennaway 
26974664626SKris Kennaway 	if (cb != NULL)
27074664626SKris Kennaway 		i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
27174664626SKris Kennaway 			0L,(long)i);
27274664626SKris Kennaway 	return(i);
27374664626SKris Kennaway 	}
27474664626SKris Kennaway 
2755c87c606SMark Murray int BIO_indent(BIO *b,int indent,int max)
2765c87c606SMark Murray 	{
2775c87c606SMark Murray 	if(indent < 0)
2785c87c606SMark Murray 		indent=0;
2795c87c606SMark Murray 	if(indent > max)
2805c87c606SMark Murray 		indent=max;
2815c87c606SMark Murray 	while(indent--)
2825c87c606SMark Murray 		if(BIO_puts(b," ") != 1)
2835c87c606SMark Murray 			return 0;
2845c87c606SMark Murray 	return 1;
2855c87c606SMark Murray 	}
2865c87c606SMark Murray 
28774664626SKris Kennaway long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
28874664626SKris Kennaway 	{
28974664626SKris Kennaway 	int i;
29074664626SKris Kennaway 
29174664626SKris Kennaway 	i=iarg;
29274664626SKris Kennaway 	return(BIO_ctrl(b,cmd,larg,(char *)&i));
29374664626SKris Kennaway 	}
29474664626SKris Kennaway 
29574664626SKris Kennaway char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
29674664626SKris Kennaway 	{
29774664626SKris Kennaway 	char *p=NULL;
29874664626SKris Kennaway 
29974664626SKris Kennaway 	if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
30074664626SKris Kennaway 		return(NULL);
30174664626SKris Kennaway 	else
30274664626SKris Kennaway 		return(p);
30374664626SKris Kennaway 	}
30474664626SKris Kennaway 
30574664626SKris Kennaway long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
30674664626SKris Kennaway 	{
30774664626SKris Kennaway 	long ret;
30874664626SKris Kennaway 	long (*cb)();
30974664626SKris Kennaway 
31074664626SKris Kennaway 	if (b == NULL) return(0);
31174664626SKris Kennaway 
31274664626SKris Kennaway 	if ((b->method == NULL) || (b->method->ctrl == NULL))
31374664626SKris Kennaway 		{
31474664626SKris Kennaway 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
31574664626SKris Kennaway 		return(-2);
31674664626SKris Kennaway 		}
31774664626SKris Kennaway 
31874664626SKris Kennaway 	cb=b->callback;
31974664626SKris Kennaway 
32074664626SKris Kennaway 	if ((cb != NULL) &&
32174664626SKris Kennaway 		((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
32274664626SKris Kennaway 		return(ret);
32374664626SKris Kennaway 
32474664626SKris Kennaway 	ret=b->method->ctrl(b,cmd,larg,parg);
32574664626SKris Kennaway 
32674664626SKris Kennaway 	if (cb != NULL)
32774664626SKris Kennaway 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
32874664626SKris Kennaway 			larg,ret);
32974664626SKris Kennaway 	return(ret);
33074664626SKris Kennaway 	}
33174664626SKris Kennaway 
332ddd58736SKris Kennaway long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
333f579bf8eSKris Kennaway 	{
334f579bf8eSKris Kennaway 	long ret;
335f579bf8eSKris Kennaway 	long (*cb)();
336f579bf8eSKris Kennaway 
337f579bf8eSKris Kennaway 	if (b == NULL) return(0);
338f579bf8eSKris Kennaway 
339f579bf8eSKris Kennaway 	if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
340f579bf8eSKris Kennaway 		{
341f579bf8eSKris Kennaway 		BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
342f579bf8eSKris Kennaway 		return(-2);
343f579bf8eSKris Kennaway 		}
344f579bf8eSKris Kennaway 
345f579bf8eSKris Kennaway 	cb=b->callback;
346f579bf8eSKris Kennaway 
347f579bf8eSKris Kennaway 	if ((cb != NULL) &&
348f579bf8eSKris Kennaway 		((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
349f579bf8eSKris Kennaway 		return(ret);
350f579bf8eSKris Kennaway 
351f579bf8eSKris Kennaway 	ret=b->method->callback_ctrl(b,cmd,fp);
352f579bf8eSKris Kennaway 
353f579bf8eSKris Kennaway 	if (cb != NULL)
354f579bf8eSKris Kennaway 		ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
355f579bf8eSKris Kennaway 			0,ret);
356f579bf8eSKris Kennaway 	return(ret);
357f579bf8eSKris Kennaway 	}
358f579bf8eSKris Kennaway 
35974664626SKris Kennaway /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
36074664626SKris Kennaway  * do; but those macros have inappropriate return type, and for interfacing
36174664626SKris Kennaway  * from other programming languages, C macros aren't much of a help anyway. */
36274664626SKris Kennaway size_t BIO_ctrl_pending(BIO *bio)
36374664626SKris Kennaway 	{
36474664626SKris Kennaway 	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
36574664626SKris Kennaway 	}
36674664626SKris Kennaway 
36774664626SKris Kennaway size_t BIO_ctrl_wpending(BIO *bio)
36874664626SKris Kennaway 	{
36974664626SKris Kennaway 	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
37074664626SKris Kennaway 	}
37174664626SKris Kennaway 
37274664626SKris Kennaway 
37374664626SKris Kennaway /* put the 'bio' on the end of b's list of operators */
37474664626SKris Kennaway BIO *BIO_push(BIO *b, BIO *bio)
37574664626SKris Kennaway 	{
37674664626SKris Kennaway 	BIO *lb;
37774664626SKris Kennaway 
37874664626SKris Kennaway 	if (b == NULL) return(bio);
37974664626SKris Kennaway 	lb=b;
38074664626SKris Kennaway 	while (lb->next_bio != NULL)
38174664626SKris Kennaway 		lb=lb->next_bio;
38274664626SKris Kennaway 	lb->next_bio=bio;
38374664626SKris Kennaway 	if (bio != NULL)
38474664626SKris Kennaway 		bio->prev_bio=lb;
38574664626SKris Kennaway 	/* called to do internal processing */
38674664626SKris Kennaway 	BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
38774664626SKris Kennaway 	return(b);
38874664626SKris Kennaway 	}
38974664626SKris Kennaway 
39074664626SKris Kennaway /* Remove the first and return the rest */
39174664626SKris Kennaway BIO *BIO_pop(BIO *b)
39274664626SKris Kennaway 	{
39374664626SKris Kennaway 	BIO *ret;
39474664626SKris Kennaway 
39574664626SKris Kennaway 	if (b == NULL) return(NULL);
39674664626SKris Kennaway 	ret=b->next_bio;
39774664626SKris Kennaway 
398fceca8a3SJacques Vidrine 	BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
399fceca8a3SJacques Vidrine 
40074664626SKris Kennaway 	if (b->prev_bio != NULL)
40174664626SKris Kennaway 		b->prev_bio->next_bio=b->next_bio;
40274664626SKris Kennaway 	if (b->next_bio != NULL)
40374664626SKris Kennaway 		b->next_bio->prev_bio=b->prev_bio;
40474664626SKris Kennaway 
40574664626SKris Kennaway 	b->next_bio=NULL;
40674664626SKris Kennaway 	b->prev_bio=NULL;
40774664626SKris Kennaway 	return(ret);
40874664626SKris Kennaway 	}
40974664626SKris Kennaway 
41074664626SKris Kennaway BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
41174664626SKris Kennaway 	{
41274664626SKris Kennaway 	BIO *b,*last;
41374664626SKris Kennaway 
41474664626SKris Kennaway 	b=last=bio;
41574664626SKris Kennaway 	for (;;)
41674664626SKris Kennaway 		{
41774664626SKris Kennaway 		if (!BIO_should_retry(b)) break;
41874664626SKris Kennaway 		last=b;
41974664626SKris Kennaway 		b=b->next_bio;
42074664626SKris Kennaway 		if (b == NULL) break;
42174664626SKris Kennaway 		}
42274664626SKris Kennaway 	if (reason != NULL) *reason=last->retry_reason;
42374664626SKris Kennaway 	return(last);
42474664626SKris Kennaway 	}
42574664626SKris Kennaway 
42674664626SKris Kennaway int BIO_get_retry_reason(BIO *bio)
42774664626SKris Kennaway 	{
42874664626SKris Kennaway 	return(bio->retry_reason);
42974664626SKris Kennaway 	}
43074664626SKris Kennaway 
43174664626SKris Kennaway BIO *BIO_find_type(BIO *bio, int type)
43274664626SKris Kennaway 	{
43374664626SKris Kennaway 	int mt,mask;
43474664626SKris Kennaway 
435ddd58736SKris Kennaway 	if(!bio) return NULL;
43674664626SKris Kennaway 	mask=type&0xff;
43774664626SKris Kennaway 	do	{
43874664626SKris Kennaway 		if (bio->method != NULL)
43974664626SKris Kennaway 			{
44074664626SKris Kennaway 			mt=bio->method->type;
44174664626SKris Kennaway 
44274664626SKris Kennaway 			if (!mask)
44374664626SKris Kennaway 				{
44474664626SKris Kennaway 				if (mt & type) return(bio);
44574664626SKris Kennaway 				}
44674664626SKris Kennaway 			else if (mt == type)
44774664626SKris Kennaway 				return(bio);
44874664626SKris Kennaway 			}
44974664626SKris Kennaway 		bio=bio->next_bio;
45074664626SKris Kennaway 		} while (bio != NULL);
45174664626SKris Kennaway 	return(NULL);
45274664626SKris Kennaway 	}
45374664626SKris Kennaway 
454ddd58736SKris Kennaway BIO *BIO_next(BIO *b)
455ddd58736SKris Kennaway 	{
456ddd58736SKris Kennaway 	if(!b) return NULL;
457ddd58736SKris Kennaway 	return b->next_bio;
458ddd58736SKris Kennaway 	}
459ddd58736SKris Kennaway 
46074664626SKris Kennaway void BIO_free_all(BIO *bio)
46174664626SKris Kennaway 	{
46274664626SKris Kennaway 	BIO *b;
46374664626SKris Kennaway 	int ref;
46474664626SKris Kennaway 
46574664626SKris Kennaway 	while (bio != NULL)
46674664626SKris Kennaway 		{
46774664626SKris Kennaway 		b=bio;
46874664626SKris Kennaway 		ref=b->references;
46974664626SKris Kennaway 		bio=bio->next_bio;
47074664626SKris Kennaway 		BIO_free(b);
47174664626SKris Kennaway 		/* Since ref count > 1, don't free anyone else. */
47274664626SKris Kennaway 		if (ref > 1) break;
47374664626SKris Kennaway 		}
47474664626SKris Kennaway 	}
47574664626SKris Kennaway 
47674664626SKris Kennaway BIO *BIO_dup_chain(BIO *in)
47774664626SKris Kennaway 	{
47874664626SKris Kennaway 	BIO *ret=NULL,*eoc=NULL,*bio,*new;
47974664626SKris Kennaway 
48074664626SKris Kennaway 	for (bio=in; bio != NULL; bio=bio->next_bio)
48174664626SKris Kennaway 		{
48274664626SKris Kennaway 		if ((new=BIO_new(bio->method)) == NULL) goto err;
48374664626SKris Kennaway 		new->callback=bio->callback;
48474664626SKris Kennaway 		new->cb_arg=bio->cb_arg;
48574664626SKris Kennaway 		new->init=bio->init;
48674664626SKris Kennaway 		new->shutdown=bio->shutdown;
48774664626SKris Kennaway 		new->flags=bio->flags;
48874664626SKris Kennaway 
48974664626SKris Kennaway 		/* This will let SSL_s_sock() work with stdin/stdout */
49074664626SKris Kennaway 		new->num=bio->num;
49174664626SKris Kennaway 
49274664626SKris Kennaway 		if (!BIO_dup_state(bio,(char *)new))
49374664626SKris Kennaway 			{
49474664626SKris Kennaway 			BIO_free(new);
49574664626SKris Kennaway 			goto err;
49674664626SKris Kennaway 			}
49774664626SKris Kennaway 
49874664626SKris Kennaway 		/* copy app data */
4995c87c606SMark Murray 		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
5005c87c606SMark Murray 					&bio->ex_data))
50174664626SKris Kennaway 			goto err;
50274664626SKris Kennaway 
50374664626SKris Kennaway 		if (ret == NULL)
50474664626SKris Kennaway 			{
50574664626SKris Kennaway 			eoc=new;
50674664626SKris Kennaway 			ret=eoc;
50774664626SKris Kennaway 			}
50874664626SKris Kennaway 		else
50974664626SKris Kennaway 			{
51074664626SKris Kennaway 			BIO_push(eoc,new);
51174664626SKris Kennaway 			eoc=new;
51274664626SKris Kennaway 			}
51374664626SKris Kennaway 		}
51474664626SKris Kennaway 	return(ret);
51574664626SKris Kennaway err:
51674664626SKris Kennaway 	if (ret != NULL)
51774664626SKris Kennaway 		BIO_free(ret);
51874664626SKris Kennaway 	return(NULL);
51974664626SKris Kennaway 	}
52074664626SKris Kennaway 
52174664626SKris Kennaway void BIO_copy_next_retry(BIO *b)
52274664626SKris Kennaway 	{
52374664626SKris Kennaway 	BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
52474664626SKris Kennaway 	b->retry_reason=b->next_bio->retry_reason;
52574664626SKris Kennaway 	}
52674664626SKris Kennaway 
527f579bf8eSKris Kennaway int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
528f579bf8eSKris Kennaway 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
52974664626SKris Kennaway 	{
5305c87c606SMark Murray 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
5315c87c606SMark Murray 				new_func, dup_func, free_func);
53274664626SKris Kennaway 	}
53374664626SKris Kennaway 
534f579bf8eSKris Kennaway int BIO_set_ex_data(BIO *bio, int idx, void *data)
53574664626SKris Kennaway 	{
53674664626SKris Kennaway 	return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
53774664626SKris Kennaway 	}
53874664626SKris Kennaway 
539f579bf8eSKris Kennaway void *BIO_get_ex_data(BIO *bio, int idx)
54074664626SKris Kennaway 	{
54174664626SKris Kennaway 	return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
54274664626SKris Kennaway 	}
54374664626SKris Kennaway 
544f579bf8eSKris Kennaway unsigned long BIO_number_read(BIO *bio)
545f579bf8eSKris Kennaway {
546f579bf8eSKris Kennaway 	if(bio) return bio->num_read;
547f579bf8eSKris Kennaway 	return 0;
548f579bf8eSKris Kennaway }
549f579bf8eSKris Kennaway 
550f579bf8eSKris Kennaway unsigned long BIO_number_written(BIO *bio)
551f579bf8eSKris Kennaway {
552f579bf8eSKris Kennaway 	if(bio) return bio->num_write;
553f579bf8eSKris Kennaway 	return 0;
554f579bf8eSKris Kennaway }
555ddd58736SKris Kennaway 
556ddd58736SKris Kennaway IMPLEMENT_STACK_OF(BIO)
557