| OLD | NEW |
| (Empty) |
| 1 /* crypto/bio/bio_lib.c */ | |
| 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | |
| 3 * All rights reserved. | |
| 4 * | |
| 5 * This package is an SSL implementation written | |
| 6 * by Eric Young (eay@cryptsoft.com). | |
| 7 * The implementation was written so as to conform with Netscapes SSL. | |
| 8 * | |
| 9 * This library is free for commercial and non-commercial use as long as | |
| 10 * the following conditions are aheared to. The following conditions | |
| 11 * apply to all code found in this distribution, be it the RC4, RSA, | |
| 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
| 13 * included with this distribution is covered by the same copyright terms | |
| 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
| 15 * | |
| 16 * Copyright remains Eric Young's, and as such any Copyright notices in | |
| 17 * the code are not to be removed. | |
| 18 * If this package is used in a product, Eric Young should be given attribution | |
| 19 * as the author of the parts of the library used. | |
| 20 * This can be in the form of a textual message at program startup or | |
| 21 * in documentation (online or textual) provided with the package. | |
| 22 * | |
| 23 * Redistribution and use in source and binary forms, with or without | |
| 24 * modification, are permitted provided that the following conditions | |
| 25 * are met: | |
| 26 * 1. Redistributions of source code must retain the copyright | |
| 27 * notice, this list of conditions and the following disclaimer. | |
| 28 * 2. Redistributions in binary form must reproduce the above copyright | |
| 29 * notice, this list of conditions and the following disclaimer in the | |
| 30 * documentation and/or other materials provided with the distribution. | |
| 31 * 3. All advertising materials mentioning features or use of this software | |
| 32 * must display the following acknowledgement: | |
| 33 * "This product includes cryptographic software written by | |
| 34 * Eric Young (eay@cryptsoft.com)" | |
| 35 * The word 'cryptographic' can be left out if the rouines from the library | |
| 36 * being used are not cryptographic related :-). | |
| 37 * 4. If you include any Windows specific code (or a derivative thereof) from | |
| 38 * the apps directory (application code) you must include an acknowledgement: | |
| 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
| 40 * | |
| 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | |
| 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
| 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 51 * SUCH DAMAGE. | |
| 52 * | |
| 53 * The licence and distribution terms for any publically available version or | |
| 54 * derivative of this code cannot be changed. i.e. this code cannot simply be | |
| 55 * copied and put under another distribution licence | |
| 56 * [including the GNU Public Licence.] | |
| 57 */ | |
| 58 | |
| 59 #include <stdio.h> | |
| 60 #include <errno.h> | |
| 61 #include <openssl/crypto.h> | |
| 62 #include "cryptlib.h" | |
| 63 #include <openssl/bio.h> | |
| 64 #include <openssl/stack.h> | |
| 65 | |
| 66 BIO *BIO_new(BIO_METHOD *method) | |
| 67 { | |
| 68 BIO *ret=NULL; | |
| 69 | |
| 70 ret=(BIO *)OPENSSL_malloc(sizeof(BIO)); | |
| 71 if (ret == NULL) | |
| 72 { | |
| 73 BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE); | |
| 74 return(NULL); | |
| 75 } | |
| 76 if (!BIO_set(ret,method)) | |
| 77 { | |
| 78 OPENSSL_free(ret); | |
| 79 ret=NULL; | |
| 80 } | |
| 81 return(ret); | |
| 82 } | |
| 83 | |
| 84 int BIO_set(BIO *bio, BIO_METHOD *method) | |
| 85 { | |
| 86 bio->method=method; | |
| 87 bio->callback=NULL; | |
| 88 bio->cb_arg=NULL; | |
| 89 bio->init=0; | |
| 90 bio->shutdown=1; | |
| 91 bio->flags=0; | |
| 92 bio->retry_reason=0; | |
| 93 bio->num=0; | |
| 94 bio->ptr=NULL; | |
| 95 bio->prev_bio=NULL; | |
| 96 bio->next_bio=NULL; | |
| 97 bio->references=1; | |
| 98 bio->num_read=0L; | |
| 99 bio->num_write=0L; | |
| 100 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data); | |
| 101 if (method->create != NULL) | |
| 102 if (!method->create(bio)) | |
| 103 { | |
| 104 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio, | |
| 105 &bio->ex_data); | |
| 106 return(0); | |
| 107 } | |
| 108 return(1); | |
| 109 } | |
| 110 | |
| 111 int BIO_free(BIO *a) | |
| 112 { | |
| 113 int i; | |
| 114 | |
| 115 if (a == NULL) return(0); | |
| 116 | |
| 117 i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO); | |
| 118 #ifdef REF_PRINT | |
| 119 REF_PRINT("BIO",a); | |
| 120 #endif | |
| 121 if (i > 0) return(1); | |
| 122 #ifdef REF_CHECK | |
| 123 if (i < 0) | |
| 124 { | |
| 125 fprintf(stderr,"BIO_free, bad reference count\n"); | |
| 126 abort(); | |
| 127 } | |
| 128 #endif | |
| 129 if ((a->callback != NULL) && | |
| 130 ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0)) | |
| 131 return(i); | |
| 132 | |
| 133 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data); | |
| 134 | |
| 135 if ((a->method == NULL) || (a->method->destroy == NULL)) return(1); | |
| 136 a->method->destroy(a); | |
| 137 OPENSSL_free(a); | |
| 138 return(1); | |
| 139 } | |
| 140 | |
| 141 void BIO_vfree(BIO *a) | |
| 142 { BIO_free(a); } | |
| 143 | |
| 144 void BIO_clear_flags(BIO *b, int flags) | |
| 145 { | |
| 146 b->flags &= ~flags; | |
| 147 } | |
| 148 | |
| 149 int BIO_test_flags(const BIO *b, int flags) | |
| 150 { | |
| 151 return (b->flags & flags); | |
| 152 } | |
| 153 | |
| 154 void BIO_set_flags(BIO *b, int flags) | |
| 155 { | |
| 156 b->flags |= flags; | |
| 157 } | |
| 158 | |
| 159 long (*BIO_get_callback(const BIO *b))(struct bio_st *,int,const char *,int, lon
g,long) | |
| 160 { | |
| 161 return b->callback; | |
| 162 } | |
| 163 | |
| 164 void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *,int,const char *,int, l
ong,long)) | |
| 165 { | |
| 166 b->callback = cb; | |
| 167 } | |
| 168 | |
| 169 void BIO_set_callback_arg(BIO *b, char *arg) | |
| 170 { | |
| 171 b->cb_arg = arg; | |
| 172 } | |
| 173 | |
| 174 char * BIO_get_callback_arg(const BIO *b) | |
| 175 { | |
| 176 return b->cb_arg; | |
| 177 } | |
| 178 | |
| 179 const char * BIO_method_name(const BIO *b) | |
| 180 { | |
| 181 return b->method->name; | |
| 182 } | |
| 183 | |
| 184 int BIO_method_type(const BIO *b) | |
| 185 { | |
| 186 return b->method->type; | |
| 187 } | |
| 188 | |
| 189 | |
| 190 int BIO_read(BIO *b, void *out, int outl) | |
| 191 { | |
| 192 int i; | |
| 193 long (*cb)(BIO *,int,const char *,int,long,long); | |
| 194 | |
| 195 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) | |
| 196 { | |
| 197 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD); | |
| 198 return(-2); | |
| 199 } | |
| 200 | |
| 201 cb=b->callback; | |
| 202 if ((cb != NULL) && | |
| 203 ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0)) | |
| 204 return(i); | |
| 205 | |
| 206 if (!b->init) | |
| 207 { | |
| 208 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED); | |
| 209 return(-2); | |
| 210 } | |
| 211 | |
| 212 i=b->method->bread(b,out,outl); | |
| 213 | |
| 214 if (i > 0) b->num_read+=(unsigned long)i; | |
| 215 | |
| 216 if (cb != NULL) | |
| 217 i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl, | |
| 218 0L,(long)i); | |
| 219 return(i); | |
| 220 } | |
| 221 | |
| 222 int BIO_write(BIO *b, const void *in, int inl) | |
| 223 { | |
| 224 int i; | |
| 225 long (*cb)(BIO *,int,const char *,int,long,long); | |
| 226 | |
| 227 if (b == NULL) | |
| 228 return(0); | |
| 229 | |
| 230 cb=b->callback; | |
| 231 if ((b->method == NULL) || (b->method->bwrite == NULL)) | |
| 232 { | |
| 233 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD); | |
| 234 return(-2); | |
| 235 } | |
| 236 | |
| 237 if ((cb != NULL) && | |
| 238 ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0)) | |
| 239 return(i); | |
| 240 | |
| 241 if (!b->init) | |
| 242 { | |
| 243 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED); | |
| 244 return(-2); | |
| 245 } | |
| 246 | |
| 247 i=b->method->bwrite(b,in,inl); | |
| 248 | |
| 249 if (i > 0) b->num_write+=(unsigned long)i; | |
| 250 | |
| 251 if (cb != NULL) | |
| 252 i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl, | |
| 253 0L,(long)i); | |
| 254 return(i); | |
| 255 } | |
| 256 | |
| 257 int BIO_puts(BIO *b, const char *in) | |
| 258 { | |
| 259 int i; | |
| 260 long (*cb)(BIO *,int,const char *,int,long,long); | |
| 261 | |
| 262 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) | |
| 263 { | |
| 264 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD); | |
| 265 return(-2); | |
| 266 } | |
| 267 | |
| 268 cb=b->callback; | |
| 269 | |
| 270 if ((cb != NULL) && | |
| 271 ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0)) | |
| 272 return(i); | |
| 273 | |
| 274 if (!b->init) | |
| 275 { | |
| 276 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED); | |
| 277 return(-2); | |
| 278 } | |
| 279 | |
| 280 i=b->method->bputs(b,in); | |
| 281 | |
| 282 if (i > 0) b->num_write+=(unsigned long)i; | |
| 283 | |
| 284 if (cb != NULL) | |
| 285 i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0, | |
| 286 0L,(long)i); | |
| 287 return(i); | |
| 288 } | |
| 289 | |
| 290 int BIO_gets(BIO *b, char *in, int inl) | |
| 291 { | |
| 292 int i; | |
| 293 long (*cb)(BIO *,int,const char *,int,long,long); | |
| 294 | |
| 295 if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) | |
| 296 { | |
| 297 BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD); | |
| 298 return(-2); | |
| 299 } | |
| 300 | |
| 301 cb=b->callback; | |
| 302 | |
| 303 if ((cb != NULL) && | |
| 304 ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0)) | |
| 305 return(i); | |
| 306 | |
| 307 if (!b->init) | |
| 308 { | |
| 309 BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED); | |
| 310 return(-2); | |
| 311 } | |
| 312 | |
| 313 i=b->method->bgets(b,in,inl); | |
| 314 | |
| 315 if (cb != NULL) | |
| 316 i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl, | |
| 317 0L,(long)i); | |
| 318 return(i); | |
| 319 } | |
| 320 | |
| 321 int BIO_indent(BIO *b,int indent,int max) | |
| 322 { | |
| 323 if(indent < 0) | |
| 324 indent=0; | |
| 325 if(indent > max) | |
| 326 indent=max; | |
| 327 while(indent--) | |
| 328 if(BIO_puts(b," ") != 1) | |
| 329 return 0; | |
| 330 return 1; | |
| 331 } | |
| 332 | |
| 333 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) | |
| 334 { | |
| 335 int i; | |
| 336 | |
| 337 i=iarg; | |
| 338 return(BIO_ctrl(b,cmd,larg,(char *)&i)); | |
| 339 } | |
| 340 | |
| 341 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) | |
| 342 { | |
| 343 char *p=NULL; | |
| 344 | |
| 345 if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0) | |
| 346 return(NULL); | |
| 347 else | |
| 348 return(p); | |
| 349 } | |
| 350 | |
| 351 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) | |
| 352 { | |
| 353 long ret; | |
| 354 long (*cb)(BIO *,int,const char *,int,long,long); | |
| 355 | |
| 356 if (b == NULL) return(0); | |
| 357 | |
| 358 if ((b->method == NULL) || (b->method->ctrl == NULL)) | |
| 359 { | |
| 360 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); | |
| 361 return(-2); | |
| 362 } | |
| 363 | |
| 364 cb=b->callback; | |
| 365 | |
| 366 if ((cb != NULL) && | |
| 367 ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0)) | |
| 368 return(ret); | |
| 369 | |
| 370 ret=b->method->ctrl(b,cmd,larg,parg); | |
| 371 | |
| 372 if (cb != NULL) | |
| 373 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd, | |
| 374 larg,ret); | |
| 375 return(ret); | |
| 376 } | |
| 377 | |
| 378 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const c
har *, int, long, long)) | |
| 379 { | |
| 380 long ret; | |
| 381 long (*cb)(BIO *,int,const char *,int,long,long); | |
| 382 | |
| 383 if (b == NULL) return(0); | |
| 384 | |
| 385 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) | |
| 386 { | |
| 387 BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD); | |
| 388 return(-2); | |
| 389 } | |
| 390 | |
| 391 cb=b->callback; | |
| 392 | |
| 393 if ((cb != NULL) && | |
| 394 ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0)) | |
| 395 return(ret); | |
| 396 | |
| 397 ret=b->method->callback_ctrl(b,cmd,fp); | |
| 398 | |
| 399 if (cb != NULL) | |
| 400 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd, | |
| 401 0,ret); | |
| 402 return(ret); | |
| 403 } | |
| 404 | |
| 405 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros | |
| 406 * do; but those macros have inappropriate return type, and for interfacing | |
| 407 * from other programming languages, C macros aren't much of a help anyway. */ | |
| 408 size_t BIO_ctrl_pending(BIO *bio) | |
| 409 { | |
| 410 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); | |
| 411 } | |
| 412 | |
| 413 size_t BIO_ctrl_wpending(BIO *bio) | |
| 414 { | |
| 415 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); | |
| 416 } | |
| 417 | |
| 418 | |
| 419 /* put the 'bio' on the end of b's list of operators */ | |
| 420 BIO *BIO_push(BIO *b, BIO *bio) | |
| 421 { | |
| 422 BIO *lb; | |
| 423 | |
| 424 if (b == NULL) return(bio); | |
| 425 lb=b; | |
| 426 while (lb->next_bio != NULL) | |
| 427 lb=lb->next_bio; | |
| 428 lb->next_bio=bio; | |
| 429 if (bio != NULL) | |
| 430 bio->prev_bio=lb; | |
| 431 /* called to do internal processing */ | |
| 432 BIO_ctrl(b,BIO_CTRL_PUSH,0,lb); | |
| 433 return(b); | |
| 434 } | |
| 435 | |
| 436 /* Remove the first and return the rest */ | |
| 437 BIO *BIO_pop(BIO *b) | |
| 438 { | |
| 439 BIO *ret; | |
| 440 | |
| 441 if (b == NULL) return(NULL); | |
| 442 ret=b->next_bio; | |
| 443 | |
| 444 BIO_ctrl(b,BIO_CTRL_POP,0,b); | |
| 445 | |
| 446 if (b->prev_bio != NULL) | |
| 447 b->prev_bio->next_bio=b->next_bio; | |
| 448 if (b->next_bio != NULL) | |
| 449 b->next_bio->prev_bio=b->prev_bio; | |
| 450 | |
| 451 b->next_bio=NULL; | |
| 452 b->prev_bio=NULL; | |
| 453 return(ret); | |
| 454 } | |
| 455 | |
| 456 BIO *BIO_get_retry_BIO(BIO *bio, int *reason) | |
| 457 { | |
| 458 BIO *b,*last; | |
| 459 | |
| 460 b=last=bio; | |
| 461 for (;;) | |
| 462 { | |
| 463 if (!BIO_should_retry(b)) break; | |
| 464 last=b; | |
| 465 b=b->next_bio; | |
| 466 if (b == NULL) break; | |
| 467 } | |
| 468 if (reason != NULL) *reason=last->retry_reason; | |
| 469 return(last); | |
| 470 } | |
| 471 | |
| 472 int BIO_get_retry_reason(BIO *bio) | |
| 473 { | |
| 474 return(bio->retry_reason); | |
| 475 } | |
| 476 | |
| 477 BIO *BIO_find_type(BIO *bio, int type) | |
| 478 { | |
| 479 int mt,mask; | |
| 480 | |
| 481 if(!bio) return NULL; | |
| 482 mask=type&0xff; | |
| 483 do { | |
| 484 if (bio->method != NULL) | |
| 485 { | |
| 486 mt=bio->method->type; | |
| 487 | |
| 488 if (!mask) | |
| 489 { | |
| 490 if (mt & type) return(bio); | |
| 491 } | |
| 492 else if (mt == type) | |
| 493 return(bio); | |
| 494 } | |
| 495 bio=bio->next_bio; | |
| 496 } while (bio != NULL); | |
| 497 return(NULL); | |
| 498 } | |
| 499 | |
| 500 BIO *BIO_next(BIO *b) | |
| 501 { | |
| 502 if(!b) return NULL; | |
| 503 return b->next_bio; | |
| 504 } | |
| 505 | |
| 506 void BIO_free_all(BIO *bio) | |
| 507 { | |
| 508 BIO *b; | |
| 509 int ref; | |
| 510 | |
| 511 while (bio != NULL) | |
| 512 { | |
| 513 b=bio; | |
| 514 ref=b->references; | |
| 515 bio=bio->next_bio; | |
| 516 BIO_free(b); | |
| 517 /* Since ref count > 1, don't free anyone else. */ | |
| 518 if (ref > 1) break; | |
| 519 } | |
| 520 } | |
| 521 | |
| 522 BIO *BIO_dup_chain(BIO *in) | |
| 523 { | |
| 524 BIO *ret=NULL,*eoc=NULL,*bio,*new_bio; | |
| 525 | |
| 526 for (bio=in; bio != NULL; bio=bio->next_bio) | |
| 527 { | |
| 528 if ((new_bio=BIO_new(bio->method)) == NULL) goto err; | |
| 529 new_bio->callback=bio->callback; | |
| 530 new_bio->cb_arg=bio->cb_arg; | |
| 531 new_bio->init=bio->init; | |
| 532 new_bio->shutdown=bio->shutdown; | |
| 533 new_bio->flags=bio->flags; | |
| 534 | |
| 535 /* This will let SSL_s_sock() work with stdin/stdout */ | |
| 536 new_bio->num=bio->num; | |
| 537 | |
| 538 if (!BIO_dup_state(bio,(char *)new_bio)) | |
| 539 { | |
| 540 BIO_free(new_bio); | |
| 541 goto err; | |
| 542 } | |
| 543 | |
| 544 /* copy app data */ | |
| 545 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, | |
| 546 &bio->ex_data)) | |
| 547 goto err; | |
| 548 | |
| 549 if (ret == NULL) | |
| 550 { | |
| 551 eoc=new_bio; | |
| 552 ret=eoc; | |
| 553 } | |
| 554 else | |
| 555 { | |
| 556 BIO_push(eoc,new_bio); | |
| 557 eoc=new_bio; | |
| 558 } | |
| 559 } | |
| 560 return(ret); | |
| 561 err: | |
| 562 if (ret != NULL) | |
| 563 BIO_free(ret); | |
| 564 return(NULL); | |
| 565 } | |
| 566 | |
| 567 void BIO_copy_next_retry(BIO *b) | |
| 568 { | |
| 569 BIO_set_flags(b,BIO_get_retry_flags(b->next_bio)); | |
| 570 b->retry_reason=b->next_bio->retry_reason; | |
| 571 } | |
| 572 | |
| 573 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, | |
| 574 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) | |
| 575 { | |
| 576 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, | |
| 577 new_func, dup_func, free_func); | |
| 578 } | |
| 579 | |
| 580 int BIO_set_ex_data(BIO *bio, int idx, void *data) | |
| 581 { | |
| 582 return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); | |
| 583 } | |
| 584 | |
| 585 void *BIO_get_ex_data(BIO *bio, int idx) | |
| 586 { | |
| 587 return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); | |
| 588 } | |
| 589 | |
| 590 unsigned long BIO_number_read(BIO *bio) | |
| 591 { | |
| 592 if(bio) return bio->num_read; | |
| 593 return 0; | |
| 594 } | |
| 595 | |
| 596 unsigned long BIO_number_written(BIO *bio) | |
| 597 { | |
| 598 if(bio) return bio->num_write; | |
| 599 return 0; | |
| 600 } | |
| 601 | |
| 602 IMPLEMENT_STACK_OF(BIO) | |
| OLD | NEW |