+ /*
+ * This code figures out if we are going to chase a
+ * referral / search reference, or pass it back to the application
+ */
+ v3ref = 0; /* Assume not a V3 search reference or 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 = -1;
+ 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 arrary 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;
+#ifdef NEW_LOGGING
+ LDAP_LOG (( "result", LDAP_LEVEL_DETAIL1,
+ "read1msg: search ref chased,"
+ "mark request chasing refs, id = %d\n",
+ lr->lr_msgid ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "read1msg: search ref chased, mark request chasing refs, id = %d\n",
+ lr->lr_msgid, 0, 0);
+#endif
+ }
+ v3ref = 1; /* We sucessfully chased the reference */
+ }
+ }
+ }
+ } else {
+ /* Check for V3 referral */
+ ber_len_t len;
+ if ( ber_scanf( &tmpber, "{iaa",/*}*/ &lderr,
+ &lr->lr_res_matched, &lr->lr_res_error )
+ != LBER_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 = -1;
+ if( LDAP_BOOL_GET(&ld->ld_options, LDAP_BOOL_REFERRALS)
+ || (lr->lr_parent != NULL) )
+ {
+ v3ref = -1; /* Assume referral not chased and return it to app */
+ /* Get the referral list */
+ if( ber_scanf( &tmpber, "{v}", &refs) == LBER_ERROR) {
+ rc = LDAP_DECODING_ERROR;
+ lr->lr_status = LDAP_REQST_COMPLETED;
+#ifdef NEW_LOGGING
+ LDAP_LOG (( "result", LDAP_LEVEL_DETAIL1,
+ "read1msg: referral decode error,"
+ "mark request completed, id = %d\n",
+ lr->lr_msgid ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "read1msg: referral decode error, mark request completed, id = %d\n",
+ lr->lr_msgid, 0, 0);
+#endif
+ } 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;
+#ifdef NEW_LOGGING
+ LDAP_LOG (( "result", LDAP_LEVEL_DETAIL1,
+ "read1msg: referral chased,"
+ "mark request completed, id = %d\n",
+ lr->lr_msgid ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "read1msg: referral chased, mark request completed, id = %d\n",
+ lr->lr_msgid, 0, 0);
+#endif
+ if( refer_cnt > 0) {
+ v3ref = 1; /* Referral successfully chased */
+ }
+ }
+ }
+ }
+
+ 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 > -1) ) {
+ /* For a v3 search referral/reference, only come here if already chased it */