155714Skris/* crypto/bio/bss_conn.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. 855714Skris * 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). 1555714Skris * 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. 2255714Skris * 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 :-). 3755714Skris * 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)" 4055714Skris * 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. 5255714Skris * 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#define USE_SOCKETS 6255714Skris#include "cryptlib.h" 6355714Skris#include <openssl/bio.h> 6455714Skris 65160814Ssimon#ifndef OPENSSL_NO_SOCK 66160814Ssimon 67109998Smarkm#ifdef OPENSSL_SYS_WIN16 6855714Skris#define SOCKET_PROTOCOL 0 /* more microsoft stupidity */ 6955714Skris#else 7055714Skris#define SOCKET_PROTOCOL IPPROTO_TCP 7155714Skris#endif 7255714Skris 73109998Smarkm#if (defined(OPENSSL_SYS_VMS) && __VMS_VER < 70000000) 7455714Skris/* FIONBIO used as a switch to enable ioctl, and that isn't in VMS < 7.0 */ 7555714Skris#undef FIONBIO 7655714Skris#endif 7755714Skris 7855714Skris 7955714Skristypedef struct bio_connect_st 8055714Skris { 8155714Skris int state; 8255714Skris 8355714Skris char *param_hostname; 8455714Skris char *param_port; 8555714Skris int nbio; 8655714Skris 8755714Skris unsigned char ip[4]; 8855714Skris unsigned short port; 8955714Skris 9055714Skris struct sockaddr_in them; 9155714Skris 9255714Skris /* int socket; this will be kept in bio->num so that it is 9359191Skris * compatible with the bss_sock bio */ 9455714Skris 9555714Skris /* called when the connection is initially made 9655714Skris * callback(BIO,state,ret); The callback should return 9759191Skris * 'ret'. state is for compatibility with the ssl info_callback */ 98109998Smarkm int (*info_callback)(const BIO *bio,int state,int ret); 9955714Skris } BIO_CONNECT; 10055714Skris 10168651Skrisstatic int conn_write(BIO *h, const char *buf, int num); 10268651Skrisstatic int conn_read(BIO *h, char *buf, int size); 10368651Skrisstatic int conn_puts(BIO *h, const char *str); 10468651Skrisstatic long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2); 10555714Skrisstatic int conn_new(BIO *h); 10655714Skrisstatic int conn_free(BIO *data); 10768651Skrisstatic long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *); 10855714Skris 10955714Skrisstatic int conn_state(BIO *b, BIO_CONNECT *c); 11055714Skrisstatic void conn_close_socket(BIO *data); 11155714SkrisBIO_CONNECT *BIO_CONNECT_new(void ); 11255714Skrisvoid BIO_CONNECT_free(BIO_CONNECT *a); 11355714Skris 11455714Skrisstatic BIO_METHOD methods_connectp= 11555714Skris { 11655714Skris BIO_TYPE_CONNECT, 11755714Skris "socket connect", 11855714Skris conn_write, 11955714Skris conn_read, 12055714Skris conn_puts, 12155714Skris NULL, /* connect_gets, */ 12255714Skris conn_ctrl, 12355714Skris conn_new, 12455714Skris conn_free, 12559191Skris conn_callback_ctrl, 12655714Skris }; 12755714Skris 12855714Skrisstatic int conn_state(BIO *b, BIO_CONNECT *c) 12955714Skris { 13055714Skris int ret= -1,i; 13155714Skris unsigned long l; 13255714Skris char *p,*q; 133160814Ssimon int (*cb)(const BIO *,int,int)=NULL; 13455714Skris 13555714Skris if (c->info_callback != NULL) 13655714Skris cb=c->info_callback; 13755714Skris 13855714Skris for (;;) 13955714Skris { 14055714Skris switch (c->state) 14155714Skris { 14255714Skris case BIO_CONN_S_BEFORE: 14355714Skris p=c->param_hostname; 14455714Skris if (p == NULL) 14555714Skris { 14655714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED); 14755714Skris goto exit_loop; 14855714Skris } 14955714Skris for ( ; *p != '\0'; p++) 15055714Skris { 15155714Skris if ((*p == ':') || (*p == '/')) break; 15255714Skris } 15355714Skris 15455714Skris i= *p; 15555714Skris if ((i == ':') || (i == '/')) 15655714Skris { 15755714Skris 15855714Skris *(p++)='\0'; 15955714Skris if (i == ':') 16055714Skris { 16155714Skris for (q=p; *q; q++) 16255714Skris if (*q == '/') 16355714Skris { 16455714Skris *q='\0'; 16555714Skris break; 16655714Skris } 16755714Skris if (c->param_port != NULL) 16868651Skris OPENSSL_free(c->param_port); 16955714Skris c->param_port=BUF_strdup(p); 17055714Skris } 17155714Skris } 17255714Skris 17355714Skris if (c->param_port == NULL) 17455714Skris { 17555714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED); 17655714Skris ERR_add_error_data(2,"host=",c->param_hostname); 17755714Skris goto exit_loop; 17855714Skris } 17955714Skris c->state=BIO_CONN_S_GET_IP; 18055714Skris break; 18155714Skris 18255714Skris case BIO_CONN_S_GET_IP: 18355714Skris if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0) 18455714Skris goto exit_loop; 18555714Skris c->state=BIO_CONN_S_GET_PORT; 18655714Skris break; 18755714Skris 18855714Skris case BIO_CONN_S_GET_PORT: 18955714Skris if (c->param_port == NULL) 19055714Skris { 19168651Skris /* abort(); */ 19255714Skris goto exit_loop; 19355714Skris } 19455714Skris else if (BIO_get_port(c->param_port,&c->port) <= 0) 19555714Skris goto exit_loop; 19655714Skris c->state=BIO_CONN_S_CREATE_SOCKET; 19755714Skris break; 19855714Skris 19955714Skris case BIO_CONN_S_CREATE_SOCKET: 20055714Skris /* now setup address */ 20155714Skris memset((char *)&c->them,0,sizeof(c->them)); 20255714Skris c->them.sin_family=AF_INET; 20355714Skris c->them.sin_port=htons((unsigned short)c->port); 20455714Skris l=(unsigned long) 20555714Skris ((unsigned long)c->ip[0]<<24L)| 20655714Skris ((unsigned long)c->ip[1]<<16L)| 20755714Skris ((unsigned long)c->ip[2]<< 8L)| 20855714Skris ((unsigned long)c->ip[3]); 20955714Skris c->them.sin_addr.s_addr=htonl(l); 21055714Skris c->state=BIO_CONN_S_CREATE_SOCKET; 21155714Skris 21255714Skris ret=socket(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); 21355714Skris if (ret == INVALID_SOCKET) 21455714Skris { 21555714Skris SYSerr(SYS_F_SOCKET,get_last_socket_error()); 21655714Skris ERR_add_error_data(4,"host=",c->param_hostname, 21755714Skris ":",c->param_port); 21855714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET); 21955714Skris goto exit_loop; 22055714Skris } 22155714Skris b->num=ret; 22255714Skris c->state=BIO_CONN_S_NBIO; 22355714Skris break; 22455714Skris 22555714Skris case BIO_CONN_S_NBIO: 22655714Skris if (c->nbio) 22755714Skris { 22855714Skris if (!BIO_socket_nbio(b->num,1)) 22955714Skris { 23055714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO); 23155714Skris ERR_add_error_data(4,"host=", 23255714Skris c->param_hostname, 23355714Skris ":",c->param_port); 23455714Skris goto exit_loop; 23555714Skris } 23655714Skris } 23755714Skris c->state=BIO_CONN_S_CONNECT; 23855714Skris 239109998Smarkm#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) 24055714Skris i=1; 24155714Skris i=setsockopt(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); 24255714Skris if (i < 0) 24355714Skris { 24455714Skris SYSerr(SYS_F_SOCKET,get_last_socket_error()); 24555714Skris ERR_add_error_data(4,"host=",c->param_hostname, 24655714Skris ":",c->param_port); 24755714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE); 24855714Skris goto exit_loop; 24955714Skris } 25055714Skris#endif 25155714Skris break; 25255714Skris 25355714Skris case BIO_CONN_S_CONNECT: 25455714Skris BIO_clear_retry_flags(b); 25555714Skris ret=connect(b->num, 25655714Skris (struct sockaddr *)&c->them, 25755714Skris sizeof(c->them)); 25855714Skris b->retry_reason=0; 25955714Skris if (ret < 0) 26055714Skris { 26155714Skris if (BIO_sock_should_retry(ret)) 26255714Skris { 26355714Skris BIO_set_retry_special(b); 26455714Skris c->state=BIO_CONN_S_BLOCKED_CONNECT; 26555714Skris b->retry_reason=BIO_RR_CONNECT; 26655714Skris } 26755714Skris else 26855714Skris { 26955714Skris SYSerr(SYS_F_CONNECT,get_last_socket_error()); 27055714Skris ERR_add_error_data(4,"host=", 27155714Skris c->param_hostname, 27255714Skris ":",c->param_port); 27355714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR); 27455714Skris } 27555714Skris goto exit_loop; 27655714Skris } 27755714Skris else 27855714Skris c->state=BIO_CONN_S_OK; 27955714Skris break; 28055714Skris 28155714Skris case BIO_CONN_S_BLOCKED_CONNECT: 28255714Skris i=BIO_sock_error(b->num); 28355714Skris if (i) 28455714Skris { 28555714Skris BIO_clear_retry_flags(b); 28655714Skris SYSerr(SYS_F_CONNECT,i); 28755714Skris ERR_add_error_data(4,"host=", 28855714Skris c->param_hostname, 28955714Skris ":",c->param_port); 29055714Skris BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR); 29155714Skris ret=0; 29255714Skris goto exit_loop; 29355714Skris } 29455714Skris else 29555714Skris c->state=BIO_CONN_S_OK; 29655714Skris break; 29755714Skris 29855714Skris case BIO_CONN_S_OK: 29955714Skris ret=1; 30055714Skris goto exit_loop; 30155714Skris default: 30268651Skris /* abort(); */ 30355714Skris goto exit_loop; 30455714Skris } 30555714Skris 30655714Skris if (cb != NULL) 30755714Skris { 30855714Skris if (!(ret=cb((BIO *)b,c->state,ret))) 30955714Skris goto end; 31055714Skris } 31155714Skris } 31255714Skris 31355714Skris /* Loop does not exit */ 31455714Skrisexit_loop: 31555714Skris if (cb != NULL) 31655714Skris ret=cb((BIO *)b,c->state,ret); 31755714Skrisend: 31855714Skris return(ret); 31955714Skris } 32055714Skris 32155714SkrisBIO_CONNECT *BIO_CONNECT_new(void) 32255714Skris { 32355714Skris BIO_CONNECT *ret; 32455714Skris 32568651Skris if ((ret=(BIO_CONNECT *)OPENSSL_malloc(sizeof(BIO_CONNECT))) == NULL) 32655714Skris return(NULL); 32755714Skris ret->state=BIO_CONN_S_BEFORE; 32855714Skris ret->param_hostname=NULL; 32955714Skris ret->param_port=NULL; 33055714Skris ret->info_callback=NULL; 33155714Skris ret->nbio=0; 33255714Skris ret->ip[0]=0; 33355714Skris ret->ip[1]=0; 33455714Skris ret->ip[2]=0; 33555714Skris ret->ip[3]=0; 33655714Skris ret->port=0; 33755714Skris memset((char *)&ret->them,0,sizeof(ret->them)); 33855714Skris return(ret); 33955714Skris } 34055714Skris 34155714Skrisvoid BIO_CONNECT_free(BIO_CONNECT *a) 34255714Skris { 34355714Skris if(a == NULL) 34455714Skris return; 34555714Skris 34655714Skris if (a->param_hostname != NULL) 34768651Skris OPENSSL_free(a->param_hostname); 34855714Skris if (a->param_port != NULL) 34968651Skris OPENSSL_free(a->param_port); 35068651Skris OPENSSL_free(a); 35155714Skris } 35255714Skris 35355714SkrisBIO_METHOD *BIO_s_connect(void) 35455714Skris { 35555714Skris return(&methods_connectp); 35655714Skris } 35755714Skris 35855714Skrisstatic int conn_new(BIO *bi) 35955714Skris { 36055714Skris bi->init=0; 36155714Skris bi->num=INVALID_SOCKET; 36255714Skris bi->flags=0; 36355714Skris if ((bi->ptr=(char *)BIO_CONNECT_new()) == NULL) 36455714Skris return(0); 36555714Skris else 36655714Skris return(1); 36755714Skris } 36855714Skris 36955714Skrisstatic void conn_close_socket(BIO *bio) 37055714Skris { 37155714Skris BIO_CONNECT *c; 37255714Skris 37355714Skris c=(BIO_CONNECT *)bio->ptr; 37455714Skris if (bio->num != INVALID_SOCKET) 37555714Skris { 37655714Skris /* Only do a shutdown if things were established */ 37755714Skris if (c->state == BIO_CONN_S_OK) 37855714Skris shutdown(bio->num,2); 37955714Skris closesocket(bio->num); 38055714Skris bio->num=INVALID_SOCKET; 38155714Skris } 38255714Skris } 38355714Skris 38455714Skrisstatic int conn_free(BIO *a) 38555714Skris { 38655714Skris BIO_CONNECT *data; 38755714Skris 38855714Skris if (a == NULL) return(0); 38955714Skris data=(BIO_CONNECT *)a->ptr; 39055714Skris 39155714Skris if (a->shutdown) 39255714Skris { 39355714Skris conn_close_socket(a); 39455714Skris BIO_CONNECT_free(data); 39555714Skris a->ptr=NULL; 39655714Skris a->flags=0; 39755714Skris a->init=0; 39855714Skris } 39955714Skris return(1); 40055714Skris } 40155714Skris 40255714Skrisstatic int conn_read(BIO *b, char *out, int outl) 40355714Skris { 40455714Skris int ret=0; 40555714Skris BIO_CONNECT *data; 40655714Skris 40755714Skris data=(BIO_CONNECT *)b->ptr; 40855714Skris if (data->state != BIO_CONN_S_OK) 40955714Skris { 41055714Skris ret=conn_state(b,data); 41155714Skris if (ret <= 0) 41255714Skris return(ret); 41355714Skris } 41455714Skris 41555714Skris if (out != NULL) 41655714Skris { 41755714Skris clear_socket_error(); 41855714Skris ret=readsocket(b->num,out,outl); 41955714Skris BIO_clear_retry_flags(b); 42055714Skris if (ret <= 0) 42155714Skris { 42255714Skris if (BIO_sock_should_retry(ret)) 42355714Skris BIO_set_retry_read(b); 42455714Skris } 42555714Skris } 42655714Skris return(ret); 42755714Skris } 42855714Skris 42968651Skrisstatic int conn_write(BIO *b, const char *in, int inl) 43055714Skris { 43155714Skris int ret; 43255714Skris BIO_CONNECT *data; 43355714Skris 43455714Skris data=(BIO_CONNECT *)b->ptr; 43555714Skris if (data->state != BIO_CONN_S_OK) 43655714Skris { 43755714Skris ret=conn_state(b,data); 43855714Skris if (ret <= 0) return(ret); 43955714Skris } 44055714Skris 44155714Skris clear_socket_error(); 44255714Skris ret=writesocket(b->num,in,inl); 44355714Skris BIO_clear_retry_flags(b); 44455714Skris if (ret <= 0) 44555714Skris { 44655714Skris if (BIO_sock_should_retry(ret)) 44755714Skris BIO_set_retry_write(b); 44855714Skris } 44955714Skris return(ret); 45055714Skris } 45155714Skris 45268651Skrisstatic long conn_ctrl(BIO *b, int cmd, long num, void *ptr) 45355714Skris { 45455714Skris BIO *dbio; 45555714Skris int *ip; 45655714Skris const char **pptr; 45755714Skris long ret=1; 45855714Skris BIO_CONNECT *data; 45955714Skris 46055714Skris data=(BIO_CONNECT *)b->ptr; 46155714Skris 46255714Skris switch (cmd) 46355714Skris { 46455714Skris case BIO_CTRL_RESET: 46555714Skris ret=0; 46655714Skris data->state=BIO_CONN_S_BEFORE; 46755714Skris conn_close_socket(b); 46855714Skris b->flags=0; 46955714Skris break; 47055714Skris case BIO_C_DO_STATE_MACHINE: 47155714Skris /* use this one to start the connection */ 472160814Ssimon if (data->state != BIO_CONN_S_OK) 47355714Skris ret=(long)conn_state(b,data); 47455714Skris else 47555714Skris ret=1; 47655714Skris break; 47755714Skris case BIO_C_GET_CONNECT: 47855714Skris if (ptr != NULL) 47955714Skris { 48055714Skris pptr=(const char **)ptr; 48155714Skris if (num == 0) 48255714Skris { 48355714Skris *pptr=data->param_hostname; 48455714Skris 48555714Skris } 48655714Skris else if (num == 1) 48755714Skris { 48855714Skris *pptr=data->param_port; 48955714Skris } 49055714Skris else if (num == 2) 49155714Skris { 49255714Skris *pptr= (char *)&(data->ip[0]); 49355714Skris } 49455714Skris else if (num == 3) 49555714Skris { 49655714Skris *((int *)ptr)=data->port; 49755714Skris } 49855714Skris if ((!b->init) || (ptr == NULL)) 49959191Skris *pptr="not initialized"; 50055714Skris ret=1; 50155714Skris } 50255714Skris break; 50355714Skris case BIO_C_SET_CONNECT: 50455714Skris if (ptr != NULL) 50555714Skris { 50655714Skris b->init=1; 50755714Skris if (num == 0) 50855714Skris { 50955714Skris if (data->param_hostname != NULL) 51068651Skris OPENSSL_free(data->param_hostname); 51155714Skris data->param_hostname=BUF_strdup(ptr); 51255714Skris } 51355714Skris else if (num == 1) 51455714Skris { 51555714Skris if (data->param_port != NULL) 51668651Skris OPENSSL_free(data->param_port); 51755714Skris data->param_port=BUF_strdup(ptr); 51855714Skris } 51955714Skris else if (num == 2) 52055714Skris { 52155714Skris char buf[16]; 522109998Smarkm unsigned char *p = ptr; 52355714Skris 524127128Snectar BIO_snprintf(buf,sizeof buf,"%d.%d.%d.%d", 525127128Snectar p[0],p[1],p[2],p[3]); 52655714Skris if (data->param_hostname != NULL) 52768651Skris OPENSSL_free(data->param_hostname); 52855714Skris data->param_hostname=BUF_strdup(buf); 52955714Skris memcpy(&(data->ip[0]),ptr,4); 53055714Skris } 53155714Skris else if (num == 3) 53255714Skris { 533109998Smarkm char buf[DECIMAL_SIZE(int)+1]; 53455714Skris 535127128Snectar BIO_snprintf(buf,sizeof buf,"%d",*(int *)ptr); 53655714Skris if (data->param_port != NULL) 53768651Skris OPENSSL_free(data->param_port); 53855714Skris data->param_port=BUF_strdup(buf); 53955714Skris data->port= *(int *)ptr; 54055714Skris } 54155714Skris } 54255714Skris break; 54355714Skris case BIO_C_SET_NBIO: 54455714Skris data->nbio=(int)num; 54555714Skris break; 54655714Skris case BIO_C_GET_FD: 54755714Skris if (b->init) 54855714Skris { 54955714Skris ip=(int *)ptr; 55055714Skris if (ip != NULL) 55155714Skris *ip=b->num; 55255714Skris ret=b->num; 55355714Skris } 55455714Skris else 55555714Skris ret= -1; 55655714Skris break; 55755714Skris case BIO_CTRL_GET_CLOSE: 55855714Skris ret=b->shutdown; 55955714Skris break; 56055714Skris case BIO_CTRL_SET_CLOSE: 56155714Skris b->shutdown=(int)num; 56255714Skris break; 56355714Skris case BIO_CTRL_PENDING: 56455714Skris case BIO_CTRL_WPENDING: 56555714Skris ret=0; 56655714Skris break; 56755714Skris case BIO_CTRL_FLUSH: 56855714Skris break; 56955714Skris case BIO_CTRL_DUP: 57059191Skris { 57155714Skris dbio=(BIO *)ptr; 57255714Skris if (data->param_port) 57355714Skris BIO_set_conn_port(dbio,data->param_port); 57455714Skris if (data->param_hostname) 57555714Skris BIO_set_conn_hostname(dbio,data->param_hostname); 57655714Skris BIO_set_nbio(dbio,data->nbio); 577109998Smarkm /* FIXME: the cast of the function seems unlikely to be a good idea */ 578109998Smarkm (void)BIO_set_info_callback(dbio,(bio_info_cb *)data->info_callback); 57959191Skris } 58055714Skris break; 58155714Skris case BIO_CTRL_SET_CALLBACK: 58259191Skris { 58359191Skris#if 0 /* FIXME: Should this be used? -- Richard Levitte */ 58459191Skris BIOerr(BIO_F_CONN_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 58559191Skris ret = -1; 58659191Skris#else 58759191Skris ret=0; 58859191Skris#endif 58959191Skris } 59055714Skris break; 59155714Skris case BIO_CTRL_GET_CALLBACK: 59255714Skris { 593160814Ssimon int (**fptr)(const BIO *bio,int state,int xret); 59455714Skris 595160814Ssimon fptr=(int (**)(const BIO *bio,int state,int xret))ptr; 59655714Skris *fptr=data->info_callback; 59755714Skris } 59855714Skris break; 59955714Skris default: 60055714Skris ret=0; 60155714Skris break; 60255714Skris } 60355714Skris return(ret); 60455714Skris } 60555714Skris 60668651Skrisstatic long conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 60759191Skris { 60859191Skris long ret=1; 60959191Skris BIO_CONNECT *data; 61059191Skris 61159191Skris data=(BIO_CONNECT *)b->ptr; 61259191Skris 61359191Skris switch (cmd) 61459191Skris { 61559191Skris case BIO_CTRL_SET_CALLBACK: 61659191Skris { 617109998Smarkm data->info_callback=(int (*)(const struct bio_st *, int, int))fp; 61859191Skris } 61959191Skris break; 62059191Skris default: 62159191Skris ret=0; 62259191Skris break; 62359191Skris } 62459191Skris return(ret); 62559191Skris } 62659191Skris 62768651Skrisstatic int conn_puts(BIO *bp, const char *str) 62855714Skris { 62955714Skris int n,ret; 63055714Skris 63155714Skris n=strlen(str); 63255714Skris ret=conn_write(bp,str,n); 63355714Skris return(ret); 63455714Skris } 63555714Skris 63655714SkrisBIO *BIO_new_connect(char *str) 63755714Skris { 63855714Skris BIO *ret; 63955714Skris 64055714Skris ret=BIO_new(BIO_s_connect()); 64155714Skris if (ret == NULL) return(NULL); 64255714Skris if (BIO_set_conn_hostname(ret,str)) 64355714Skris return(ret); 64455714Skris else 64555714Skris { 64655714Skris BIO_free(ret); 64755714Skris return(NULL); 64855714Skris } 64955714Skris } 65055714Skris 65155714Skris#endif 65255714Skris 653