+ /*
+ * This code figures out if we are going to chase a
+ * referral / search reference, or pass it back to the application
+ */
+ v3ref = V3REF_NOREF; /* Assume not a V3 search reference/referral */
+ if( (tag != LDAP_RES_SEARCH_ENTRY) && (ld->ld_version > LDAP_VERSION2) ) {
+ BerElement tmpber = *ber; /* struct copy */
+ char **refs = NULL;
+
+ if( tag == LDAP_RES_SEARCH_REFERENCE ) {
+ /* This is a V3 search reference */
+ /* Assume we do not chase the reference,
+ * but pass it to application */
+ v3ref = V3REF_TOAPP;
+ if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS) ||
+ (lr->lr_parent != NULL) )
+ {
+ /* Get the referral list */
+ if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) {
+ rc = LDAP_DECODING_ERROR;
+ } else {
+ /* Note: refs array is freed by ldap_chase_v3referrals */
+ refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
+ 1, &lr->lr_res_error, &hadref );
+ if ( refer_cnt > 0 ) {
+ /* sucessfully chased reference */
+ /* If haven't got end search, set chasing referrals */
+ if( lr->lr_status != LDAP_REQST_COMPLETED) {
+ lr->lr_status = LDAP_REQST_CHASINGREFS;
+ Debug( LDAP_DEBUG_TRACE,
+ "read1msg: search ref chased, "
+ "mark request chasing refs, "
+ "id = %d\n",
+ lr->lr_msgid, 0, 0);
+ }
+
+ /* We sucessfully chased the reference */
+ v3ref = V3REF_SUCCESS;
+ }
+ }
+ }
+ } else {
+ /* Check for V3 referral */
+ ber_len_t len;
+ char *lr_res_error = NULL;
+
+ if ( ber_scanf( &tmpber, "{eaa",/*}*/ &lderr,
+ &lr->lr_res_matched, &lr_res_error )
+ != LBER_ERROR )
+ {
+ if ( lr_res_error != NULL ) {
+ if ( lr->lr_res_error != NULL ) {
+ (void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
+ LDAP_FREE( (char *)lr_res_error );
+
+ } else {
+ lr->lr_res_error = lr_res_error;
+ }
+ }
+
+ /* Check if V3 referral */
+ if ( ber_peek_tag( &tmpber, &len ) == LDAP_TAG_REFERRAL ) {
+ /* We have a V3 referral, assume we cannot chase it */
+ v3ref = V3REF_TOAPP;
+ if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS)
+ || (lr->lr_parent != NULL) )
+ {
+ /* Assume referral not chased and return it to app */
+ v3ref = V3REF_TOAPP;
+
+ /* Get the referral list */
+ if( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) {
+ rc = LDAP_DECODING_ERROR;
+ lr->lr_status = LDAP_REQST_COMPLETED;
+ Debug( LDAP_DEBUG_TRACE,
+ "read1msg: referral decode error, mark request completed, ld %p msgid %d\n",
+ ld, lr->lr_msgid, 0);
+ } else {
+ /* Chase the referral
+ * Note: refs arrary is freed by ldap_chase_v3referrals
+ */
+ refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
+ 0, &lr->lr_res_error, &hadref );
+ lr->lr_status = LDAP_REQST_COMPLETED;
+ Debug( LDAP_DEBUG_TRACE,
+ "read1msg: referral chased, mark request completed, ld %p msgid %d\n",
+ ld, lr->lr_msgid, 0);
+ if( refer_cnt > 0) {
+ /* Referral successfully chased */
+ v3ref = V3REF_SUCCESS;
+ }
+ }
+ }
+ }
+
+ if( lr->lr_res_matched != NULL ) {
+ LDAP_FREE( lr->lr_res_matched );
+ lr->lr_res_matched = NULL;
+ }
+ if( lr->lr_res_error != NULL ) {
+ LDAP_FREE( lr->lr_res_error );
+ lr->lr_res_error = NULL;
+ }
+ }
+ }
+ }
+
+ /* All results that just return a status, i.e. don't return data
+ * go through the following code. This code also chases V2 referrals
+ * and checks if all referrals have been chased.
+ */
+ if ( (tag != LDAP_RES_SEARCH_ENTRY) && (v3ref != V3REF_TOAPP) &&
+ (tag != LDAP_RES_INTERMEDIATE ))
+ {
+ /* For a v3 search referral/reference, only come here if already chased it */