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.
8280297Sjkim *
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).
15280297Sjkim *
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.
22280297Sjkim *
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 :-).
37280297Sjkim * 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)"
40280297Sjkim *
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.
52280297Sjkim *
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)
67280297Sjkim{
68280297Sjkim    BIO *ret = NULL;
6955714Skris
70280297Sjkim    ret = (BIO *)OPENSSL_malloc(sizeof(BIO));
71280297Sjkim    if (ret == NULL) {
72280297Sjkim        BIOerr(BIO_F_BIO_NEW, ERR_R_MALLOC_FAILURE);
73280297Sjkim        return (NULL);
74280297Sjkim    }
75280297Sjkim    if (!BIO_set(ret, method)) {
76280297Sjkim        OPENSSL_free(ret);
77280297Sjkim        ret = NULL;
78280297Sjkim    }
79280297Sjkim    return (ret);
80280297Sjkim}
8155714Skris
8255714Skrisint BIO_set(BIO *bio, BIO_METHOD *method)
83280297Sjkim{
84280297Sjkim    bio->method = method;
85280297Sjkim    bio->callback = NULL;
86280297Sjkim    bio->cb_arg = NULL;
87280297Sjkim    bio->init = 0;
88280297Sjkim    bio->shutdown = 1;
89280297Sjkim    bio->flags = 0;
90280297Sjkim    bio->retry_reason = 0;
91280297Sjkim    bio->num = 0;
92280297Sjkim    bio->ptr = NULL;
93280297Sjkim    bio->prev_bio = NULL;
94280297Sjkim    bio->next_bio = NULL;
95280297Sjkim    bio->references = 1;
96280297Sjkim    bio->num_read = 0L;
97280297Sjkim    bio->num_write = 0L;
98280297Sjkim    CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
99280297Sjkim    if (method->create != NULL)
100280297Sjkim        if (!method->create(bio)) {
101280297Sjkim            CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
102280297Sjkim            return (0);
103280297Sjkim        }
104280297Sjkim    return (1);
105280297Sjkim}
10655714Skris
10755714Skrisint BIO_free(BIO *a)
108280297Sjkim{
109280297Sjkim    int i;
11055714Skris
111280297Sjkim    if (a == NULL)
112280297Sjkim        return (0);
11355714Skris
114280297Sjkim    i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO);
11555714Skris#ifdef REF_PRINT
116280297Sjkim    REF_PRINT("BIO", a);
11755714Skris#endif
118280297Sjkim    if (i > 0)
119280297Sjkim        return (1);
12055714Skris#ifdef REF_CHECK
121280297Sjkim    if (i < 0) {
122280297Sjkim        fprintf(stderr, "BIO_free, bad reference count\n");
123280297Sjkim        abort();
124280297Sjkim    }
12555714Skris#endif
126280297Sjkim    if ((a->callback != NULL) &&
127280297Sjkim        ((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
128280297Sjkim        return (i);
12955714Skris
130280297Sjkim    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
13155714Skris
132280297Sjkim    if ((a->method != NULL) && (a->method->destroy != NULL))
133280297Sjkim        a->method->destroy(a);
134280297Sjkim    OPENSSL_free(a);
135280297Sjkim    return (1);
136280297Sjkim}
13755714Skris
13868651Skrisvoid BIO_vfree(BIO *a)
139280297Sjkim{
140280297Sjkim    BIO_free(a);
141280297Sjkim}
14268651Skris
143167612Ssimonvoid BIO_clear_flags(BIO *b, int flags)
144280297Sjkim{
145280297Sjkim    b->flags &= ~flags;
146280297Sjkim}
147167612Ssimon
148280297Sjkimint BIO_test_flags(const BIO *b, int flags)
149280297Sjkim{
150280297Sjkim    return (b->flags & flags);
151280297Sjkim}
152167612Ssimon
153280297Sjkimvoid BIO_set_flags(BIO *b, int flags)
154280297Sjkim{
155280297Sjkim    b->flags |= flags;
156280297Sjkim}
157167612Ssimon
158280297Sjkimlong (*BIO_get_callback(const BIO *b)) (struct bio_st *, int, const char *,
159280297Sjkim                                        int, long, long) {
160280297Sjkim    return b->callback;
161280297Sjkim}
162167612Ssimon
163280297Sjkimvoid BIO_set_callback(BIO *b,
164280297Sjkim                      long (*cb) (struct bio_st *, int, const char *, int,
165280297Sjkim                                  long, long))
166280297Sjkim{
167280297Sjkim    b->callback = cb;
168280297Sjkim}
169167612Ssimon
170167612Ssimonvoid BIO_set_callback_arg(BIO *b, char *arg)
171280297Sjkim{
172280297Sjkim    b->cb_arg = arg;
173280297Sjkim}
174167612Ssimon
175280297Sjkimchar *BIO_get_callback_arg(const BIO *b)
176280297Sjkim{
177280297Sjkim    return b->cb_arg;
178280297Sjkim}
179167612Ssimon
180280297Sjkimconst char *BIO_method_name(const BIO *b)
181280297Sjkim{
182280297Sjkim    return b->method->name;
183280297Sjkim}
184167612Ssimon
185167612Ssimonint BIO_method_type(const BIO *b)
186280297Sjkim{
187280297Sjkim    return b->method->type;
188280297Sjkim}
189167612Ssimon
19055714Skrisint BIO_read(BIO *b, void *out, int outl)
191280297Sjkim{
192280297Sjkim    int i;
193280297Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
19455714Skris
195280297Sjkim    if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) {
196280297Sjkim        BIOerr(BIO_F_BIO_READ, BIO_R_UNSUPPORTED_METHOD);
197280297Sjkim        return (-2);
198280297Sjkim    }
19955714Skris
200280297Sjkim    cb = b->callback;
201280297Sjkim    if ((cb != NULL) &&
202280297Sjkim        ((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
203280297Sjkim        return (i);
20455714Skris
205280297Sjkim    if (!b->init) {
206280297Sjkim        BIOerr(BIO_F_BIO_READ, BIO_R_UNINITIALIZED);
207280297Sjkim        return (-2);
208280297Sjkim    }
20955714Skris
210280297Sjkim    i = b->method->bread(b, out, outl);
21155714Skris
212280297Sjkim    if (i > 0)
213280297Sjkim        b->num_read += (unsigned long)i;
21455714Skris
215280297Sjkim    if (cb != NULL)
216280297Sjkim        i = (int)cb(b, BIO_CB_READ | BIO_CB_RETURN, out, outl, 0L, (long)i);
217280297Sjkim    return (i);
218280297Sjkim}
21955714Skris
22059191Skrisint BIO_write(BIO *b, const void *in, int inl)
221280297Sjkim{
222280297Sjkim    int i;
223280297Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
22455714Skris
225280297Sjkim    if (b == NULL)
226280297Sjkim        return (0);
22755714Skris
228280297Sjkim    cb = b->callback;
229280297Sjkim    if ((b->method == NULL) || (b->method->bwrite == NULL)) {
230280297Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNSUPPORTED_METHOD);
231280297Sjkim        return (-2);
232280297Sjkim    }
23355714Skris
234280297Sjkim    if ((cb != NULL) &&
235280297Sjkim        ((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
236280297Sjkim        return (i);
23755714Skris
238280297Sjkim    if (!b->init) {
239280297Sjkim        BIOerr(BIO_F_BIO_WRITE, BIO_R_UNINITIALIZED);
240280297Sjkim        return (-2);
241280297Sjkim    }
24255714Skris
243280297Sjkim    i = b->method->bwrite(b, in, inl);
24455714Skris
245280297Sjkim    if (i > 0)
246280297Sjkim        b->num_write += (unsigned long)i;
24755714Skris
248280297Sjkim    if (cb != NULL)
249280297Sjkim        i = (int)cb(b, BIO_CB_WRITE | BIO_CB_RETURN, in, inl, 0L, (long)i);
250280297Sjkim    return (i);
251280297Sjkim}
25255714Skris
25355714Skrisint BIO_puts(BIO *b, const char *in)
254280297Sjkim{
255280297Sjkim    int i;
256280297Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
25755714Skris
258280297Sjkim    if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
259280297Sjkim        BIOerr(BIO_F_BIO_PUTS, BIO_R_UNSUPPORTED_METHOD);
260280297Sjkim        return (-2);
261280297Sjkim    }
26255714Skris
263280297Sjkim    cb = b->callback;
26455714Skris
265280297Sjkim    if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
266280297Sjkim        return (i);
26755714Skris
268280297Sjkim    if (!b->init) {
269280297Sjkim        BIOerr(BIO_F_BIO_PUTS, BIO_R_UNINITIALIZED);
270280297Sjkim        return (-2);
271280297Sjkim    }
27255714Skris
273280297Sjkim    i = b->method->bputs(b, in);
27455714Skris
275280297Sjkim    if (i > 0)
276280297Sjkim        b->num_write += (unsigned long)i;
27768651Skris
278280297Sjkim    if (cb != NULL)
279280297Sjkim        i = (int)cb(b, BIO_CB_PUTS | BIO_CB_RETURN, in, 0, 0L, (long)i);
280280297Sjkim    return (i);
281280297Sjkim}
28255714Skris
28355714Skrisint BIO_gets(BIO *b, char *in, int inl)
284280297Sjkim{
285280297Sjkim    int i;
286280297Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
28755714Skris
288280297Sjkim    if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
289280297Sjkim        BIOerr(BIO_F_BIO_GETS, BIO_R_UNSUPPORTED_METHOD);
290280297Sjkim        return (-2);
291280297Sjkim    }
29255714Skris
293280297Sjkim    cb = b->callback;
29455714Skris
295280297Sjkim    if ((cb != NULL) && ((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
296280297Sjkim        return (i);
29755714Skris
298280297Sjkim    if (!b->init) {
299280297Sjkim        BIOerr(BIO_F_BIO_GETS, BIO_R_UNINITIALIZED);
300280297Sjkim        return (-2);
301280297Sjkim    }
30255714Skris
303280297Sjkim    i = b->method->bgets(b, in, inl);
30455714Skris
305280297Sjkim    if (cb != NULL)
306280297Sjkim        i = (int)cb(b, BIO_CB_GETS | BIO_CB_RETURN, in, inl, 0L, (long)i);
307280297Sjkim    return (i);
308280297Sjkim}
30955714Skris
310280297Sjkimint BIO_indent(BIO *b, int indent, int max)
311280297Sjkim{
312280297Sjkim    if (indent < 0)
313280297Sjkim        indent = 0;
314280297Sjkim    if (indent > max)
315280297Sjkim        indent = max;
316280297Sjkim    while (indent--)
317280297Sjkim        if (BIO_puts(b, " ") != 1)
318280297Sjkim            return 0;
319280297Sjkim    return 1;
320280297Sjkim}
321109998Smarkm
32255714Skrislong BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
323280297Sjkim{
324280297Sjkim    int i;
32555714Skris
326280297Sjkim    i = iarg;
327280297Sjkim    return (BIO_ctrl(b, cmd, larg, (char *)&i));
328280297Sjkim}
32955714Skris
33055714Skrischar *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
331280297Sjkim{
332280297Sjkim    char *p = NULL;
33355714Skris
334280297Sjkim    if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
335280297Sjkim        return (NULL);
336280297Sjkim    else
337280297Sjkim        return (p);
338280297Sjkim}
33955714Skris
34055714Skrislong BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
341280297Sjkim{
342280297Sjkim    long ret;
343280297Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
34455714Skris
345280297Sjkim    if (b == NULL)
346280297Sjkim        return (0);
34755714Skris
348280297Sjkim    if ((b->method == NULL) || (b->method->ctrl == NULL)) {
349280297Sjkim        BIOerr(BIO_F_BIO_CTRL, BIO_R_UNSUPPORTED_METHOD);
350280297Sjkim        return (-2);
351280297Sjkim    }
35255714Skris
353280297Sjkim    cb = b->callback;
35455714Skris
355280297Sjkim    if ((cb != NULL) &&
356280297Sjkim        ((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
357280297Sjkim        return (ret);
35855714Skris
359280297Sjkim    ret = b->method->ctrl(b, cmd, larg, parg);
36055714Skris
361280297Sjkim    if (cb != NULL)
362280297Sjkim        ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
363280297Sjkim    return (ret);
364280297Sjkim}
36555714Skris
366280297Sjkimlong BIO_callback_ctrl(BIO *b, int cmd,
367280297Sjkim                       void (*fp) (struct bio_st *, int, const char *, int,
368280297Sjkim                                   long, long))
369280297Sjkim{
370280297Sjkim    long ret;
371280297Sjkim    long (*cb) (BIO *, int, const char *, int, long, long);
37259191Skris
373280297Sjkim    if (b == NULL)
374280297Sjkim        return (0);
37559191Skris
376280297Sjkim    if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
377280297Sjkim        BIOerr(BIO_F_BIO_CALLBACK_CTRL, BIO_R_UNSUPPORTED_METHOD);
378280297Sjkim        return (-2);
379280297Sjkim    }
38059191Skris
381280297Sjkim    cb = b->callback;
38259191Skris
383280297Sjkim    if ((cb != NULL) &&
384280297Sjkim        ((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
385280297Sjkim        return (ret);
38659191Skris
387280297Sjkim    ret = b->method->callback_ctrl(b, cmd, fp);
38859191Skris
389280297Sjkim    if (cb != NULL)
390280297Sjkim        ret = cb(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
391280297Sjkim    return (ret);
392280297Sjkim}
39359191Skris
394280297Sjkim/*
395280297Sjkim * 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
397280297Sjkim * from other programming languages, C macros aren't much of a help anyway.
398280297Sjkim */
39955714Skrissize_t BIO_ctrl_pending(BIO *bio)
400280297Sjkim{
401280297Sjkim    return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
402280297Sjkim}
40355714Skris
40455714Skrissize_t BIO_ctrl_wpending(BIO *bio)
405280297Sjkim{
406280297Sjkim    return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
407280297Sjkim}
40855714Skris
40955714Skris/* put the 'bio' on the end of b's list of operators */
41055714SkrisBIO *BIO_push(BIO *b, BIO *bio)
411280297Sjkim{
412280297Sjkim    BIO *lb;
41355714Skris
414280297Sjkim    if (b == NULL)
415280297Sjkim        return (bio);
416280297Sjkim    lb = b;
417280297Sjkim    while (lb->next_bio != NULL)
418280297Sjkim        lb = lb->next_bio;
419280297Sjkim    lb->next_bio = bio;
420280297Sjkim    if (bio != NULL)
421280297Sjkim        bio->prev_bio = lb;
422280297Sjkim    /* called to do internal processing */
423280297Sjkim    BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
424280297Sjkim    return (b);
425280297Sjkim}
42655714Skris
42755714Skris/* Remove the first and return the rest */
42855714SkrisBIO *BIO_pop(BIO *b)
429280297Sjkim{
430280297Sjkim    BIO *ret;
43155714Skris
432280297Sjkim    if (b == NULL)
433280297Sjkim        return (NULL);
434280297Sjkim    ret = b->next_bio;
43555714Skris
436280297Sjkim    BIO_ctrl(b, BIO_CTRL_POP, 0, b);
437111147Snectar
438280297Sjkim    if (b->prev_bio != NULL)
439280297Sjkim        b->prev_bio->next_bio = b->next_bio;
440280297Sjkim    if (b->next_bio != NULL)
441280297Sjkim        b->next_bio->prev_bio = b->prev_bio;
44255714Skris
443280297Sjkim    b->next_bio = NULL;
444280297Sjkim    b->prev_bio = NULL;
445280297Sjkim    return (ret);
446280297Sjkim}
44755714Skris
44855714SkrisBIO *BIO_get_retry_BIO(BIO *bio, int *reason)
449280297Sjkim{
450280297Sjkim    BIO *b, *last;
45155714Skris
452280297Sjkim    b = last = bio;
453280297Sjkim    for (;;) {
454280297Sjkim        if (!BIO_should_retry(b))
455280297Sjkim            break;
456280297Sjkim        last = b;
457280297Sjkim        b = b->next_bio;
458280297Sjkim        if (b == NULL)
459280297Sjkim            break;
460280297Sjkim    }
461280297Sjkim    if (reason != NULL)
462280297Sjkim        *reason = last->retry_reason;
463280297Sjkim    return (last);
464280297Sjkim}
46555714Skris
46655714Skrisint BIO_get_retry_reason(BIO *bio)
467280297Sjkim{
468280297Sjkim    return (bio->retry_reason);
469280297Sjkim}
47055714Skris
47155714SkrisBIO *BIO_find_type(BIO *bio, int type)
472280297Sjkim{
473280297Sjkim    int mt, mask;
47455714Skris
475280297Sjkim    if (!bio)
476280297Sjkim        return NULL;
477280297Sjkim    mask = type & 0xff;
478280297Sjkim    do {
479280297Sjkim        if (bio->method != NULL) {
480280297Sjkim            mt = bio->method->type;
48155714Skris
482280297Sjkim            if (!mask) {
483280297Sjkim                if (mt & type)
484280297Sjkim                    return (bio);
485280297Sjkim            } else if (mt == type)
486280297Sjkim                return (bio);
487280297Sjkim        }
488280297Sjkim        bio = bio->next_bio;
489280297Sjkim    } while (bio != NULL);
490280297Sjkim    return (NULL);
491280297Sjkim}
49255714Skris
49368651SkrisBIO *BIO_next(BIO *b)
494280297Sjkim{
495280297Sjkim    if (!b)
496280297Sjkim        return NULL;
497280297Sjkim    return b->next_bio;
498280297Sjkim}
49968651Skris
50055714Skrisvoid BIO_free_all(BIO *bio)
501280297Sjkim{
502280297Sjkim    BIO *b;
503280297Sjkim    int ref;
50455714Skris
505280297Sjkim    while (bio != NULL) {
506280297Sjkim        b = bio;
507280297Sjkim        ref = b->references;
508280297Sjkim        bio = bio->next_bio;
509280297Sjkim        BIO_free(b);
510280297Sjkim        /* Since ref count > 1, don't free anyone else. */
511280297Sjkim        if (ref > 1)
512280297Sjkim            break;
513280297Sjkim    }
514280297Sjkim}
51555714Skris
51655714SkrisBIO *BIO_dup_chain(BIO *in)
517280297Sjkim{
518280297Sjkim    BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
51955714Skris
520280297Sjkim    for (bio = in; bio != NULL; bio = bio->next_bio) {
521280297Sjkim        if ((new_bio = BIO_new(bio->method)) == NULL)
522280297Sjkim            goto err;
523280297Sjkim        new_bio->callback = bio->callback;
524280297Sjkim        new_bio->cb_arg = bio->cb_arg;
525280297Sjkim        new_bio->init = bio->init;
526280297Sjkim        new_bio->shutdown = bio->shutdown;
527280297Sjkim        new_bio->flags = bio->flags;
52855714Skris
529280297Sjkim        /* This will let SSL_s_sock() work with stdin/stdout */
530280297Sjkim        new_bio->num = bio->num;
53155714Skris
532280297Sjkim        if (!BIO_dup_state(bio, (char *)new_bio)) {
533280297Sjkim            BIO_free(new_bio);
534280297Sjkim            goto err;
535280297Sjkim        }
53655714Skris
537280297Sjkim        /* copy app data */
538280297Sjkim        if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data,
539284283Sjkim                                &bio->ex_data)) {
540284283Sjkim            BIO_free(new_bio);
541280297Sjkim            goto err;
542284283Sjkim        }
54355714Skris
544280297Sjkim        if (ret == NULL) {
545280297Sjkim            eoc = new_bio;
546280297Sjkim            ret = eoc;
547280297Sjkim        } else {
548280297Sjkim            BIO_push(eoc, new_bio);
549280297Sjkim            eoc = new_bio;
550280297Sjkim        }
551280297Sjkim    }
552280297Sjkim    return (ret);
553280297Sjkim err:
554284283Sjkim    BIO_free_all(ret);
555284283Sjkim
556280297Sjkim    return (NULL);
557280297Sjkim}
55855714Skris
55955714Skrisvoid BIO_copy_next_retry(BIO *b)
560280297Sjkim{
561280297Sjkim    BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
562280297Sjkim    b->retry_reason = b->next_bio->retry_reason;
563280297Sjkim}
56455714Skris
56559191Skrisint BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
566280297Sjkim                         CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
567280297Sjkim{
568280297Sjkim    return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
569280297Sjkim                                   new_func, dup_func, free_func);
570280297Sjkim}
57155714Skris
57259191Skrisint BIO_set_ex_data(BIO *bio, int idx, void *data)
573280297Sjkim{
574280297Sjkim    return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
575280297Sjkim}
57655714Skris
57759191Skrisvoid *BIO_get_ex_data(BIO *bio, int idx)
578280297Sjkim{
579280297Sjkim    return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
580280297Sjkim}
58155714Skris
58259191Skrisunsigned long BIO_number_read(BIO *bio)
58359191Skris{
584280297Sjkim    if (bio)
585280297Sjkim        return bio->num_read;
586280297Sjkim    return 0;
58759191Skris}
58859191Skris
58959191Skrisunsigned long BIO_number_written(BIO *bio)
59059191Skris{
591280297Sjkim    if (bio)
592280297Sjkim        return bio->num_write;
593280297Sjkim    return 0;
59459191Skris}
59568651Skris
59668651SkrisIMPLEMENT_STACK_OF(BIO)
597