+/*
+ * Dummy response that simply traces if back-ldap tried to send
+ * anything to the client
+ */
+static int
+ldap_chain_cb_response( Operation *op, SlapReply *rs )
+{
+ if ( rs->sr_type == REP_RESULT ) {
+ op->o_callback->sc_private = (void *)(1);
+
+ } else if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH )
+ {
+ /* strip the entryDN attribute, but keep returning results */
+ (void)ldap_chain_cb_search_response( op, rs );
+ }
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+ldap_chain_op(
+ Operation *op,
+ SlapReply *rs,
+ int ( *op_f )( Operation *op, SlapReply *rs ),
+ BerVarray ref )
+{
+ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
+ struct ldapinfo li, *lip = (struct ldapinfo *)on->on_bi.bi_private;
+ int rc;
+
+ if ( lip->url != NULL ) {
+ op->o_bd->be_private = on->on_bi.bi_private;
+ return ( *op_f )( op, rs );
+ }
+
+ li = *lip;
+ op->o_bd->be_private = &li;
+
+ /* if we parse the URI then by no means
+ * we can cache stuff or reuse connections,
+ * because in back-ldap there's no caching
+ * based on the URI value, which is supposed
+ * to be set once for all (correct?) */
+ op->o_do_not_cache = 1;
+
+ for ( ; !BER_BVISNULL( ref ); ref++ ) {
+ LDAPURLDesc *srv;
+ char *save_dn;
+
+ /* We're setting the URI of the first referral;
+ * what if there are more?
+
+Document: draft-ietf-ldapbis-protocol-27.txt
+
+4.1.10. Referral
+ ...
+ If the client wishes to progress the operation, it MUST follow the
+ referral by contacting one of the supported services. If multiple
+ URIs are present, the client assumes that any supported URI may be
+ used to progress the operation.
+
+ * so we actually need to follow exactly one,
+ * and we can assume any is fine.
+ */
+
+ /* parse reference and use
+ * proto://[host][:port]/ only */
+ rc = ldap_url_parse_ext( ref->bv_val, &srv );
+ if ( rc != LDAP_URL_SUCCESS ) {
+ /* try next */
+ rc = LDAP_OTHER;
+ continue;
+ }
+
+ /* remove DN essentially because later on
+ * ldap_initialize() will parse the URL
+ * as a comma-separated URL list */
+ save_dn = srv->lud_dn;
+ srv->lud_dn = "";
+ srv->lud_scope = LDAP_SCOPE_DEFAULT;
+ li.url = ldap_url_desc2str( srv );
+ srv->lud_dn = save_dn;
+ ldap_free_urldesc( srv );
+
+ if ( li.url == NULL ) {
+ /* try next */
+ rc = LDAP_OTHER;
+ continue;
+ }
+
+ rc = ( *op_f )( op, rs );
+
+ ldap_memfree( li.url );
+ li.url = NULL;
+
+ if ( rc == LDAP_SUCCESS && rs->sr_err == LDAP_SUCCESS ) {
+ break;
+ }
+ }
+
+ return rc;
+}
+