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.
8280304Sjkim *
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).
15280304Sjkim *
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.
22280304Sjkim *
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 :-).
37280304Sjkim * 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)"
40280304Sjkim *
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.
52280304Sjkim *
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)
67280304Sjkim{
68280304Sjkim    BIO *ret = NULL;
6955714Skris
70280304Sjkim    ret = (BIO *)OPENSSL_malloc(sizeof(BIO));
71280304Sjkim    if (ret == NULL) {
72280304Sjkim        BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
73280304Sjkim        return (NULL);
74280304Sjkim    }
75280304Sjkim    if (!BIO_set(ret, method)) {
76280304Sjkim        OPENSSL_free(ret);
77280304Sjkim        ret = NULL;
78280304Sjkim    }
79280304Sjkim    return (ret);
80280304Sjkim}
8155714Skris
8255714Skrisint BIO_set(BIO *bio, BIO_METHOD *method)
83280304Sjkim{
84280304Sjkim    bio->method = method;
85280304Sjkim    bio->callback = NULL;
86280304Sjkim    bio->cb_arg = NULL;
87280304Sjkim    bio->init = 0;
88280304Sjkim    bio->shutdown = 1;
89280304Sjkim    bio->flags = 0;
90280304Sjkim    bio->retry_reason = 0;
91280304Sjkim    bio->num = 0;
92280304Sjkim    bio->ptr = NULL;
93280304Sjkim    bio->prev_bio = NULL;
94280304Sjkim    bio->next_bio = NULL;
95280304Sjkim    bio->references = 1;
96280304Sjkim    bio->num_read = 0L;
97280304Sjkim    bio->num_write = 0L;
98280304Sjkim    CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
99280304Sjkim    if (method->create != NULL)
100280304Sjkim        if (!method->create(bio)) {
101280304Sjkim            CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
102280304Sjkim            return (0);
103280304Sjkim        }
104280304Sjkim    return (1);
105280304Sjkim}
10655714Skris
10755714Skrisint BIO_free(BIO *a)
108280304Sjkim{
109280304Sjkim    int i;
11055714Skris
111280304Sjkim    if (a == NULL)
112280304Sjkim        return (0);
11355714Skris
114280304Sjkim    i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO);
11555714Skris#ifdef REF_PRINT
116280304Sjkim    REF_PRINT("BIO", a);
11755714Skris#endif
118280304Sjkim    if (i > 0)
119280304Sjkim        return (1);
12055714Skris#ifdef REF_CHECK
121280304Sjkim    if (i < 0) {
122280304Sjkim        fprintf(stderr, "BIO_free, bad reference count\n");
123280304Sjkim        abort();
124280304Sjkim    }
12555714Skris#endif
126280304Sjkim    if ((a->callback != NULL) &&
127280304Sjkim        ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
128280304Sjkim        return (i);
12955714Skris
130280304Sjkim    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
13155714Skris
132280304Sjkim    if ((a->method != NULL) && (a->method->destroy != NULL))
133280304Sjkim        a->method->destroy(a);
134280304Sjkim    OPENSSL_free(a);
135280304Sjkim    return (1);
136280304Sjkim}
13755714Skris
13868651Skrisvoid BIO_vfree(BIO *a)
139280304Sjkim{
140280304Sjkim    BIO_free(a);
141280304Sjkim}
14268651Skris
143167612Ssimonvoid BIO_clear_flags(BIO *b, int flags)
144280304Sjkim{
145280304Sjkim    b->flags &= ~flags;
146280304Sjkim}
147167612Ssimon
148280304Sjkimint BIO_test_flags(const BIO *b, int flags)
149280304Sjkim{
150280304Sjkim    return (b->flags & flags);
151280304Sjkim}
152167612Ssimon
153280304Sjkimvoid BIO_set_flags(BIO *b, int flags)
154280304Sjkim{
155280304Sjkim    b->flags |= flags;
156280304Sjkim}
157167612Ssimon
158280304Sjkimlong (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *,
159280304Sjkim                                        int, long, long) {
160280304Sjkim    return b->callback;
161280304Sjkim}
162167612Ssimon
163280304Sjkimvoid BIO_set_callback(BIO *b,
164280304Sjkim                      long (*cb) (struct bio_st *, int, const char *, int,
165280304Sjkim                                  long, long))
166280304Sjkim{
167280304Sjkim    b->callback = cb;
168280304Sjkim}
169167612Ssimon
170167612Ssimonvoid BIO_set_callback_arg(BIO *b, char *arg)
171280304Sjkim{
172280304Sjkim    b->cb_arg = arg;
173280304Sjkim}
174167612Ssimon
175280304Sjkimchar *BIO_get_callback_arg(const BIO *b)
176280304Sjkim{
177280304Sjkim    return b->cb_arg;
178280304Sjkim}
179167612Ssimon
180280304Sjkimconst char *BIO_method_name(const BIO *b)
181280304Sjkim{
182280304Sjkim    return b->method->name;
183280304Sjkim}
184167612Ssimon
185167612Ssimonint BIO_method_type(const BIO *b)
186280304Sjkim{
187280304Sjkim    return b->method->type;
188280304Sjkim}
189167612Ssimon
19055714Skrisint BIO_read(BIO *b, void *out, int outl)
191280304Sjkim{
192280304Sjkim    int i;
193280304Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
19455714Skris
195280304Sjkim    if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
196280304Sjkim        BIOerr(BIO_F_BIO_READ, BIO_R_UNSUPPORTED_METHOD);
197280304Sjkim        return (-2);
198280304Sjkim    }
19955714Skris
200280304Sjkim    cb = b->callback;
201280304Sjkim    if ((cb != NULL) &&
202280304Sjkim        ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
203280304Sjkim        return (i);
20455714Skris
205280304Sjkim    if (!b->init) {
206280304Sjkim        BIOerr(BIO_F_BIO_READ, BIO_R_UNINITIALIZED);
207280304Sjkim        return (-2);
208280304Sjkim    }
20955714Skris
210280304Sjkim    i = b->method->bread(b, out, outl);
21155714Skris
212280304Sjkim    if (i > 0)
213280304Sjkim        b->num_read += (unsigned long)i;
21455714Skris
215280304Sjkim    if (cb != NULL)
216280304Sjkim        i = (int)cb(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0L, (long)i);
217280304Sjkim    return (i);
218280304Sjkim}
21955714Skris
22059191Skrisint BIO_write(BIO *b, const void *in, int inl)
221280304Sjkim{
222280304Sjkim    int i;
223280304Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
22455714Skris
225280304Sjkim    if (b == NULL)
226280304Sjkim        return (0);
22755714Skris
228280304Sjkim    cb = b->callback;
229280304Sjkim    if ((b->method == NULL) || (b->method->bwrite == NULL)) {
230280304Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNSUPPORTED_METHOD);
231280304Sjkim        return (-2);
232280304Sjkim    }
23355714Skris
234280304Sjkim    if ((cb != NULL) &&
235280304Sjkim        ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
236280304Sjkim        return (i);
23755714Skris
238280304Sjkim    if (!b->init) {
239280304Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNINITIALIZED);
240280304Sjkim        return (-2);
241280304Sjkim    }
24255714Skris
243280304Sjkim    i = b->method->bwrite(b, in, inl);
24455714Skris
245280304Sjkim    if (i > 0)
246280304Sjkim        b->num_write += (unsigned long)i;
24755714Skris
248280304Sjkim    if (cb != NULL)
249280304Sjkim        i = (int)cb(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0L, (long)i);
250280304Sjkim    return (i);
251280304Sjkim}
25255714Skris
25355714Skrisint BIO_puts(BIO *b, const char *in)
254280304Sjkim{
255280304Sjkim    int i;
256280304Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
25755714Skris
258280304Sjkim    if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
259280304Sjkim        BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
260280304Sjkim        return (-2);
261280304Sjkim    }
26255714Skris
263280304Sjkim    cb = b->callback;
26455714Skris
265280304Sjkim    if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
266280304Sjkim        return (i);
26755714Skris
268280304Sjkim    if (!b->init) {
269280304Sjkim        BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
270280304Sjkim        return (-2);
271280304Sjkim    }
27255714Skris
273280304Sjkim    i = b->method->bputs(b, in);
27455714Skris
275280304Sjkim    if (i > 0)
276280304Sjkim        b->num_write += (unsigned long)i;
27768651Skris
278280304Sjkim    if (cb != NULL)
279280304Sjkim        i = (int)cb(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0L, (long)i);
280280304Sjkim    return (i);
281280304Sjkim}
28255714Skris
28355714Skrisint BIO_gets(BIO *b, char *in, int inl)
284280304Sjkim{
285280304Sjkim    int i;
286280304Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
28755714Skris
288280304Sjkim    if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
289280304Sjkim        BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
290280304Sjkim        return (-2);
291280304Sjkim    }
29255714Skris
293280304Sjkim    cb = b->callback;
29455714Skris
295280304Sjkim    if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
296280304Sjkim        return (i);
29755714Skris
298280304Sjkim    if (!b->init) {
299280304Sjkim        BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
300280304Sjkim        return (-2);
301280304Sjkim    }
30255714Skris
303280304Sjkim    i = b->method->bgets(b, in, inl);
30455714Skris
305280304Sjkim    if (cb != NULL)
306280304Sjkim        i = (int)cb(b, BIO_CB_GETS | BIO_CB_RETURN, in, inl, 0L, (long)i);
307280304Sjkim    return (i);
308280304Sjkim}
30955714Skris
310280304Sjkimint BIO_indent(BIO *b, int indent, int max)
311280304Sjkim{
312280304Sjkim    if (indent < 0)
313280304Sjkim        indent = 0;
314280304Sjkim    if (indent > max)
315280304Sjkim        indent = max;
316280304Sjkim    while (indent--)
317280304Sjkim        if (BIO_puts(b, " ") != 1)
318280304Sjkim            return 0;
319280304Sjkim    return 1;
320280304Sjkim}
321109998Smarkm
32255714Skrislong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
323280304Sjkim{
324280304Sjkim    int i;
32555714Skris
326280304Sjkim    i = iarg;
327280304Sjkim    return (BIO_ctrl(b, cmd, larg, (char *)&i));
328280304Sjkim}
32955714Skris
33055714Skrischar *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
331280304Sjkim{
332280304Sjkim    char *p = NULL;
33355714Skris
334280304Sjkim    if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
335280304Sjkim        return (NULL);
336280304Sjkim    else
337280304Sjkim        return (p);
338280304Sjkim}
33955714Skris
34055714Skrislong BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
341280304Sjkim{
342280304Sjkim    long ret;
343280304Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
34455714Skris
345280304Sjkim    if (b == NULL)
346280304Sjkim        return (0);
34755714Skris
348280304Sjkim    if ((b->method == NULL) || (b->method->ctrl == NULL)) {
349280304Sjkim        BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
350280304Sjkim        return (-2);
351280304Sjkim    }
35255714Skris
353280304Sjkim    cb = b->callback;
35455714Skris
355280304Sjkim    if ((cb != NULL) &&
356280304Sjkim        ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
357280304Sjkim        return (ret);
35855714Skris
359280304Sjkim    ret = b->method->ctrl(b, cmd, larg, parg);
36055714Skris
361280304Sjkim    if (cb != NULL)
362280304Sjkim        ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
363280304Sjkim    return (ret);
364280304Sjkim}
36555714Skris
366280304Sjkimlong BIO_callback_ctrl(BIO *b, int cmd,
367280304Sjkim                       void (*fp) (struct bio_st *, int, const char *, int,
368280304Sjkim                                   long, long))
369280304Sjkim{
370280304Sjkim    long ret;
371280304Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
37259191Skris
373280304Sjkim    if (b == NULL)
374280304Sjkim        return (0);
37559191Skris
376280304Sjkim    if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
377280304Sjkim        BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
378280304Sjkim        return (-2);
379280304Sjkim    }
38059191Skris
381280304Sjkim    cb = b->callback;
38259191Skris
383280304Sjkim    if ((cb != NULL) &&
384280304Sjkim        ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
385280304Sjkim        return (ret);
38659191Skris
387280304Sjkim    ret = b->method->callback_ctrl(b, cmd, fp);
38859191Skris
389280304Sjkim    if (cb != NULL)
390280304Sjkim        ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
391280304Sjkim    return (ret);
392280304Sjkim}
39359191Skris
394280304Sjkim/*
395280304Sjkim * 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
397280304Sjkim * from other programming languages, C macros aren't much of a help anyway.
398280304Sjkim */
39955714Skrissize_t BIO_ctrl_pending(BIO *bio)
400280304Sjkim{
401280304Sjkim    return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
402280304Sjkim}
40355714Skris
40455714Skrissize_t BIO_ctrl_wpending(BIO *bio)
405280304Sjkim{
406280304Sjkim    return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
407280304Sjkim}
40855714Skris
40955714Skris/* put the 'bio' on the end of b's list of operators */
41055714SkrisBIO *BIO_push(BIO *b, BIO *bio)
411280304Sjkim{
412280304Sjkim    BIO *lb;
41355714Skris
414280304Sjkim    if (b == NULL)
415280304Sjkim        return (bio);
416280304Sjkim    lb = b;
417280304Sjkim    while (lb->next_bio != NULL)
418280304Sjkim        lb = lb->next_bio;
419280304Sjkim    lb->next_bio = bio;
420280304Sjkim    if (bio != NULL)
421280304Sjkim        bio->prev_bio = lb;
422280304Sjkim    /* called to do internal processing */
423280304Sjkim    BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
424280304Sjkim    return (b);
425280304Sjkim}
42655714Skris
42755714Skris/* Remove the first and return the rest */
42855714SkrisBIO *BIO_pop(BIO *b)
429280304Sjkim{
430280304Sjkim    BIO *ret;
43155714Skris
432280304Sjkim    if (b == NULL)
433280304Sjkim        return (NULL);
434280304Sjkim    ret = b->next_bio;
43555714Skris
436280304Sjkim    BIO_ctrl(b, BIO_CTRL_POP, 0, b);
437111147Snectar
438280304Sjkim    if (b->prev_bio != NULL)
439280304Sjkim        b->prev_bio->next_bio = b->next_bio;
440280304Sjkim    if (b->next_bio != NULL)
441280304Sjkim        b->next_bio->prev_bio = b->prev_bio;
44255714Skris
443280304Sjkim    b->next_bio = NULL;
444280304Sjkim    b->prev_bio = NULL;
445280304Sjkim    return (ret);
446280304Sjkim}
44755714Skris
44855714SkrisBIO *BIO_get_retry_BIO(BIO *bio, int *reason)
449280304Sjkim{
450280304Sjkim    BIO *b, *last;
45155714Skris
452280304Sjkim    b = last = bio;
453280304Sjkim    for (;;) {
454280304Sjkim        if (!BIO_should_retry(b))
455280304Sjkim            break;
456280304Sjkim        last = b;
457280304Sjkim        b = b->next_bio;
458280304Sjkim        if (b == NULL)
459280304Sjkim            break;
460280304Sjkim    }
461280304Sjkim    if (reason != NULL)
462280304Sjkim        *reason = last->retry_reason;
463280304Sjkim    return (last);
464280304Sjkim}
46555714Skris
46655714Skrisint BIO_get_retry_reason(BIO *bio)
467280304Sjkim{
468280304Sjkim    return (bio->retry_reason);
469280304Sjkim}
47055714Skris
47155714SkrisBIO *BIO_find_type(BIO *bio, int type)
472280304Sjkim{
473280304Sjkim    int mt, mask;
47455714Skris
475280304Sjkim    if (!bio)
476280304Sjkim        return NULL;
477280304Sjkim    mask = type & 0xff;
478280304Sjkim    do {
479280304Sjkim        if (bio->method != NULL) {
480280304Sjkim            mt = bio->method->type;
48155714Skris
482280304Sjkim            if (!mask) {
483280304Sjkim                if (mt & type)
484280304Sjkim                    return (bio);
485280304Sjkim            } else if (mt == type)
486280304Sjkim                return (bio);
487280304Sjkim        }
488280304Sjkim        bio = bio->next_bio;
489280304Sjkim    } while (bio != NULL);
490280304Sjkim    return (NULL);
491280304Sjkim}
49255714Skris
49368651SkrisBIO *BIO_next(BIO *b)
494280304Sjkim{
495280304Sjkim    if (!b)
496280304Sjkim        return NULL;
497280304Sjkim    return b->next_bio;
498280304Sjkim}
49968651Skris
50055714Skrisvoid BIO_free_all(BIO *bio)
501280304Sjkim{
502280304Sjkim    BIO *b;
503280304Sjkim    int ref;
50455714Skris
505280304Sjkim    while (bio != NULL) {
506280304Sjkim        b = bio;
507280304Sjkim        ref = b->references;
508280304Sjkim        bio = bio->next_bio;
509280304Sjkim        BIO_free(b);
510280304Sjkim        /* Since ref count > 1, don't free anyone else. */
511280304Sjkim        if (ref > 1)
512280304Sjkim            break;
513280304Sjkim    }
514280304Sjkim}
51555714Skris
51655714SkrisBIO *BIO_dup_chain(BIO *in)
517280304Sjkim{
518280304Sjkim    BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
51955714Skris
520280304Sjkim    for (bio = in; bio != NULL; bio = bio->next_bio) {
521280304Sjkim        if ((new_bio = BIO_new(bio->method)) == NULL)
522280304Sjkim            goto err;
523280304Sjkim        new_bio->callback = bio->callback;
524280304Sjkim        new_bio->cb_arg = bio->cb_arg;
525280304Sjkim        new_bio->init = bio->init;
526280304Sjkim        new_bio->shutdown = bio->shutdown;
527280304Sjkim        new_bio->flags = bio->flags;
52855714Skris
529280304Sjkim        /* This will let SSL_s_sock() work with stdin/stdout */
530280304Sjkim        new_bio->num = bio->num;
53155714Skris
532280304Sjkim        if (!BIO_dup_state(bio, (char *)new_bio)) {
533280304Sjkim            BIO_free(new_bio);
534280304Sjkim            goto err;
535280304Sjkim        }
53655714Skris
537280304Sjkim        /* copy app data */
538280304Sjkim        if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
539284285Sjkim                                &bio->ex_data)) {
540284285Sjkim            BIO_free(new_bio);
541280304Sjkim            goto err;
542284285Sjkim        }
54355714Skris
544280304Sjkim        if (ret == NULL) {
545280304Sjkim            eoc = new_bio;
546280304Sjkim            ret = eoc;
547280304Sjkim        } else {
548280304Sjkim            BIO_push(eoc, new_bio);
549280304Sjkim            eoc = new_bio;
550280304Sjkim        }
551280304Sjkim    }
552280304Sjkim    return (ret);
553280304Sjkim err:
554284285Sjkim    BIO_free_all(ret);
555284285Sjkim
556280304Sjkim    return (NULL);
557280304Sjkim}
55855714Skris
55955714Skrisvoid BIO_copy_next_retry(BIO *b)
560280304Sjkim{
561280304Sjkim    BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
562280304Sjkim    b->retry_reason = b->next_bio->retry_reason;
563280304Sjkim}
56455714Skris
56559191Skrisint BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
566280304Sjkim                         CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
567280304Sjkim{
568280304Sjkim    return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
569280304Sjkim                                   new_func, dup_func, free_func);
570280304Sjkim}
57155714Skris
57259191Skrisint BIO_set_ex_data(BIO *bio, int idx, void *data)
573280304Sjkim{
574280304Sjkim    return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
575280304Sjkim}
57655714Skris
57759191Skrisvoid *BIO_get_ex_data(BIO *bio, int idx)
578280304Sjkim{
579280304Sjkim    return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
580280304Sjkim}
58155714Skris
58259191Skrisunsigned long BIO_number_read(BIO *bio)
58359191Skris{
584280304Sjkim    if (bio)
585280304Sjkim        return bio->num_read;
586280304Sjkim    return 0;
58759191Skris}
58859191Skris
58959191Skrisunsigned long BIO_number_written(BIO *bio)
59059191Skris{
591280304Sjkim    if (bio)
592280304Sjkim        return bio->num_write;
593280304Sjkim    return 0;
59459191Skris}
59568651Skris
59668651SkrisIMPLEMENT_STACK_OF(BIO)
597