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