From: Howard Chu Date: Fri, 15 Aug 2008 10:23:29 +0000 (+0000) Subject: Connect callbacks need error recovery checks X-Git-Tag: ACLCHECK_0~1422 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=baad2b249d32aa364f95cb80e917b13a0bcf48e7;p=openldap Connect callbacks need error recovery checks --- diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 62043d60cd..4b61a21245 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -531,6 +531,9 @@ LDAP_F (void) ldap_mark_select_clear( LDAP *ld, Sockbuf *sb ); LDAP_F (int) ldap_is_read_ready( LDAP *ld, Sockbuf *sb ); LDAP_F (int) ldap_is_write_ready( LDAP *ld, Sockbuf *sb ); +LDAP_F (int) ldap_int_connect_cbs( LDAP *ld, Sockbuf *sb, + ber_socket_t *s, const char *name, struct sockaddr *addr ); + /* * in os-local.c */ diff --git a/libraries/libldap/os-ip.c b/libraries/libldap/os-ip.c index 8946c0561f..bda0f18a22 100644 --- a/libraries/libldap/os-ip.c +++ b/libraries/libldap/os-ip.c @@ -424,6 +424,56 @@ ldap_pvt_inet_aton( const char *host, struct in_addr *in) } #endif +int +ldap_int_connect_cbs(LDAP *ld, Sockbuf *sb, ber_socket_t *s, const char *host, struct sockaddr *addr) +{ + struct ldapoptions *lo; + ldaplist *ll; + ldap_conncb *cb; + int rc; + + ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, s ); + + /* Invoke all handle-specific callbacks first */ + lo = &ld->ld_options; + for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { + cb = ll->ll_data; + rc = cb->lc_add( ld, sb, host, addr, cb ); + /* on any failure, call the teardown functions for anything + * that previously succeeded + */ + if ( rc ) { + ldaplist *l2; + for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { + cb = l2->ll_data; + cb->lc_del( ld, sb, cb ); + } + /* a failure might have implicitly closed the fd */ + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); + return rc; + } + } + lo = LDAP_INT_GLOBAL_OPT(); + for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { + cb = ll->ll_data; + rc = cb->lc_add( ld, sb, host, addr, cb ); + if ( rc ) { + ldaplist *l2; + for (l2 = lo->ldo_conn_cbs; l2 != ll; l2 = l2->ll_next) { + cb = l2->ll_data; + cb->lc_del( ld, sb, cb ); + } + lo = &ld->ld_options; + for (l2 = lo->ldo_conn_cbs; l2; l2 = l2->ll_next) { + cb = l2->ll_data; + cb->lc_del( ld, sb, cb ); + } + ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_FD, s ); + return rc; + } + } + return 0; +} int ldap_connect_to_host(LDAP *ld, Sockbuf *sb, @@ -537,20 +587,11 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, rc = ldap_pvt_connect( ld, s, sai->ai_addr, sai->ai_addrlen, async ); if ( rc == 0 || rc == -2 ) { - ldaplist *ll; - struct ldapoptions *lo; - ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s ); - lo = &ld->ld_options; - for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { - ldap_conncb *cb = ll->ll_data; - cb->lc_add( ld, sb, host, sai->ai_addr, cb ); - } - lo = LDAP_INT_GLOBAL_OPT(); - for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { - ldap_conncb *cb = ll->ll_data; - cb->lc_add( ld, sb, host, sai->ai_addr, cb ); - } - break; + err = ldap_int_connect_cbs( ld, sb, &s, host, sai->ai_addr ); + if ( err ) + rc = err; + else + break; } ldap_pvt_close_socket(ld, s); } @@ -621,20 +662,11 @@ ldap_connect_to_host(LDAP *ld, Sockbuf *sb, async); if ( (rc == 0) || (rc == -2) ) { - ldaplist *ll; - struct ldapoptions *lo; - ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, &s ); - lo = &ld->ld_options; - for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { - ldap_conncb *cb = ll->ll_data; - cb->lc_add( ld, sb, host, (struct sockaddr *)&sin, cb ); - } - lo = LDAP_INT_GLOBAL_OPT(); - for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { - ldap_conncb *cb = ll->ll_data; - cb->lc_add( ld, sb, host, (struct sockaddr *)&sin, cb ); - } - break; + i = ldap_int_connect_cbs( ld, sb, &s, host, (struct sockaddr *)&sin ); + if ( i ) + rc = i; + else + break; } ldap_pvt_close_socket(ld, s); diff --git a/libraries/libldap/os-local.c b/libraries/libldap/os-local.c index c0f21430bb..3a05f90c03 100644 --- a/libraries/libldap/os-local.c +++ b/libraries/libldap/os-local.c @@ -350,20 +350,12 @@ ldap_connect_to_path(LDAP *ld, Sockbuf *sb, const char *path, int async) rc = ldap_pvt_connect(ld, s, &server, async); if (rc == 0) { - ldaplist *ll; - struct ldapoptions *lo; - ber_sockbuf_ctrl( sb, LBER_SB_OPT_SET_FD, (void *)&s ); - lo = &ld->ld_options; - for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { - ldap_conncb *cb = ll->ll_data; - cb->lc_add( ld, sb, path, (struct sockaddr *)&server, cb ); - } - lo = LDAP_INT_GLOBAL_OPT(); - for (ll = lo->ldo_conn_cbs; ll; ll = ll->ll_next) { - ldap_conncb *cb = ll->ll_data; - cb->lc_add( ld, sb, path, (struct sockaddr *)&server, cb ); - } - } else { + int err; + err = ldap_int_connect_cbs( ld, sb, &s, path, (struct sockaddr *)&server ); + if ( err ) + rc = err; + } + if ( rc ) { ldap_pvt_close_socket(ld, s); } return rc;