bss_conn.c revision 59191
11556Srgrimes/* crypto/bio/bss_conn.c */ 217987Speter/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 31556Srgrimes * All rights reserved. 41556Srgrimes * 51556Srgrimes * This package is an SSL implementation written 61556Srgrimes * by Eric Young (eay@cryptsoft.com). 71556Srgrimes * The implementation was written so as to conform with Netscapes SSL. 81556Srgrimes * 91556Srgrimes * This library is free for commercial and non-commercial use as long as 101556Srgrimes * the following conditions are aheared to. The following conditions 111556Srgrimes * apply to all code found in this distribution, be it the RC4, RSA, 121556Srgrimes * lhash, DES, etc., code; not just the SSL code. The SSL documentation 131556Srgrimes * included with this distribution is covered by the same copyright terms 141556Srgrimes * except that the holder is Tim Hudson (tjh@cryptsoft.com). 151556Srgrimes * 161556Srgrimes * Copyright remains Eric Young's, and as such any Copyright notices in 171556Srgrimes * the code are not to be removed. 181556Srgrimes * If this package is used in a product, Eric Young should be given attribution 191556Srgrimes * as the author of the parts of the library used. 201556Srgrimes * This can be in the form of a textual message at program startup or 211556Srgrimes * in documentation (online or textual) provided with the package. 221556Srgrimes * 231556Srgrimes * Redistribution and use in source and binary forms, with or without 241556Srgrimes * modification, are permitted provided that the following conditions 251556Srgrimes * are met: 261556Srgrimes * 1. Redistributions of source code must retain the copyright 271556Srgrimes * notice, this list of conditions and the following disclaimer. 281556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 291556Srgrimes * notice, this list of conditions and the following disclaimer in the 301556Srgrimes * documentation and/or other materials provided with the distribution. 311556Srgrimes * 3. All advertising materials mentioning features or use of this software 3217987Speter * must display the following acknowledgement: 331556Srgrimes * "This product includes cryptographic software written by 341556Srgrimes * Eric Young (eay@cryptsoft.com)" 351556Srgrimes * The word 'cryptographic' can be left out if the rouines from the library 361556Srgrimes * being used are not cryptographic related :-). 371556Srgrimes * 4. If you include any Windows specific code (or a derivative thereof) from 381556Srgrimes * the apps directory (application code) you must include an acknowledgement: 391556Srgrimes * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 401556Srgrimes * 411556Srgrimes * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 421556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 441556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 451556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 461556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 471556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 481556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 491556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 501556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 511556Srgrimes * SUCH DAMAGE. 521556Srgrimes * 531556Srgrimes * The licence and distribution terms for any publically available version or 541556Srgrimes * derivative of this code cannot be changed. i.e. this code cannot simply be 551556Srgrimes * copied and put under another distribution licence 561556Srgrimes * [including the GNU Public Licence.] 571556Srgrimes */ 581556Srgrimes 591556Srgrimes#ifndef NO_SOCK 601556Srgrimes 611556Srgrimes#include <stdio.h> 621556Srgrimes#include <errno.h> 631556Srgrimes#define USE_SOCKETS 641556Srgrimes#include "cryptlib.h" 651556Srgrimes#include <openssl/bio.h> 661556Srgrimes 671556Srgrimes#ifdef WIN16 681556Srgrimes#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 691556Srgrimes#else 701556Srgrimes#define SOCKET_PROTOCOL IPPROTO_TCP 711556Srgrimes#endif 721556Srgrimes 731556Srgrimes#if (defined(VMS) && __VMS_VER < 70000000) 741556Srgrimes/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ 751556Srgrimes#undef FIONBIO 761556Srgrimes#endif 771556Srgrimes 781556Srgrimes 791556Srgrimestypedef struct bio_connect_st 801556Srgrimes { 811556Srgrimes int state; 821556Srgrimes 831556Srgrimes char *param_hostname; 841556Srgrimes char *param_port; 851556Srgrimes int nbio; 861556Srgrimes 871556Srgrimes unsigned char ip[4]; 881556Srgrimes unsigned short port; 891556Srgrimes 901556Srgrimes struct sockaddr_in them; 911556Srgrimes 921556Srgrimes /* int socket; this will be kept in bio->num so that it is 931556Srgrimes * compatible with the bss_sock bio */ 941556Srgrimes 951556Srgrimes /* called when the connection is initially made 961556Srgrimes * callback(BIO,state,ret); The callback should return 971556Srgrimes * 'ret'. state is for compatibility with the ssl info_callback */ 981556Srgrimes int (*info_callback)(); 991556Srgrimes } BIO_CONNECT; 1001556Srgrimes 1011556Srgrimesstatic int conn_write(BIO *h,char *buf,int num); 1021556Srgrimesstatic int conn_read(BIO *h,char *buf,int size); 1031556Srgrimesstatic int conn_puts(BIO *h,char *str); 1041556Srgrimesstatic long conn_ctrl(BIO *h,int cmd,long arg1,char *arg2); 1051556Srgrimesstatic int conn_new(BIO *h); 1061556Srgrimesstatic int conn_free(BIO *data); 1071556Srgrimesstatic long conn_callback_ctrl(BIO *h,int cmd,void *(*fp)()); 1081556Srgrimes 1091556Srgrimesstatic int conn_state(BIO *b, BIO_CONNECT *c); 1101556Srgrimesstatic void conn_close_socket(BIO *data); 1111556SrgrimesBIO_CONNECT *BIO_CONNECT_new(void ); 1121556Srgrimesvoid BIO_CONNECT_free(BIO_CONNECT *a); 1131556Srgrimes 1141556Srgrimesstatic BIO_METHOD methods_connectp= 1151556Srgrimes { 1161556Srgrimes BIO_TYPE_CONNECT, 1171556Srgrimes "socket connect", 1181556Srgrimes conn_write, 1191556Srgrimes conn_read, 1201556Srgrimes conn_puts, 1211556Srgrimes NULL, /* connect_gets, */ 1221556Srgrimes conn_ctrl, 1231556Srgrimes conn_new, 1241556Srgrimes conn_free, 1251556Srgrimes conn_callback_ctrl, 1261556Srgrimes }; 1271556Srgrimes 1281556Srgrimesstatic int conn_state(BIO *b, BIO_CONNECT *c) 1291556Srgrimes { 1301556Srgrimes int ret= -1,i; 1311556Srgrimes unsigned long l; 1321556Srgrimes char *p,*q; 1331556Srgrimes int (*cb)()=NULL; 1341556Srgrimes 1351556Srgrimes if (c->info_callback != NULL) 1361556Srgrimes cb=c->info_callback; 1371556Srgrimes 1381556Srgrimes for (;;) 1391556Srgrimes { 1401556Srgrimes switch (c->state) 1411556Srgrimes { 1421556Srgrimes case BIO_CONN_S_BEFORE: 1431556Srgrimes p=c->param_hostname; 1441556Srgrimes if (p == NULL) 1451556Srgrimes { 1461556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED); 1471556Srgrimes goto exit_loop; 1481556Srgrimes } 1491556Srgrimes for ( ; *p != '\0'; p++) 1501556Srgrimes { 1511556Srgrimes if ((*p == ':') || (*p == '/')) break; 1521556Srgrimes } 1531556Srgrimes 1541556Srgrimes i= *p; 1551556Srgrimes if ((i == ':') || (i == '/')) 1561556Srgrimes { 1571556Srgrimes 1581556Srgrimes *(p++)='\0'; 1591556Srgrimes if (i == ':') 1601556Srgrimes { 1611556Srgrimes for (q=p; *q; q++) 1621556Srgrimes if (*q == '/') 1631556Srgrimes { 1641556Srgrimes *q='\0'; 1651556Srgrimes break; 1661556Srgrimes } 1671556Srgrimes if (c->param_port != NULL) 1681556Srgrimes Free(c->param_port); 1691556Srgrimes c->param_port=BUF_strdup(p); 1701556Srgrimes } 1711556Srgrimes } 1721556Srgrimes 1731556Srgrimes if (c->param_port == NULL) 1741556Srgrimes { 1751556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED); 1761556Srgrimes ERR_add_error_data(2,"host=",c->param_hostname); 1771556Srgrimes goto exit_loop; 1781556Srgrimes } 1791556Srgrimes c->state=BIO_CONN_S_GET_IP; 1801556Srgrimes break; 1811556Srgrimes 1821556Srgrimes case BIO_CONN_S_GET_IP: 1831556Srgrimes if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0) 1841556Srgrimes goto exit_loop; 1851556Srgrimes c->state=BIO_CONN_S_GET_PORT; 1861556Srgrimes break; 1871556Srgrimes 1881556Srgrimes case BIO_CONN_S_GET_PORT: 1891556Srgrimes if (c->param_port == NULL) 1901556Srgrimes { 1911556Srgrimes abort(); 1921556Srgrimes goto exit_loop; 1931556Srgrimes } 1941556Srgrimes else if (BIO_get_port(c->param_port,&c->port) <= 0) 1951556Srgrimes goto exit_loop; 1961556Srgrimes c->state=BIO_CONN_S_CREATE_SOCKET; 1971556Srgrimes break; 1981556Srgrimes 1991556Srgrimes case BIO_CONN_S_CREATE_SOCKET: 2001556Srgrimes /* now setup address */ 2011556Srgrimes memset((char *)&c->them,0,sizeof(c->them)); 2021556Srgrimes c->them.sin_family=AF_INET; 2031556Srgrimes c->them.sin_port=htons((unsigned short)c->port); 2041556Srgrimes l=(unsigned long) 2051556Srgrimes ((unsigned long)c->ip[0]<<24L)| 2061556Srgrimes ((unsigned long)c->ip[1]<<16L)| 2071556Srgrimes ((unsigned long)c->ip[2]<< 8L)| 2081556Srgrimes ((unsigned long)c->ip[3]); 2091556Srgrimes c->them.sin_addr.s_addr=htonl(l); 2101556Srgrimes c->state=BIO_CONN_S_CREATE_SOCKET; 2111556Srgrimes 2121556Srgrimes ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 2131556Srgrimes if (ret == INVALID_SOCKET) 2141556Srgrimes { 2151556Srgrimes SYSerr(SYS_F_SOCKET,get_last_socket_error()); 2161556Srgrimes ERR_add_error_data(4,"host=",c->param_hostname, 2171556Srgrimes ":",c->param_port); 2181556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET); 2191556Srgrimes goto exit_loop; 2201556Srgrimes } 2211556Srgrimes b->num=ret; 2221556Srgrimes c->state=BIO_CONN_S_NBIO; 2231556Srgrimes break; 2241556Srgrimes 2251556Srgrimes case BIO_CONN_S_NBIO: 2261556Srgrimes if (c->nbio) 2271556Srgrimes { 2281556Srgrimes if (!BIO_socket_nbio(b->num,1)) 2291556Srgrimes { 2301556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO); 2311556Srgrimes ERR_add_error_data(4,"host=", 2321556Srgrimes c->param_hostname, 2331556Srgrimes ":",c->param_port); 2341556Srgrimes goto exit_loop; 2351556Srgrimes } 2361556Srgrimes } 2371556Srgrimes c->state=BIO_CONN_S_CONNECT; 2381556Srgrimes 2391556Srgrimes#ifdef SO_KEEPALIVE 2401556Srgrimes i=1; 2411556Srgrimes i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); 2421556Srgrimes if (i < 0) 2431556Srgrimes { 2441556Srgrimes SYSerr(SYS_F_SOCKET,get_last_socket_error()); 2451556Srgrimes ERR_add_error_data(4,"host=",c->param_hostname, 2461556Srgrimes ":",c->param_port); 2471556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE); 2481556Srgrimes goto exit_loop; 2491556Srgrimes } 2501556Srgrimes#endif 2511556Srgrimes break; 2521556Srgrimes 2531556Srgrimes case BIO_CONN_S_CONNECT: 2541556Srgrimes BIO_clear_retry_flags(b); 2551556Srgrimes ret=connect(b->num, 2561556Srgrimes (struct sockaddr *)&c->them, 2571556Srgrimes sizeof(c->them)); 2581556Srgrimes b->retry_reason=0; 2591556Srgrimes if (ret < 0) 2601556Srgrimes { 2611556Srgrimes if (BIO_sock_should_retry(ret)) 2621556Srgrimes { 2631556Srgrimes BIO_set_retry_special(b); 2641556Srgrimes c->state=BIO_CONN_S_BLOCKED_CONNECT; 2651556Srgrimes b->retry_reason=BIO_RR_CONNECT; 2661556Srgrimes } 2671556Srgrimes else 2681556Srgrimes { 2691556Srgrimes SYSerr(SYS_F_CONNECT,get_last_socket_error()); 2701556Srgrimes ERR_add_error_data(4,"host=", 2711556Srgrimes c->param_hostname, 2721556Srgrimes ":",c->param_port); 2731556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR); 2741556Srgrimes } 2751556Srgrimes goto exit_loop; 2761556Srgrimes } 2771556Srgrimes else 2781556Srgrimes c->state=BIO_CONN_S_OK; 2791556Srgrimes break; 2801556Srgrimes 2811556Srgrimes case BIO_CONN_S_BLOCKED_CONNECT: 2821556Srgrimes i=BIO_sock_error(b->num); 2831556Srgrimes if (i) 2841556Srgrimes { 2851556Srgrimes BIO_clear_retry_flags(b); 2861556Srgrimes SYSerr(SYS_F_CONNECT,i); 2871556Srgrimes ERR_add_error_data(4,"host=", 2881556Srgrimes c->param_hostname, 2891556Srgrimes ":",c->param_port); 2901556Srgrimes BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR); 2911556Srgrimes ret=0; 2921556Srgrimes goto exit_loop; 2931556Srgrimes } 2941556Srgrimes else 2951556Srgrimes c->state=BIO_CONN_S_OK; 2961556Srgrimes break; 2971556Srgrimes 2981556Srgrimes case BIO_CONN_S_OK: 2991556Srgrimes ret=1; 3001556Srgrimes goto exit_loop; 3011556Srgrimes default: 3021556Srgrimes abort(); 3031556Srgrimes goto exit_loop; 3041556Srgrimes } 3051556Srgrimes 3061556Srgrimes if (cb != NULL) 3071556Srgrimes { 3081556Srgrimes if (!(ret=cb((BIO *)b,c->state,ret))) 3091556Srgrimes goto end; 3101556Srgrimes } 3111556Srgrimes } 3121556Srgrimes 3131556Srgrimes /* Loop does not exit */ 3141556Srgrimesexit_loop: 3151556Srgrimes if (cb != NULL) 3161556Srgrimes ret=cb((BIO *)b,c->state,ret); 3171556Srgrimesend: 3181556Srgrimes return(ret); 3191556Srgrimes } 3201556Srgrimes 3211556SrgrimesBIO_CONNECT *BIO_CONNECT_new(void) 3221556Srgrimes { 3231556Srgrimes BIO_CONNECT *ret; 3241556Srgrimes 3251556Srgrimes if ((ret=(BIO_CONNECT *)Malloc(sizeof(BIO_CONNECT))) == NULL) 3261556Srgrimes return(NULL); 3271556Srgrimes ret->state=BIO_CONN_S_BEFORE; 3281556Srgrimes ret->param_hostname=NULL; 3291556Srgrimes ret->param_port=NULL; 3301556Srgrimes ret->info_callback=NULL; 3311556Srgrimes ret->nbio=0; 3321556Srgrimes ret->ip[0]=0; 3331556Srgrimes ret->ip[1]=0; 3341556Srgrimes ret->ip[2]=0; 3351556Srgrimes ret->ip[3]=0; 3361556Srgrimes ret->port=0; 3371556Srgrimes memset((char *)&ret->them,0,sizeof(ret->them)); 3381556Srgrimes return(ret); 3391556Srgrimes } 3401556Srgrimes 3411556Srgrimesvoid BIO_CONNECT_free(BIO_CONNECT *a) 3421556Srgrimes { 3431556Srgrimes if(a == NULL) 3441556Srgrimes return; 3451556Srgrimes 3461556Srgrimes if (a->param_hostname != NULL) 3471556Srgrimes Free(a->param_hostname); 3481556Srgrimes if (a->param_port != NULL) 3491556Srgrimes Free(a->param_port); 3501556Srgrimes Free(a); 3511556Srgrimes } 3521556Srgrimes 3531556SrgrimesBIO_METHOD *BIO_s_connect(void) 3541556Srgrimes { 3551556Srgrimes return(&methods_connectp); 3561556Srgrimes } 3571556Srgrimes 358static int conn_new(BIO *bi) 359 { 360 bi->init=0; 361 bi->num=INVALID_SOCKET; 362 bi->flags=0; 363 if ((bi->ptr=(char *)BIO_CONNECT_new()) == NULL) 364 return(0); 365 else 366 return(1); 367 } 368 369static void conn_close_socket(BIO *bio) 370 { 371 BIO_CONNECT *c; 372 373 c=(BIO_CONNECT *)bio->ptr; 374 if (bio->num != INVALID_SOCKET) 375 { 376 /* Only do a shutdown if things were established */ 377 if (c->state == BIO_CONN_S_OK) 378 shutdown(bio->num,2); 379 closesocket(bio->num); 380 bio->num=INVALID_SOCKET; 381 } 382 } 383 384static int conn_free(BIO *a) 385 { 386 BIO_CONNECT *data; 387 388 if (a == NULL) return(0); 389 data=(BIO_CONNECT *)a->ptr; 390 391 if (a->shutdown) 392 { 393 conn_close_socket(a); 394 BIO_CONNECT_free(data); 395 a->ptr=NULL; 396 a->flags=0; 397 a->init=0; 398 } 399 return(1); 400 } 401 402static int conn_read(BIO *b, char *out, int outl) 403 { 404 int ret=0; 405 BIO_CONNECT *data; 406 407 data=(BIO_CONNECT *)b->ptr; 408 if (data->state != BIO_CONN_S_OK) 409 { 410 ret=conn_state(b,data); 411 if (ret <= 0) 412 return(ret); 413 } 414 415 if (out != NULL) 416 { 417 clear_socket_error(); 418 ret=readsocket(b->num,out,outl); 419 BIO_clear_retry_flags(b); 420 if (ret <= 0) 421 { 422 if (BIO_sock_should_retry(ret)) 423 BIO_set_retry_read(b); 424 } 425 } 426 return(ret); 427 } 428 429static int conn_write(BIO *b, char *in, int inl) 430 { 431 int ret; 432 BIO_CONNECT *data; 433 434 data=(BIO_CONNECT *)b->ptr; 435 if (data->state != BIO_CONN_S_OK) 436 { 437 ret=conn_state(b,data); 438 if (ret <= 0) return(ret); 439 } 440 441 clear_socket_error(); 442 ret=writesocket(b->num,in,inl); 443 BIO_clear_retry_flags(b); 444 if (ret <= 0) 445 { 446 if (BIO_sock_should_retry(ret)) 447 BIO_set_retry_write(b); 448 } 449 return(ret); 450 } 451 452static long conn_ctrl(BIO *b, int cmd, long num, char *ptr) 453 { 454 BIO *dbio; 455 int *ip; 456 const char **pptr; 457 long ret=1; 458 BIO_CONNECT *data; 459 460 data=(BIO_CONNECT *)b->ptr; 461 462 switch (cmd) 463 { 464 case BIO_CTRL_RESET: 465 ret=0; 466 data->state=BIO_CONN_S_BEFORE; 467 conn_close_socket(b); 468 b->flags=0; 469 break; 470 case BIO_C_DO_STATE_MACHINE: 471 /* use this one to start the connection */ 472 if (!data->state != BIO_CONN_S_OK) 473 ret=(long)conn_state(b,data); 474 else 475 ret=1; 476 break; 477 case BIO_C_GET_CONNECT: 478 if (ptr != NULL) 479 { 480 pptr=(const char **)ptr; 481 if (num == 0) 482 { 483 *pptr=data->param_hostname; 484 485 } 486 else if (num == 1) 487 { 488 *pptr=data->param_port; 489 } 490 else if (num == 2) 491 { 492 *pptr= (char *)&(data->ip[0]); 493 } 494 else if (num == 3) 495 { 496 *((int *)ptr)=data->port; 497 } 498 if ((!b->init) || (ptr == NULL)) 499 *pptr="not initialized"; 500 ret=1; 501 } 502 break; 503 case BIO_C_SET_CONNECT: 504 if (ptr != NULL) 505 { 506 b->init=1; 507 if (num == 0) 508 { 509 if (data->param_hostname != NULL) 510 Free(data->param_hostname); 511 data->param_hostname=BUF_strdup(ptr); 512 } 513 else if (num == 1) 514 { 515 if (data->param_port != NULL) 516 Free(data->param_port); 517 data->param_port=BUF_strdup(ptr); 518 } 519 else if (num == 2) 520 { 521 char buf[16]; 522 523 sprintf(buf,"%d.%d.%d.%d", 524 ptr[0],ptr[1],ptr[2],ptr[3]); 525 if (data->param_hostname != NULL) 526 Free(data->param_hostname); 527 data->param_hostname=BUF_strdup(buf); 528 memcpy(&(data->ip[0]),ptr,4); 529 } 530 else if (num == 3) 531 { 532 char buf[16]; 533 534 sprintf(buf,"%d",*(int *)ptr); 535 if (data->param_port != NULL) 536 Free(data->param_port); 537 data->param_port=BUF_strdup(buf); 538 data->port= *(int *)ptr; 539 } 540 } 541 break; 542 case BIO_C_SET_NBIO: 543 data->nbio=(int)num; 544 break; 545 case BIO_C_GET_FD: 546 if (b->init) 547 { 548 ip=(int *)ptr; 549 if (ip != NULL) 550 *ip=b->num; 551 ret=b->num; 552 } 553 else 554 ret= -1; 555 break; 556 case BIO_CTRL_GET_CLOSE: 557 ret=b->shutdown; 558 break; 559 case BIO_CTRL_SET_CLOSE: 560 b->shutdown=(int)num; 561 break; 562 case BIO_CTRL_PENDING: 563 case BIO_CTRL_WPENDING: 564 ret=0; 565 break; 566 case BIO_CTRL_FLUSH: 567 break; 568 case BIO_CTRL_DUP: 569 { 570 dbio=(BIO *)ptr; 571 if (data->param_port) 572 BIO_set_conn_port(dbio,data->param_port); 573 if (data->param_hostname) 574 BIO_set_conn_hostname(dbio,data->param_hostname); 575 BIO_set_nbio(dbio,data->nbio); 576 (void)BIO_set_info_callback(dbio,(void *(*)())(data->info_callback)); 577 } 578 break; 579 case BIO_CTRL_SET_CALLBACK: 580 { 581#if 0 /* FIXME: Should this be used? -- Richard Levitte */ 582 BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 583 ret = -1; 584#else 585 ret=0; 586#endif 587 } 588 break; 589 case BIO_CTRL_GET_CALLBACK: 590 { 591 int (**fptr)(); 592 593 fptr=(int (**)())ptr; 594 *fptr=data->info_callback; 595 } 596 break; 597 default: 598 ret=0; 599 break; 600 } 601 return(ret); 602 } 603 604static long conn_callback_ctrl(BIO *b, int cmd, void *(*fp)()) 605 { 606 long ret=1; 607 BIO_CONNECT *data; 608 609 data=(BIO_CONNECT *)b->ptr; 610 611 switch (cmd) 612 { 613 case BIO_CTRL_SET_CALLBACK: 614 { 615 data->info_callback=(int (*)())fp; 616 } 617 break; 618 default: 619 ret=0; 620 break; 621 } 622 return(ret); 623 } 624 625static int conn_puts(BIO *bp, char *str) 626 { 627 int n,ret; 628 629 n=strlen(str); 630 ret=conn_write(bp,str,n); 631 return(ret); 632 } 633 634BIO *BIO_new_connect(char *str) 635 { 636 BIO *ret; 637 638 ret=BIO_new(BIO_s_connect()); 639 if (ret == NULL) return(NULL); 640 if (BIO_set_conn_hostname(ret,str)) 641 return(ret); 642 else 643 { 644 BIO_free(ret); 645 return(NULL); 646 } 647 } 648 649#endif 650 651