diff options
Diffstat (limited to 'crypto/bio/bss_conn.c')
-rw-r--r-- | crypto/bio/bss_conn.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c index dd43a406018ca..807a82b23ba2e 100644 --- a/crypto/bio/bss_conn.c +++ b/crypto/bio/bss_conn.c @@ -186,8 +186,17 @@ static int conn_state(BIO *b, BIO_CONNECT *c) case BIO_CONN_S_BLOCKED_CONNECT: i = BIO_sock_error(b->num); - if (i) { + if (i != 0) { BIO_clear_retry_flags(b); + if ((c->addr_iter = BIO_ADDRINFO_next(c->addr_iter)) != NULL) { + /* + * if there are more addresses to try, do that first + */ + BIO_closesocket(b->num); + c->state = BIO_CONN_S_CREATE_SOCKET; + ERR_clear_error(); + break; + } SYSerr(SYS_F_CONNECT, i); ERR_add_error_data(4, "hostname=", c->param_hostname, @@ -407,12 +416,13 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_C_SET_CONNECT: if (ptr != NULL) { b->init = 1; - if (num == 0) { + if (num == 0) { /* BIO_set_conn_hostname */ char *hold_service = data->param_service; /* We affect the hostname regardless. However, the input * string might contain a host:service spec, so we must * parse it, which might or might not affect the service */ + OPENSSL_free(data->param_hostname); data->param_hostname = NULL; ret = BIO_parse_hostserv(ptr, @@ -421,19 +431,29 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_PARSE_PRIO_HOST); if (hold_service != data->param_service) OPENSSL_free(hold_service); - } else if (num == 1) { + } else if (num == 1) { /* BIO_set_conn_port */ OPENSSL_free(data->param_service); - data->param_service = BUF_strdup(ptr); - } else if (num == 2) { + if ((data->param_service = OPENSSL_strdup(ptr)) == NULL) + ret = 0; + } else if (num == 2) { /* BIO_set_conn_address */ const BIO_ADDR *addr = (const BIO_ADDR *)ptr; + char *host = BIO_ADDR_hostname_string(addr, 1); + char *service = BIO_ADDR_service_string(addr, 1); + + ret = host != NULL && service != NULL; if (ret) { - data->param_hostname = BIO_ADDR_hostname_string(addr, 1); - data->param_service = BIO_ADDR_service_string(addr, 1); + OPENSSL_free(data->param_hostname); + data->param_hostname = host; + OPENSSL_free(data->param_service); + data->param_service = service; BIO_ADDRINFO_free(data->addr_first); data->addr_first = NULL; data->addr_iter = NULL; + } else { + OPENSSL_free(host); + OPENSSL_free(service); } - } else if (num == 3) { + } else if (num == 3) { /* BIO_set_conn_ip_family */ data->connect_family = *(int *)ptr; } else { ret = 0; |