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. 8296341Sdelphij * 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). 15296341Sdelphij * 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. 22296341Sdelphij * 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 :-). 37296341Sdelphij * 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)" 40296341Sdelphij * 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. 52296341Sdelphij * 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) 67296341Sdelphij{ 68296341Sdelphij BIO *ret = NULL; 6955714Skris 70296341Sdelphij ret = (BIO *)OPENSSL_malloc(sizeof(BIO)); 71296341Sdelphij if (ret == NULL) { 72296341Sdelphij BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE); 73296341Sdelphij return (NULL); 74296341Sdelphij } 75296341Sdelphij if (!BIO_set(ret, method)) { 76296341Sdelphij OPENSSL_free(ret); 77296341Sdelphij ret = NULL; 78296341Sdelphij } 79296341Sdelphij return (ret); 80296341Sdelphij} 8155714Skris 8255714Skrisint BIO_set(BIO *bio, BIO_METHOD *method) 83296341Sdelphij{ 84296341Sdelphij bio->method = method; 85296341Sdelphij bio->callback = NULL; 86296341Sdelphij bio->cb_arg = NULL; 87296341Sdelphij bio->init = 0; 88296341Sdelphij bio->shutdown = 1; 89296341Sdelphij bio->flags = 0; 90296341Sdelphij bio->retry_reason = 0; 91296341Sdelphij bio->num = 0; 92296341Sdelphij bio->ptr = NULL; 93296341Sdelphij bio->prev_bio = NULL; 94296341Sdelphij bio->next_bio = NULL; 95296341Sdelphij bio->references = 1; 96296341Sdelphij bio->num_read = 0L; 97296341Sdelphij bio->num_write = 0L; 98296341Sdelphij CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 99296341Sdelphij if (method->create != NULL) 100296341Sdelphij if (!method->create(bio)) { 101296341Sdelphij CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); 102296341Sdelphij return (0); 103296341Sdelphij } 104296341Sdelphij return (1); 105296341Sdelphij} 10655714Skris 10755714Skrisint BIO_free(BIO *a) 108296341Sdelphij{ 109296341Sdelphij int i; 11055714Skris 111296341Sdelphij if (a == NULL) 112296341Sdelphij return (0); 11355714Skris 114296341Sdelphij i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO); 11555714Skris#ifdef REF_PRINT 116296341Sdelphij REF_PRINT("BIO", a); 11755714Skris#endif 118296341Sdelphij if (i > 0) 119296341Sdelphij return (1); 12055714Skris#ifdef REF_CHECK 121296341Sdelphij if (i < 0) { 122296341Sdelphij fprintf(stderr, "BIO_free, bad reference count\n"); 123296341Sdelphij abort(); 124296341Sdelphij } 12555714Skris#endif 126296341Sdelphij if ((a->callback != NULL) && 127296341Sdelphij ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0)) 128296341Sdelphij return (i); 12955714Skris 130296341Sdelphij CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); 13155714Skris 132296341Sdelphij if ((a->method != NULL) && (a->method->destroy != NULL)) 133296341Sdelphij a->method->destroy(a); 134296341Sdelphij OPENSSL_free(a); 135296341Sdelphij return (1); 136296341Sdelphij} 13755714Skris 13868651Skrisvoid BIO_vfree(BIO *a) 139296341Sdelphij{ 140296341Sdelphij BIO_free(a); 141296341Sdelphij} 14268651Skris 143167612Ssimonvoid BIO_clear_flags(BIO *b, int flags) 144296341Sdelphij{ 145296341Sdelphij b->flags &= ~flags; 146296341Sdelphij} 147167612Ssimon 148296341Sdelphijint BIO_test_flags(const BIO *b, int flags) 149296341Sdelphij{ 150296341Sdelphij return (b->flags & flags); 151296341Sdelphij} 152167612Ssimon 153296341Sdelphijvoid BIO_set_flags(BIO *b, int flags) 154296341Sdelphij{ 155296341Sdelphij b->flags |= flags; 156296341Sdelphij} 157167612Ssimon 158296341Sdelphijlong (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *, 159296341Sdelphij int, long, long) { 160296341Sdelphij return b->callback; 161296341Sdelphij} 162167612Ssimon 163296341Sdelphijvoid BIO_set_callback(BIO *b, 164296341Sdelphij long (*cb) (struct bio_st *, int, const char *, int, 165296341Sdelphij long, long)) 166296341Sdelphij{ 167296341Sdelphij b->callback = cb; 168296341Sdelphij} 169167612Ssimon 170167612Ssimonvoid BIO_set_callback_arg(BIO *b, char *arg) 171296341Sdelphij{ 172296341Sdelphij b->cb_arg = arg; 173296341Sdelphij} 174167612Ssimon 175296341Sdelphijchar *BIO_get_callback_arg(const BIO *b) 176296341Sdelphij{ 177296341Sdelphij return b->cb_arg; 178296341Sdelphij} 179167612Ssimon 180296341Sdelphijconst char *BIO_method_name(const BIO *b) 181296341Sdelphij{ 182296341Sdelphij return b->method->name; 183296341Sdelphij} 184167612Ssimon 185167612Ssimonint BIO_method_type(const BIO *b) 186296341Sdelphij{ 187296341Sdelphij return b->method->type; 188296341Sdelphij} 189167612Ssimon 19055714Skrisint BIO_read(BIO *b, void *out, int outl) 191296341Sdelphij{ 192296341Sdelphij int i; 193296341Sdelphij long (*cb) (BIO *, int, const char *, int, long, long); 19455714Skris 195296341Sdelphij if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) { 196296341Sdelphij BIOerr(BIO_F_BIO_READ, BIO_R_UNSUPPORTED_METHOD); 197296341Sdelphij return (-2); 198296341Sdelphij } 19955714Skris 200296341Sdelphij cb = b->callback; 201296341Sdelphij if ((cb != NULL) && 202296341Sdelphij ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0)) 203296341Sdelphij return (i); 20455714Skris 205296341Sdelphij if (!b->init) { 206296341Sdelphij BIOerr(BIO_F_BIO_READ, BIO_R_UNINITIALIZED); 207296341Sdelphij return (-2); 208296341Sdelphij } 20955714Skris 210296341Sdelphij i = b->method->bread(b, out, outl); 21155714Skris 212296341Sdelphij if (i > 0) 213296341Sdelphij b->num_read += (unsigned long)i; 21455714Skris 215296341Sdelphij if (cb != NULL) 216296341Sdelphij i = (int)cb(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0L, (long)i); 217296341Sdelphij return (i); 218296341Sdelphij} 21955714Skris 22059191Skrisint BIO_write(BIO *b, const void *in, int inl) 221296341Sdelphij{ 222296341Sdelphij int i; 223296341Sdelphij long (*cb) (BIO *, int, const char *, int, long, long); 22455714Skris 225296341Sdelphij if (b == NULL) 226296341Sdelphij return (0); 22755714Skris 228296341Sdelphij cb = b->callback; 229296341Sdelphij if ((b->method == NULL) || (b->method->bwrite == NULL)) { 230296341Sdelphij BIOerr(BIO_F_BIO_WRITE, BIO_R_UNSUPPORTED_METHOD); 231296341Sdelphij return (-2); 232296341Sdelphij } 23355714Skris 234296341Sdelphij if ((cb != NULL) && 235296341Sdelphij ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0)) 236296341Sdelphij return (i); 23755714Skris 238296341Sdelphij if (!b->init) { 239296341Sdelphij BIOerr(BIO_F_BIO_WRITE, BIO_R_UNINITIALIZED); 240296341Sdelphij return (-2); 241296341Sdelphij } 24255714Skris 243296341Sdelphij i = b->method->bwrite(b, in, inl); 24455714Skris 245296341Sdelphij if (i > 0) 246296341Sdelphij b->num_write += (unsigned long)i; 24755714Skris 248296341Sdelphij if (cb != NULL) 249296341Sdelphij i = (int)cb(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0L, (long)i); 250296341Sdelphij return (i); 251296341Sdelphij} 25255714Skris 25355714Skrisint BIO_puts(BIO *b, const char *in) 254296341Sdelphij{ 255296341Sdelphij int i; 256296341Sdelphij long (*cb) (BIO *, int, const char *, int, long, long); 25755714Skris 258296341Sdelphij if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) { 259296341Sdelphij BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD); 260296341Sdelphij return (-2); 261296341Sdelphij } 26255714Skris 263296341Sdelphij cb = b->callback; 26455714Skris 265296341Sdelphij if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0)) 266296341Sdelphij return (i); 26755714Skris 268296341Sdelphij if (!b->init) { 269296341Sdelphij BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED); 270296341Sdelphij return (-2); 271296341Sdelphij } 27255714Skris 273296341Sdelphij i = b->method->bputs(b, in); 27455714Skris 275296341Sdelphij if (i > 0) 276296341Sdelphij b->num_write += (unsigned long)i; 27768651Skris 278296341Sdelphij if (cb != NULL) 279296341Sdelphij i = (int)cb(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0L, (long)i); 280296341Sdelphij return (i); 281296341Sdelphij} 28255714Skris 28355714Skrisint BIO_gets(BIO *b, char *in, int inl) 284296341Sdelphij{ 285296341Sdelphij int i; 286296341Sdelphij long (*cb) (BIO *, int, const char *, int, long, long); 28755714Skris 288296341Sdelphij if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) { 289296341Sdelphij BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD); 290296341Sdelphij return (-2); 291296341Sdelphij } 29255714Skris 293296341Sdelphij cb = b->callback; 29455714Skris 295296341Sdelphij if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0)) 296296341Sdelphij return (i); 29755714Skris 298296341Sdelphij if (!b->init) { 299296341Sdelphij BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED); 300296341Sdelphij return (-2); 301296341Sdelphij } 30255714Skris 303296341Sdelphij i = b->method->bgets(b, in, inl); 30455714Skris 305296341Sdelphij if (cb != NULL) 306296341Sdelphij i = (int)cb(b, BIO_CB_GETS | BIO_CB_RETURN, in, inl, 0L, (long)i); 307296341Sdelphij return (i); 308296341Sdelphij} 30955714Skris 310296341Sdelphijint BIO_indent(BIO *b, int indent, int max) 311296341Sdelphij{ 312296341Sdelphij if (indent < 0) 313296341Sdelphij indent = 0; 314296341Sdelphij if (indent > max) 315296341Sdelphij indent = max; 316296341Sdelphij while (indent--) 317296341Sdelphij if (BIO_puts(b, " ") != 1) 318296341Sdelphij return 0; 319296341Sdelphij return 1; 320296341Sdelphij} 321109998Smarkm 32255714Skrislong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) 323296341Sdelphij{ 324296341Sdelphij int i; 32555714Skris 326296341Sdelphij i = iarg; 327296341Sdelphij return (BIO_ctrl(b, cmd, larg, (char *)&i)); 328296341Sdelphij} 32955714Skris 33055714Skrischar *BIO_ptr_ctrl(BIO *b, int cmd, long larg) 331296341Sdelphij{ 332296341Sdelphij char *p = NULL; 33355714Skris 334296341Sdelphij if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0) 335296341Sdelphij return (NULL); 336296341Sdelphij else 337296341Sdelphij return (p); 338296341Sdelphij} 33955714Skris 34055714Skrislong BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 341296341Sdelphij{ 342296341Sdelphij long ret; 343296341Sdelphij long (*cb) (BIO *, int, const char *, int, long, long); 34455714Skris 345296341Sdelphij if (b == NULL) 346296341Sdelphij return (0); 34755714Skris 348296341Sdelphij if ((b->method == NULL) || (b->method->ctrl == NULL)) { 349296341Sdelphij BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD); 350296341Sdelphij return (-2); 351296341Sdelphij } 35255714Skris 353296341Sdelphij cb = b->callback; 35455714Skris 355296341Sdelphij if ((cb != NULL) && 356296341Sdelphij ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0)) 357296341Sdelphij return (ret); 35855714Skris 359296341Sdelphij ret = b->method->ctrl(b, cmd, larg, parg); 36055714Skris 361296341Sdelphij if (cb != NULL) 362296341Sdelphij ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret); 363296341Sdelphij return (ret); 364296341Sdelphij} 36555714Skris 366296341Sdelphijlong BIO_callback_ctrl(BIO *b, int cmd, 367296341Sdelphij void (*fp) (struct bio_st *, int, const char *, int, 368296341Sdelphij long, long)) 369296341Sdelphij{ 370296341Sdelphij long ret; 371296341Sdelphij long (*cb) (BIO *, int, const char *, int, long, long); 37259191Skris 373296341Sdelphij if (b == NULL) 374296341Sdelphij return (0); 37559191Skris 376296341Sdelphij if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) { 377296341Sdelphij BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD); 378296341Sdelphij return (-2); 379296341Sdelphij } 38059191Skris 381296341Sdelphij cb = b->callback; 38259191Skris 383296341Sdelphij if ((cb != NULL) && 384296341Sdelphij ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0)) 385296341Sdelphij return (ret); 38659191Skris 387296341Sdelphij ret = b->method->callback_ctrl(b, cmd, fp); 38859191Skris 389296341Sdelphij if (cb != NULL) 390296341Sdelphij ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret); 391296341Sdelphij return (ret); 392296341Sdelphij} 39359191Skris 394296341Sdelphij/* 395296341Sdelphij * It is unfortunate to duplicate in functions what the BIO_(w)pending macros 39655714Skris * do; but those macros have inappropriate return type, and for interfacing 397296341Sdelphij * from other programming languages, C macros aren't much of a help anyway. 398296341Sdelphij */ 39955714Skrissize_t BIO_ctrl_pending(BIO *bio) 400296341Sdelphij{ 401296341Sdelphij return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 402296341Sdelphij} 40355714Skris 40455714Skrissize_t BIO_ctrl_wpending(BIO *bio) 405296341Sdelphij{ 406296341Sdelphij return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 407296341Sdelphij} 40855714Skris 40955714Skris/* put the 'bio' on the end of b's list of operators */ 41055714SkrisBIO *BIO_push(BIO *b, BIO *bio) 411296341Sdelphij{ 412296341Sdelphij BIO *lb; 41355714Skris 414296341Sdelphij if (b == NULL) 415296341Sdelphij return (bio); 416296341Sdelphij lb = b; 417296341Sdelphij while (lb->next_bio != NULL) 418296341Sdelphij lb = lb->next_bio; 419296341Sdelphij lb->next_bio = bio; 420296341Sdelphij if (bio != NULL) 421296341Sdelphij bio->prev_bio = lb; 422296341Sdelphij /* called to do internal processing */ 423296341Sdelphij BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb); 424296341Sdelphij return (b); 425296341Sdelphij} 42655714Skris 42755714Skris/* Remove the first and return the rest */ 42855714SkrisBIO *BIO_pop(BIO *b) 429296341Sdelphij{ 430296341Sdelphij BIO *ret; 43155714Skris 432296341Sdelphij if (b == NULL) 433296341Sdelphij return (NULL); 434296341Sdelphij ret = b->next_bio; 43555714Skris 436296341Sdelphij BIO_ctrl(b, BIO_CTRL_POP, 0, b); 437111147Snectar 438296341Sdelphij if (b->prev_bio != NULL) 439296341Sdelphij b->prev_bio->next_bio = b->next_bio; 440296341Sdelphij if (b->next_bio != NULL) 441296341Sdelphij b->next_bio->prev_bio = b->prev_bio; 44255714Skris 443296341Sdelphij b->next_bio = NULL; 444296341Sdelphij b->prev_bio = NULL; 445296341Sdelphij return (ret); 446296341Sdelphij} 44755714Skris 44855714SkrisBIO *BIO_get_retry_BIO(BIO *bio, int *reason) 449296341Sdelphij{ 450296341Sdelphij BIO *b, *last; 45155714Skris 452296341Sdelphij b = last = bio; 453296341Sdelphij for (;;) { 454296341Sdelphij if (!BIO_should_retry(b)) 455296341Sdelphij break; 456296341Sdelphij last = b; 457296341Sdelphij b = b->next_bio; 458296341Sdelphij if (b == NULL) 459296341Sdelphij break; 460296341Sdelphij } 461296341Sdelphij if (reason != NULL) 462296341Sdelphij *reason = last->retry_reason; 463296341Sdelphij return (last); 464296341Sdelphij} 46555714Skris 46655714Skrisint BIO_get_retry_reason(BIO *bio) 467296341Sdelphij{ 468296341Sdelphij return (bio->retry_reason); 469296341Sdelphij} 47055714Skris 47155714SkrisBIO *BIO_find_type(BIO *bio, int type) 472296341Sdelphij{ 473296341Sdelphij int mt, mask; 47455714Skris 475296341Sdelphij if (!bio) 476296341Sdelphij return NULL; 477296341Sdelphij mask = type & 0xff; 478296341Sdelphij do { 479296341Sdelphij if (bio->method != NULL) { 480296341Sdelphij mt = bio->method->type; 48155714Skris 482296341Sdelphij if (!mask) { 483296341Sdelphij if (mt & type) 484296341Sdelphij return (bio); 485296341Sdelphij } else if (mt == type) 486296341Sdelphij return (bio); 487296341Sdelphij } 488296341Sdelphij bio = bio->next_bio; 489296341Sdelphij } while (bio != NULL); 490296341Sdelphij return (NULL); 491296341Sdelphij} 49255714Skris 49368651SkrisBIO *BIO_next(BIO *b) 494296341Sdelphij{ 495296341Sdelphij if (!b) 496296341Sdelphij return NULL; 497296341Sdelphij return b->next_bio; 498296341Sdelphij} 49968651Skris 50055714Skrisvoid BIO_free_all(BIO *bio) 501296341Sdelphij{ 502296341Sdelphij BIO *b; 503296341Sdelphij int ref; 50455714Skris 505296341Sdelphij while (bio != NULL) { 506296341Sdelphij b = bio; 507296341Sdelphij ref = b->references; 508296341Sdelphij bio = bio->next_bio; 509296341Sdelphij BIO_free(b); 510296341Sdelphij /* Since ref count > 1, don't free anyone else. */ 511296341Sdelphij if (ref > 1) 512296341Sdelphij break; 513296341Sdelphij } 514296341Sdelphij} 51555714Skris 51655714SkrisBIO *BIO_dup_chain(BIO *in) 517296341Sdelphij{ 518296341Sdelphij BIO *ret = NULL, *eoc = NULL, *bio, *new_bio; 51955714Skris 520296341Sdelphij for (bio = in; bio != NULL; bio = bio->next_bio) { 521296341Sdelphij if ((new_bio = BIO_new(bio->method)) == NULL) 522296341Sdelphij goto err; 523296341Sdelphij new_bio->callback = bio->callback; 524296341Sdelphij new_bio->cb_arg = bio->cb_arg; 525296341Sdelphij new_bio->init = bio->init; 526296341Sdelphij new_bio->shutdown = bio->shutdown; 527296341Sdelphij new_bio->flags = bio->flags; 52855714Skris 529296341Sdelphij /* This will let SSL_s_sock() work with stdin/stdout */ 530296341Sdelphij new_bio->num = bio->num; 53155714Skris 532296341Sdelphij if (!BIO_dup_state(bio, (char *)new_bio)) { 533296341Sdelphij BIO_free(new_bio); 534296341Sdelphij goto err; 535296341Sdelphij } 53655714Skris 537296341Sdelphij /* copy app data */ 538296341Sdelphij if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, 539284295Sdelphij &bio->ex_data)) { 540284295Sdelphij BIO_free(new_bio); 541296341Sdelphij goto err; 542284295Sdelphij } 54355714Skris 544296341Sdelphij if (ret == NULL) { 545296341Sdelphij eoc = new_bio; 546296341Sdelphij ret = eoc; 547296341Sdelphij } else { 548296341Sdelphij BIO_push(eoc, new_bio); 549296341Sdelphij eoc = new_bio; 550296341Sdelphij } 551296341Sdelphij } 552296341Sdelphij return (ret); 553296341Sdelphij err: 554296341Sdelphij BIO_free_all(ret); 555284295Sdelphij 556296341Sdelphij return (NULL); 557296341Sdelphij} 55855714Skris 55955714Skrisvoid BIO_copy_next_retry(BIO *b) 560296341Sdelphij{ 561296341Sdelphij BIO_set_flags(b, BIO_get_retry_flags(b->next_bio)); 562296341Sdelphij b->retry_reason = b->next_bio->retry_reason; 563296341Sdelphij} 56455714Skris 56559191Skrisint BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 566296341Sdelphij CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 567296341Sdelphij{ 568296341Sdelphij return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, 569296341Sdelphij new_func, dup_func, free_func); 570296341Sdelphij} 57155714Skris 57259191Skrisint BIO_set_ex_data(BIO *bio, int idx, void *data) 573296341Sdelphij{ 574296341Sdelphij return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data)); 575296341Sdelphij} 57655714Skris 57759191Skrisvoid *BIO_get_ex_data(BIO *bio, int idx) 578296341Sdelphij{ 579296341Sdelphij return (CRYPTO_get_ex_data(&(bio->ex_data), idx)); 580296341Sdelphij} 58155714Skris 58259191Skrisunsigned long BIO_number_read(BIO *bio) 58359191Skris{ 584296341Sdelphij if (bio) 585296341Sdelphij return bio->num_read; 586296341Sdelphij return 0; 58759191Skris} 58859191Skris 58959191Skrisunsigned long BIO_number_written(BIO *bio) 59059191Skris{ 591296341Sdelphij if (bio) 592296341Sdelphij return bio->num_write; 593296341Sdelphij return 0; 59459191Skris} 59568651Skris 59668651SkrisIMPLEMENT_STACK_OF(BIO) 597