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