Back to index

openldap  2.4.31
result.c
Go to the documentation of this file.
00001 /* result.c - routines to send ldap results, errors, and referrals */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 
00027 #include "portable.h"
00028 
00029 #include <stdio.h>
00030 
00031 #include <ac/socket.h>
00032 #include <ac/errno.h>
00033 #include <ac/string.h>
00034 #include <ac/ctype.h>
00035 #include <ac/time.h>
00036 #include <ac/unistd.h>
00037 
00038 #include "slap.h"
00039 
00040 const struct berval slap_dummy_bv = BER_BVNULL;
00041 
00042 int slap_null_cb( Operation *op, SlapReply *rs )
00043 {
00044        return 0;
00045 }
00046 
00047 int slap_freeself_cb( Operation *op, SlapReply *rs )
00048 {
00049        assert( op->o_callback != NULL );
00050 
00051        op->o_tmpfree( op->o_callback, op->o_tmpmemctx );
00052        op->o_callback = NULL;
00053 
00054        return SLAP_CB_CONTINUE;
00055 }
00056 
00057 static char *v2ref( BerVarray ref, const char *text )
00058 {
00059        size_t len = 0, i = 0;
00060        char *v2;
00061 
00062        if(ref == NULL) {
00063               if (text) {
00064                      return ch_strdup(text);
00065               } else {
00066                      return NULL;
00067               }
00068        }
00069        
00070        if ( text != NULL ) {
00071               len = strlen( text );
00072               if (text[len-1] != '\n') {
00073                   i = 1;
00074               }
00075        }
00076 
00077        v2 = ch_malloc( len+i+sizeof("Referral:") );
00078 
00079        if( text != NULL ) {
00080               strcpy(v2, text);
00081               if( i ) {
00082                      v2[len++] = '\n';
00083               }
00084        }
00085        strcpy( v2+len, "Referral:" );
00086        len += sizeof("Referral:");
00087 
00088        for( i=0; ref[i].bv_val != NULL; i++ ) {
00089               v2 = ch_realloc( v2, len + ref[i].bv_len + 1 );
00090               v2[len-1] = '\n';
00091               AC_MEMCPY(&v2[len], ref[i].bv_val, ref[i].bv_len );
00092               len += ref[i].bv_len;
00093               if (ref[i].bv_val[ref[i].bv_len-1] != '/') {
00094                      ++len;
00095               }
00096        }
00097 
00098        v2[len-1] = '\0';
00099        return v2;
00100 }
00101 
00102 ber_tag_t
00103 slap_req2res( ber_tag_t tag )
00104 {
00105        switch( tag ) {
00106        case LDAP_REQ_ADD:
00107        case LDAP_REQ_BIND:
00108        case LDAP_REQ_COMPARE:
00109        case LDAP_REQ_EXTENDED:
00110        case LDAP_REQ_MODIFY:
00111        case LDAP_REQ_MODRDN:
00112               tag++;
00113               break;
00114 
00115        case LDAP_REQ_DELETE:
00116               tag = LDAP_RES_DELETE;
00117               break;
00118 
00119        case LDAP_REQ_ABANDON:
00120        case LDAP_REQ_UNBIND:
00121               tag = LBER_SEQUENCE;
00122               break;
00123 
00124        case LDAP_REQ_SEARCH:
00125               tag = LDAP_RES_SEARCH_RESULT;
00126               break;
00127 
00128        default:
00129               tag = LBER_SEQUENCE;
00130        }
00131 
00132        return tag;
00133 }
00134 
00135 /* SlapReply debugging, prodo-slap.h overrides it in OpenLDAP releases */
00136 #if defined(LDAP_TEST) || (defined(USE_RS_ASSERT) && (USE_RS_ASSERT))
00137 
00138 int rs_suppress_assert = 0;
00139 
00140 /* RS_ASSERT() helper function */
00141 void rs_assert_(const char*file, unsigned line, const char*fn, const char*cond)
00142 {
00143        int no_assert = rs_suppress_assert, save_errno = errno;
00144        const char *s;
00145 
00146        if ( no_assert >= 0 ) {
00147               if ( no_assert == 0 && (s = getenv( "NO_RS_ASSERT" )) && *s ) {
00148                      no_assert = rs_suppress_assert = atoi( s );
00149               }
00150               if ( no_assert > 0 ) {
00151                      errno = save_errno;
00152                      return;
00153               }
00154        }
00155 
00156 #ifdef rs_assert_    /* proto-slap.h #defined away the fn parameter */
00157        fprintf( stderr,"%s:%u: "  "RS_ASSERT(%s) failed.\n", file,line,cond );
00158 #else
00159        fprintf( stderr,"%s:%u: %s: RS_ASSERT(%s) failed.\n", file,line,fn,cond );
00160 #endif
00161        fflush( stderr );
00162 
00163        errno = save_errno;
00164        /* $NO_RS_ASSERT > 0: ignore rs_asserts, 0: abort, < 0: just warn */
00165        if ( !no_assert /* from $NO_RS_ASSERT */ ) abort();
00166 }
00167 
00168 /* SlapReply is consistent */
00169 void
00170 (rs_assert_ok)( const SlapReply *rs )
00171 {
00172        const slap_mask_t flags = rs->sr_flags;
00173 
00174        if ( flags & REP_ENTRY_MASK ) {
00175               RS_ASSERT( !(flags & REP_ENTRY_MUSTRELEASE)
00176                      || !(flags & (REP_ENTRY_MASK ^ REP_ENTRY_MUSTRELEASE)) );
00177               RS_ASSERT( rs->sr_entry != NULL );
00178               RS_ASSERT( (1 << rs->sr_type) &
00179                      ((1 << REP_SEARCH) | (1 << REP_SEARCHREF) |
00180                       (1 << REP_RESULT) | (1 << REP_GLUE_RESULT)) );
00181        }
00182 #if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */
00183        if ( (flags & (REP_MATCHED_MASK | REP_REF_MASK | REP_CTRLS_MASK)) ) {
00184               RS_ASSERT( !(flags & REP_MATCHED_MASK) || rs->sr_matched );
00185               RS_ASSERT( !(flags & REP_CTRLS_MASK  ) || rs->sr_ctrls   );
00186               /* Note: LDAP_REFERRAL + !sr_ref is OK, becomes LDAP_NO_SUCH_OBJECT */
00187        }
00188 #if (USE_RS_ASSERT) > 2
00189        if ( rs->sr_err == LDAP_SUCCESS ) {
00190               RS_ASSERT( rs->sr_text == NULL );
00191               RS_ASSERT( rs->sr_matched == NULL );
00192        }
00193 #endif
00194 #endif
00195 }
00196 
00197 /* Ready for calling a new backend operation */
00198 void
00199 (rs_assert_ready)( const SlapReply *rs )
00200 {
00201        RS_ASSERT( !rs->sr_entry   );
00202 #if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */
00203        RS_ASSERT( !rs->sr_text    );
00204        RS_ASSERT( !rs->sr_ref     );
00205        RS_ASSERT( !rs->sr_matched );
00206        RS_ASSERT( !rs->sr_ctrls   );
00207        RS_ASSERT( !rs->sr_flags   );
00208 #if (USE_RS_ASSERT) > 2
00209        RS_ASSERT( rs->sr_err == LDAP_SUCCESS );
00210 #endif
00211 #else
00212        RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
00213 #endif
00214 }
00215 
00216 /* Backend operation done */
00217 void
00218 (rs_assert_done)( const SlapReply *rs )
00219 {
00220 #if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */
00221        RS_ASSERT( !(rs->sr_flags & ~(REP_ENTRY_MODIFIABLE|REP_NO_OPERATIONALS)) );
00222        rs_assert_ok( rs );
00223 #else
00224        RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) );
00225 #endif
00226 }
00227 
00228 #endif /* LDAP_TEST || USE_RS_ASSERT */
00229 
00230 /* Reset a used SlapReply whose contents has been flushed (freed/released) */
00231 void
00232 (rs_reinit)( SlapReply *rs, slap_reply_t type )
00233 {
00234        rs_reinit( rs, type );             /* proto-slap.h macro */
00235 }
00236 
00237 /* Obey and clear rs->sr_flags & REP_ENTRY_MASK.  Clear sr_entry if freed. */
00238 void
00239 rs_flush_entry( Operation *op, SlapReply *rs, slap_overinst *on )
00240 {
00241        rs_assert_ok( rs );
00242 
00243        if ( (rs->sr_flags & REP_ENTRY_MUSTFLUSH) && rs->sr_entry != NULL ) {
00244               if ( !(rs->sr_flags & REP_ENTRY_MUSTRELEASE) ) {
00245                      entry_free( rs->sr_entry );
00246               } else if ( on != NULL ) {
00247                      overlay_entry_release_ov( op, rs->sr_entry, 0, on );
00248               } else {
00249                      be_entry_release_rw( op, rs->sr_entry, 0 );
00250               }
00251               rs->sr_entry = NULL;
00252        }
00253 
00254        rs->sr_flags &= ~REP_ENTRY_MASK;
00255 }
00256 
00257 /* Set rs->sr_entry after obeying and clearing sr_flags & REP_ENTRY_MASK. */
00258 void
00259 rs_replace_entry( Operation *op, SlapReply *rs, slap_overinst *on, Entry *e )
00260 {
00261        rs_flush_entry( op, rs, on );
00262        rs->sr_entry = e;
00263 }
00264 
00265 /*
00266  * Ensure rs->sr_entry is modifiable, by duplicating it if necessary.
00267  * Obey sr_flags.  Set REP_ENTRY_<MODIFIABLE, and MUSTBEFREED if duplicated>.
00268  * Return nonzero if rs->sr_entry was replaced.
00269  */
00270 int
00271 rs_entry2modifiable( Operation *op, SlapReply *rs, slap_overinst *on )
00272 {
00273        if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) {
00274               rs_assert_ok( rs );
00275               return 0;
00276        }
00277        rs_replace_entry( op, rs, on, entry_dup( rs->sr_entry ));
00278        rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
00279        return 1;
00280 }
00281 
00282 static long send_ldap_ber(
00283        Operation *op,
00284        BerElement *ber )
00285 {
00286        Connection *conn = op->o_conn;
00287        ber_len_t bytes;
00288        long ret = 0;
00289 
00290        ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes );
00291 
00292        /* write only one pdu at a time - wait til it's our turn */
00293        ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
00294        if (( op->o_abandon && !op->o_cancel ) || !connection_valid( conn ) ||
00295               conn->c_writers < 0 ) {
00296               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
00297               return 0;
00298        }
00299 
00300        conn->c_writers++;
00301 
00302        while ( conn->c_writers > 0 && conn->c_writing ) {
00303               ldap_pvt_thread_cond_wait( &conn->c_write1_cv, &conn->c_write1_mutex );
00304        }
00305 
00306        /* connection was closed under us */
00307        if ( conn->c_writers < 0 ) {
00308               /* we're the last waiter, let the closer continue */
00309               if ( conn->c_writers == -1 )
00310                      ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
00311               conn->c_writers++;
00312               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
00313               return 0;
00314        }
00315 
00316        /* Our turn */
00317        conn->c_writing = 1;
00318 
00319        /* write the pdu */
00320        while( 1 ) {
00321               int err;
00322 
00323               /* lock the connection */ 
00324               if ( ldap_pvt_thread_mutex_trylock( &conn->c_mutex )) {
00325                      if ( !connection_valid(conn)) {
00326                             ret = 0;
00327                             break;
00328                      }
00329                      ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
00330                      ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
00331                      if ( conn->c_writers < 0 ) {
00332                             ret = 0;
00333                             break;
00334                      }
00335                      continue;
00336               }
00337 
00338               if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) {
00339                      ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
00340                      ret = bytes;
00341                      break;
00342               }
00343 
00344               err = sock_errno();
00345 
00346               /*
00347                * we got an error.  if it's ewouldblock, we need to
00348                * wait on the socket being writable.  otherwise, figure
00349                * it's a hard error and return.
00350                */
00351 
00352               Debug( LDAP_DEBUG_CONNS, "ber_flush2 failed errno=%d reason=\"%s\"\n",
00353                   err, sock_errstr(err), 0 );
00354 
00355               if ( err != EWOULDBLOCK && err != EAGAIN ) {
00356                      conn->c_writers--;
00357                      conn->c_writing = 0;
00358                      ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
00359                      connection_closing( conn, "connection lost on write" );
00360 
00361                      ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
00362                      return -1;
00363               }
00364 
00365               /* wait for socket to be write-ready */
00366               ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex );
00367               conn->c_writewaiter = 1;
00368               slapd_set_write( conn->c_sd, 2 );
00369 
00370               ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
00371               ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
00372               ldap_pvt_thread_pool_idle( &connection_pool );
00373               ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex );
00374               conn->c_writewaiter = 0;
00375               ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex );
00376               ldap_pvt_thread_pool_unidle( &connection_pool );
00377               ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex );
00378               if ( conn->c_writers < 0 ) {
00379                      ret = 0;
00380                      break;
00381               }
00382        }
00383 
00384        conn->c_writing = 0;
00385        if ( conn->c_writers < 0 ) {
00386               conn->c_writers++;
00387               if ( !conn->c_writers )
00388                      ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
00389        } else {
00390               conn->c_writers--;
00391               ldap_pvt_thread_cond_signal( &conn->c_write1_cv );
00392        }
00393        ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex );
00394 
00395        return ret;
00396 }
00397 
00398 static int
00399 send_ldap_control( BerElement *ber, LDAPControl *c )
00400 {
00401        int rc;
00402 
00403        assert( c != NULL );
00404 
00405        rc = ber_printf( ber, "{s" /*}*/, c->ldctl_oid );
00406 
00407        if( c->ldctl_iscritical ) {
00408               rc = ber_printf( ber, "b",
00409                      (ber_int_t) c->ldctl_iscritical ) ;
00410               if( rc == -1 ) return rc;
00411        }
00412 
00413        if( c->ldctl_value.bv_val != NULL ) {
00414               rc = ber_printf( ber, "O", &c->ldctl_value ); 
00415               if( rc == -1 ) return rc;
00416        }
00417 
00418        rc = ber_printf( ber, /*{*/"N}" );
00419        if( rc == -1 ) return rc;
00420 
00421        return 0;
00422 }
00423 
00424 static int
00425 send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c )
00426 {
00427        int rc;
00428 
00429        if( c == NULL )
00430               return 0;
00431 
00432        rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS );
00433        if( rc == -1 ) return rc;
00434 
00435        for( ; *c != NULL; c++) {
00436               rc = send_ldap_control( ber, *c );
00437               if( rc == -1 ) return rc;
00438        }
00439 
00440 #ifdef SLAP_CONTROL_X_SORTEDRESULTS
00441        /* this is a hack to avoid having to modify op->s_ctrls */
00442        if( o->o_sortedresults ) {
00443               BerElementBuffer berbuf;
00444               BerElement *sber = (BerElement *) &berbuf;
00445               LDAPControl sorted;
00446               BER_BVZERO( &sorted.ldctl_value );
00447               sorted.ldctl_oid = LDAP_CONTROL_SORTRESPONSE;
00448               sorted.ldctl_iscritical = 0;
00449 
00450               ber_init2( sber, NULL, LBER_USE_DER );
00451 
00452               ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM );
00453 
00454               if( ber_flatten2( sber, &sorted.ldctl_value, 0 ) == -1 ) {
00455                      return -1;
00456               }
00457 
00458               (void) ber_free_buf( sber );
00459 
00460               rc = send_ldap_control( ber, &sorted );
00461               if( rc == -1 ) return rc;
00462        }
00463 #endif
00464 
00465        rc = ber_printf( ber, /*{*/"N}" );
00466 
00467        return rc;
00468 }
00469 
00470 /*
00471  * slap_response_play()
00472  *
00473  * plays the callback list; rationale: a callback can
00474  *   - remove itself from the list, by setting op->o_callback = NULL;
00475  *     malloc()'ed callbacks should free themselves from inside the
00476  *     sc_response() function.
00477  *   - replace itself with another (list of) callback(s), by setting
00478  *     op->o_callback = a new (list of) callback(s); in this case, it
00479  *     is the callback's responsibility to to append existing subsequent
00480  *     callbacks to the end of the list that is passed to the sc_response()
00481  *     function.
00482  *   - modify the list of subsequent callbacks by modifying the value
00483  *     of the sc_next field from inside the sc_response() function; this
00484  *     case does not require any handling from inside slap_response_play()
00485  *
00486  * To stop execution of the playlist, the sc_response() function must return
00487  * a value different from SLAP_SC_CONTINUE.
00488  *
00489  * The same applies to slap_cleanup_play(); only, there is no means to stop
00490  * execution of the playlist, since all cleanup functions must be called.
00491  */
00492 static int
00493 slap_response_play(
00494        Operation *op,
00495        SlapReply *rs )
00496 {
00497        int rc;
00498 
00499        slap_callback *sc = op->o_callback, **scp;
00500 
00501        rc = SLAP_CB_CONTINUE;
00502        for ( scp = &sc; *scp; ) {
00503               slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next;
00504 
00505               op->o_callback = *scp;
00506               if ( op->o_callback->sc_response ) {
00507                      rc = op->o_callback->sc_response( op, rs );
00508                      if ( op->o_callback == NULL ) {
00509                             /* the callback has been removed;
00510                              * repair the list */
00511                             *scp = sc_next;
00512                             sc_nextp = scp;
00513 
00514                      } else if ( op->o_callback != *scp ) {
00515                             /* a new callback has been inserted
00516                              * in place of the existing one; repair the list */
00517                             *scp = op->o_callback;
00518                             sc_nextp = scp;
00519                      }
00520                      if ( rc != SLAP_CB_CONTINUE ) break;
00521               }
00522               scp = sc_nextp;
00523        }
00524 
00525        op->o_callback = sc;
00526        return rc;
00527 }
00528 
00529 static int
00530 slap_cleanup_play(
00531        Operation *op,
00532        SlapReply *rs )
00533 {
00534        slap_callback *sc = op->o_callback, **scp;
00535 
00536        for ( scp = &sc; *scp; ) {
00537               slap_callback *sc_next = (*scp)->sc_next, **sc_nextp = &(*scp)->sc_next;
00538 
00539               op->o_callback = *scp;
00540               if ( op->o_callback->sc_cleanup ) {
00541                      (void)op->o_callback->sc_cleanup( op, rs );
00542                      if ( op->o_callback == NULL ) {
00543                             /* the callback has been removed;
00544                              * repair the list */
00545                             *scp = sc_next;
00546                             sc_nextp = scp;
00547 
00548                      } else if ( op->o_callback != *scp ) {
00549                             /* a new callback has been inserted
00550                              * after the existing one; repair the list */
00551                             /* a new callback has been inserted
00552                              * in place of the existing one; repair the list */
00553                             *scp = op->o_callback;
00554                             sc_nextp = scp;
00555                      }
00556                      /* don't care about the result; do all cleanup */
00557               }
00558               scp = sc_nextp;
00559        }
00560 
00561        op->o_callback = sc;
00562        return LDAP_SUCCESS;
00563 }
00564 
00565 static int
00566 send_ldap_response(
00567        Operation *op,
00568        SlapReply *rs )
00569 {
00570        BerElementBuffer berbuf;
00571        BerElement    *ber = (BerElement *) &berbuf;
00572        int           rc = LDAP_SUCCESS;
00573        long   bytes;
00574 
00575        /* op was actually aborted, bypass everything if client didn't Cancel */
00576        if (( rs->sr_err == SLAPD_ABANDON ) && !op->o_cancel ) {
00577               rc = SLAPD_ABANDON;
00578               goto clean2;
00579        }
00580 
00581        if ( op->o_callback ) {
00582               rc = slap_response_play( op, rs );
00583               if ( rc != SLAP_CB_CONTINUE ) {
00584                      goto clean2;
00585               }
00586        }
00587 
00588        /* op completed, connection aborted, bypass sending response */
00589        if ( op->o_abandon && !op->o_cancel ) {
00590               rc = SLAPD_ABANDON;
00591               goto clean2;
00592        }
00593 
00594 #ifdef LDAP_CONNECTIONLESS
00595        if (op->o_conn && op->o_conn->c_is_udp)
00596               ber = op->o_res_ber;
00597        else
00598 #endif
00599        {
00600               ber_init_w_nullc( ber, LBER_USE_DER );
00601               ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
00602        }
00603 
00604        rc = rs->sr_err;
00605        if ( rc == SLAPD_ABANDON && op->o_cancel )
00606               rc = LDAP_CANCELLED;
00607 
00608        Debug( LDAP_DEBUG_TRACE,
00609               "send_ldap_response: msgid=%d tag=%lu err=%d\n",
00610               rs->sr_msgid, rs->sr_tag, rc );
00611 
00612        if( rs->sr_ref ) {
00613               Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n",
00614                      rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
00615                      NULL, NULL );
00616        }
00617 
00618 #ifdef LDAP_CONNECTIONLESS
00619        if (op->o_conn && op->o_conn->c_is_udp &&
00620               op->o_protocol == LDAP_VERSION2 )
00621        {
00622               rc = ber_printf( ber, "t{ess" /*"}"*/,
00623                      rs->sr_tag, rc,
00624               rs->sr_matched == NULL ? "" : rs->sr_matched,
00625               rs->sr_text == NULL ? "" : rs->sr_text );
00626        } else 
00627 #endif
00628        if ( rs->sr_type == REP_INTERMEDIATE ) {
00629            rc = ber_printf( ber, "{it{" /*"}}"*/,
00630                      rs->sr_msgid, rs->sr_tag );
00631 
00632        } else {
00633            rc = ber_printf( ber, "{it{ess" /*"}}"*/,
00634               rs->sr_msgid, rs->sr_tag, rc,
00635               rs->sr_matched == NULL ? "" : rs->sr_matched,
00636               rs->sr_text == NULL ? "" : rs->sr_text );
00637        }
00638 
00639        if( rc != -1 ) {
00640               if ( rs->sr_ref != NULL ) {
00641                      assert( rs->sr_err == LDAP_REFERRAL );
00642                      rc = ber_printf( ber, "t{W}",
00643                             LDAP_TAG_REFERRAL, rs->sr_ref );
00644               } else {
00645                      assert( rs->sr_err != LDAP_REFERRAL );
00646               }
00647        }
00648 
00649        if( rc != -1 && rs->sr_type == REP_SASL && rs->sr_sasldata != NULL ) {
00650               rc = ber_printf( ber, "tO",
00651                      LDAP_TAG_SASL_RES_CREDS, rs->sr_sasldata );
00652        }
00653 
00654        if( rc != -1 &&
00655               ( rs->sr_type == REP_EXTENDED || rs->sr_type == REP_INTERMEDIATE ))
00656        {
00657               if ( rs->sr_rspoid != NULL ) {
00658                      rc = ber_printf( ber, "ts",
00659                             rs->sr_type == REP_EXTENDED
00660                                    ? LDAP_TAG_EXOP_RES_OID : LDAP_TAG_IM_RES_OID,
00661                             rs->sr_rspoid );
00662               }
00663               if( rc != -1 && rs->sr_rspdata != NULL ) {
00664                      rc = ber_printf( ber, "tO",
00665                             rs->sr_type == REP_EXTENDED
00666                                    ? LDAP_TAG_EXOP_RES_VALUE : LDAP_TAG_IM_RES_VALUE,
00667                             rs->sr_rspdata );
00668               }
00669        }
00670 
00671        if( rc != -1 ) {
00672               rc = ber_printf( ber, /*"{"*/ "N}" );
00673        }
00674 
00675        if( rc != -1 ) {
00676               rc = send_ldap_controls( op, ber, rs->sr_ctrls );
00677        }
00678 
00679        if( rc != -1 ) {
00680               rc = ber_printf( ber, /*"{"*/ "N}" );
00681        }
00682 
00683 #ifdef LDAP_CONNECTIONLESS
00684        if( op->o_conn && op->o_conn->c_is_udp && op->o_protocol == LDAP_VERSION2
00685               && rc != -1 )
00686        {
00687               rc = ber_printf( ber, /*"{"*/ "N}" );
00688        }
00689 #endif
00690               
00691        if ( rc == -1 ) {
00692               Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
00693 
00694 #ifdef LDAP_CONNECTIONLESS
00695               if (!op->o_conn || op->o_conn->c_is_udp == 0)
00696 #endif
00697               {
00698                      ber_free_buf( ber );
00699               }
00700               goto cleanup;
00701        }
00702 
00703        /* send BER */
00704        bytes = send_ldap_ber( op, ber );
00705 #ifdef LDAP_CONNECTIONLESS
00706        if (!op->o_conn || op->o_conn->c_is_udp == 0)
00707 #endif
00708        {
00709               ber_free_buf( ber );
00710        }
00711 
00712        if ( bytes < 0 ) {
00713               Debug( LDAP_DEBUG_ANY,
00714                      "send_ldap_response: ber write failed\n",
00715                      0, 0, 0 );
00716 
00717               goto cleanup;
00718        }
00719 
00720        ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
00721        ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
00722        ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
00723        ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
00724 
00725 cleanup:;
00726        /* Tell caller that we did this for real, as opposed to being
00727         * overridden by a callback
00728         */
00729        rc = SLAP_CB_CONTINUE;
00730 
00731 clean2:;
00732        if ( op->o_callback ) {
00733               (void)slap_cleanup_play( op, rs );
00734        }
00735 
00736        if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
00737               rs->sr_flags ^= REP_MATCHED_MUSTBEFREED; /* paranoia */
00738               if ( rs->sr_matched ) {
00739                      free( (char *)rs->sr_matched );
00740                      rs->sr_matched = NULL;
00741               }
00742        }
00743 
00744        if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
00745               rs->sr_flags ^= REP_REF_MUSTBEFREED; /* paranoia */
00746               if ( rs->sr_ref ) {
00747                      ber_bvarray_free( rs->sr_ref );
00748                      rs->sr_ref = NULL;
00749               }
00750        }
00751 
00752        if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
00753               rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
00754               if ( rs->sr_ctrls ) {
00755                      slap_free_ctrls( op, rs->sr_ctrls );
00756                      rs->sr_ctrls = NULL;
00757               }
00758        }
00759 
00760        return rc;
00761 }
00762 
00763 
00764 void
00765 send_ldap_disconnect( Operation    *op, SlapReply *rs )
00766 {
00767 #define LDAP_UNSOLICITED_ERROR(e) \
00768        (  (e) == LDAP_PROTOCOL_ERROR \
00769        || (e) == LDAP_STRONG_AUTH_REQUIRED \
00770        || (e) == LDAP_UNAVAILABLE )
00771 
00772        Debug( LDAP_DEBUG_TRACE,
00773               "send_ldap_disconnect %d:%s\n",
00774               rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL );
00775        assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) );
00776 
00777        /* TODO: Flush the entry if sr_type == REP_SEARCH/REP_SEARCHREF? */
00778        RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
00779        rs->sr_flags &= ~REP_ENTRY_MASK;   /* paranoia */
00780 
00781        rs->sr_type = REP_EXTENDED;
00782        rs->sr_rspdata = NULL;
00783 
00784        if ( op->o_protocol < LDAP_VERSION3 ) {
00785               rs->sr_rspoid = NULL;
00786               rs->sr_tag = slap_req2res( op->o_tag );
00787               rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
00788 
00789        } else {
00790               rs->sr_rspoid = LDAP_NOTICE_DISCONNECT;
00791               rs->sr_tag = LDAP_RES_EXTENDED;
00792               rs->sr_msgid = LDAP_RES_UNSOLICITED;
00793        }
00794 
00795        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
00796               Statslog( LDAP_DEBUG_STATS,
00797                      "%s DISCONNECT tag=%lu err=%d text=%s\n",
00798                      op->o_log_prefix, rs->sr_tag, rs->sr_err,
00799                      rs->sr_text ? rs->sr_text : "", 0 );
00800        }
00801 }
00802 
00803 void
00804 slap_send_ldap_result( Operation *op, SlapReply *rs )
00805 {
00806        char *tmp = NULL;
00807        const char *otext = rs->sr_text;
00808        BerVarray oref = rs->sr_ref;
00809 
00810        rs->sr_type = REP_RESULT;
00811 
00812        /* Propagate Abandons so that cleanup callbacks can be processed */
00813        if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon )
00814               goto abandon;
00815 
00816        Debug( LDAP_DEBUG_TRACE,
00817               "send_ldap_result: %s p=%d\n",
00818               op->o_log_prefix, op->o_protocol, 0 );
00819        Debug( LDAP_DEBUG_ARGS,
00820               "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n",
00821               rs->sr_err, rs->sr_matched ? rs->sr_matched : "",
00822               rs->sr_text ? rs->sr_text : "" );
00823        if( rs->sr_ref ) {
00824               Debug( LDAP_DEBUG_ARGS,
00825                      "send_ldap_result: referral=\"%s\"\n",
00826                      rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL",
00827                      NULL, NULL );
00828        }
00829        assert( !LDAP_API_ERROR( rs->sr_err ) );
00830        assert( rs->sr_err != LDAP_PARTIAL_RESULTS );
00831 
00832        if ( rs->sr_err == LDAP_REFERRAL ) {
00833               if( op->o_domain_scope ) rs->sr_ref = NULL;
00834 
00835               if( rs->sr_ref == NULL ) {
00836                      rs->sr_err = LDAP_NO_SUCH_OBJECT;
00837               } else if ( op->o_protocol < LDAP_VERSION3 ) {
00838                      rs->sr_err = LDAP_PARTIAL_RESULTS;
00839               }
00840        }
00841 
00842        if ( op->o_protocol < LDAP_VERSION3 ) {
00843               tmp = v2ref( rs->sr_ref, rs->sr_text );
00844               rs->sr_text = tmp;
00845               rs->sr_ref = NULL;
00846        }
00847 
00848 abandon:
00849        rs->sr_tag = slap_req2res( op->o_tag );
00850        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
00851 
00852        if ( rs->sr_flags & REP_REF_MUSTBEFREED ) {
00853               if ( rs->sr_ref == NULL ) {
00854                      rs->sr_flags ^= REP_REF_MUSTBEFREED;
00855                      ber_bvarray_free( oref );
00856               }
00857               oref = NULL; /* send_ldap_response() will free rs->sr_ref if != NULL */
00858        }
00859 
00860        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
00861               if ( op->o_tag == LDAP_REQ_SEARCH ) {
00862                      Statslog( LDAP_DEBUG_STATS,
00863                             "%s SEARCH RESULT tag=%lu err=%d nentries=%d text=%s\n",
00864                             op->o_log_prefix, rs->sr_tag, rs->sr_err,
00865                             rs->sr_nentries, rs->sr_text ? rs->sr_text : "" );
00866               } else {
00867                      Statslog( LDAP_DEBUG_STATS,
00868                             "%s RESULT tag=%lu err=%d text=%s\n",
00869                             op->o_log_prefix, rs->sr_tag, rs->sr_err,
00870                             rs->sr_text ? rs->sr_text : "", 0 );
00871               }
00872        }
00873 
00874        if( tmp != NULL ) ch_free(tmp);
00875        rs->sr_text = otext;
00876        rs->sr_ref = oref;
00877 }
00878 
00879 void
00880 send_ldap_sasl( Operation *op, SlapReply *rs )
00881 {
00882        Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n",
00883               rs->sr_err,
00884               rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL );
00885 
00886        RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
00887        rs->sr_flags &= ~REP_ENTRY_MASK;   /* paranoia */
00888 
00889        rs->sr_type = REP_SASL;
00890        rs->sr_tag = slap_req2res( op->o_tag );
00891        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
00892 
00893        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
00894               Statslog( LDAP_DEBUG_STATS,
00895                      "%s RESULT tag=%lu err=%d text=%s\n",
00896                      op->o_log_prefix, rs->sr_tag, rs->sr_err,
00897                      rs->sr_text ? rs->sr_text : "", 0 );
00898        }
00899 }
00900 
00901 void
00902 slap_send_ldap_extended( Operation *op, SlapReply *rs )
00903 {
00904        Debug( LDAP_DEBUG_TRACE,
00905               "send_ldap_extended: err=%d oid=%s len=%ld\n",
00906               rs->sr_err,
00907               rs->sr_rspoid ? rs->sr_rspoid : "",
00908               rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
00909 
00910        RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
00911        rs->sr_flags &= ~REP_ENTRY_MASK;   /* paranoia */
00912 
00913        rs->sr_type = REP_EXTENDED;
00914        rs->sr_tag = slap_req2res( op->o_tag );
00915        rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0;
00916 
00917        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
00918               Statslog( LDAP_DEBUG_STATS,
00919                      "%s RESULT oid=%s err=%d text=%s\n",
00920                      op->o_log_prefix, rs->sr_rspoid ? rs->sr_rspoid : "",
00921                      rs->sr_err, rs->sr_text ? rs->sr_text : "", 0 );
00922        }
00923 }
00924 
00925 void
00926 slap_send_ldap_intermediate( Operation *op, SlapReply *rs )
00927 {
00928        Debug( LDAP_DEBUG_TRACE,
00929               "send_ldap_intermediate: err=%d oid=%s len=%ld\n",
00930               rs->sr_err,
00931               rs->sr_rspoid ? rs->sr_rspoid : "",
00932               rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 );
00933 
00934        RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) );
00935        rs->sr_flags &= ~REP_ENTRY_MASK;   /* paranoia */
00936 
00937        rs->sr_type = REP_INTERMEDIATE;
00938        rs->sr_tag = LDAP_RES_INTERMEDIATE;
00939        rs->sr_msgid = op->o_msgid;
00940        if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) {
00941               Statslog( LDAP_DEBUG_STATS2,
00942                      "%s INTERM oid=%s\n",
00943                      op->o_log_prefix,
00944                      rs->sr_rspoid ? rs->sr_rspoid : "", 0, 0, 0 );
00945        }
00946 }
00947 
00948 /*
00949  * returns:
00950  *
00951  * LDAP_SUCCESS                    entry sent
00952  * LDAP_OTHER               entry not sent (other)
00953  * LDAP_INSUFFICIENT_ACCESS entry not sent (ACL)
00954  * LDAP_UNAVAILABLE         entry not sent (connection closed)
00955  * LDAP_SIZELIMIT_EXCEEDED  entry not sent (caller must send sizelimitExceeded)
00956  */
00957 
00958 int
00959 slap_send_search_entry( Operation *op, SlapReply *rs )
00960 {
00961        BerElementBuffer berbuf;
00962        BerElement    *ber = (BerElement *) &berbuf;
00963        Attribute     *a;
00964        int           i, j, rc = LDAP_UNAVAILABLE, bytes;
00965        int           userattrs;
00966        AccessControlState acl_state = ACL_STATE_INIT;
00967        int                   attrsonly;
00968        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
00969 
00970        /* a_flags: array of flags telling if the i-th element will be
00971         *          returned or filtered out
00972         * e_flags: array of a_flags
00973         */
00974        char **e_flags = NULL;
00975 
00976        rs->sr_type = REP_SEARCH;
00977 
00978        if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) {
00979               rc = LDAP_SIZELIMIT_EXCEEDED;
00980               goto error_return;
00981        }
00982 
00983        /* Every 64 entries, check for thread pool pause */
00984        if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) &&
00985               ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 )
00986        {
00987               rc = LDAP_BUSY;
00988               goto error_return;
00989        }
00990 
00991        /* eventually will loop through generated operational attribute types
00992         * currently implemented types include:
00993         *     entryDN, subschemaSubentry, and hasSubordinates */
00994        /* NOTE: moved before overlays callback circling because
00995         * they may modify entry and other stuff in rs */
00996        /* check for special all operational attributes ("+") type */
00997        /* FIXME: maybe we could set this flag at the operation level;
00998         * however, in principle the caller of send_search_entry() may
00999         * change the attribute list at each call */
01000        rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );
01001 
01002        rc = backend_operational( op, rs );
01003        if ( rc ) {
01004               goto error_return;
01005        }
01006 
01007        if ( op->o_callback ) {
01008               rc = slap_response_play( op, rs );
01009               if ( rc != SLAP_CB_CONTINUE ) {
01010                      goto error_return;
01011               }
01012        }
01013 
01014        Debug( LDAP_DEBUG_TRACE, "=> send_search_entry: conn %lu dn=\"%s\"%s\n",
01015               op->o_connid, rs->sr_entry->e_name.bv_val,
01016               op->ors_attrsonly ? " (attrsOnly)" : "" );
01017 
01018        attrsonly = op->ors_attrsonly;
01019 
01020        if ( !access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL )) {
01021               Debug( LDAP_DEBUG_ACL,
01022                      "send_search_entry: conn %lu access to entry (%s) not allowed\n", 
01023                      op->o_connid, rs->sr_entry->e_name.bv_val, 0 );
01024 
01025               rc = LDAP_INSUFFICIENT_ACCESS;
01026               goto error_return;
01027        }
01028 
01029        if ( op->o_res_ber ) {
01030               /* read back control or LDAP_CONNECTIONLESS */
01031            ber = op->o_res_ber;
01032        } else {
01033               struct berval bv;
01034 
01035               bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
01036               bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );
01037 
01038               ber_init2( ber, &bv, LBER_USE_DER );
01039               ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
01040        }
01041 
01042 #ifdef LDAP_CONNECTIONLESS
01043        if ( op->o_conn && op->o_conn->c_is_udp ) {
01044               /* CONNECTIONLESS */
01045               if ( op->o_protocol == LDAP_VERSION2 ) {
01046               rc = ber_printf(ber, "t{O{" /*}}*/,
01047                             LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
01048               } else {
01049               rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
01050                             LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
01051               }
01052        } else
01053 #endif
01054        if ( op->o_res_ber ) {
01055               /* read back control */
01056            rc = ber_printf( ber, "t{O{" /*}}*/,
01057                      LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
01058        } else {
01059            rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid,
01060                      LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name );
01061        }
01062 
01063        if ( rc == -1 ) {
01064               Debug( LDAP_DEBUG_ANY, 
01065                      "send_search_entry: conn %lu  ber_printf failed\n", 
01066                      op->o_connid, 0, 0 );
01067 
01068               if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01069               send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" );
01070               rc = rs->sr_err;
01071               goto error_return;
01072        }
01073 
01074        /* check for special all user attributes ("*") type */
01075        userattrs = SLAP_USERATTRS( rs->sr_attr_flags );
01076 
01077        /* create an array of arrays of flags. Each flag corresponds
01078         * to particular value of attribute and equals 1 if value matches
01079         * to ValuesReturnFilter or 0 if not
01080         */    
01081        if ( op->o_vrFilter != NULL ) {
01082               int    k = 0;
01083               size_t size;
01084 
01085               for ( a = rs->sr_entry->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
01086                      for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
01087               }
01088 
01089               size = i * sizeof(char *) + k;
01090               if ( size > 0 ) {
01091                      char   *a_flags;
01092                      e_flags = slap_sl_calloc ( 1, i * sizeof(char *) + k, op->o_tmpmemctx );
01093                      if( e_flags == NULL ) {
01094                      Debug( LDAP_DEBUG_ANY, 
01095                                    "send_search_entry: conn %lu slap_sl_calloc failed\n",
01096                                    op->o_connid, 0, 0 );
01097                             ber_free( ber, 1 );
01098        
01099                             send_ldap_error( op, rs, LDAP_OTHER, "out of memory" );
01100                             goto error_return;
01101                      }
01102                      a_flags = (char *)(e_flags + i);
01103                      memset( a_flags, 0, k );
01104                      for ( a=rs->sr_entry->e_attrs, i=0; a != NULL; a=a->a_next, i++ ) {
01105                             for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
01106                             e_flags[i] = a_flags;
01107                             a_flags += j;
01108                      }
01109        
01110                      rc = filter_matched_values(op, rs->sr_entry->e_attrs, &e_flags) ; 
01111                      if ( rc == -1 ) {
01112                             Debug( LDAP_DEBUG_ANY, "send_search_entry: "
01113                                    "conn %lu matched values filtering failed\n",
01114                                    op->o_connid, 0, 0 );
01115                             if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01116                             send_ldap_error( op, rs, LDAP_OTHER,
01117                                    "matched values filtering error" );
01118                             rc = rs->sr_err;
01119                             goto error_return;
01120                      }
01121               }
01122        }
01123 
01124        for ( a = rs->sr_entry->e_attrs, j = 0; a != NULL; a = a->a_next, j++ ) {
01125               AttributeDescription *desc = a->a_desc;
01126               int finish = 0;
01127 
01128               if ( rs->sr_attrs == NULL ) {
01129                      /* all user attrs request, skip operational attributes */
01130                      if( is_at_operational( desc->ad_type ) ) {
01131                             continue;
01132                      }
01133 
01134               } else {
01135                      /* specific attrs requested */
01136                      if ( is_at_operational( desc->ad_type ) ) {
01137                             /* if not explicitly requested */
01138                             if ( !ad_inlist( desc, rs->sr_attrs )) {
01139                                    /* if not all op attrs requested, skip */
01140                                    if ( !SLAP_OPATTRS( rs->sr_attr_flags ))
01141                                           continue;
01142                                    /* if DSA-specific and replicating, skip */
01143                                    if ( op->o_sync != SLAP_CONTROL_NONE &&
01144                                           desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION )
01145                                           continue;
01146                             }
01147                      } else {
01148                             if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
01149                                    continue;
01150                             }
01151                      }
01152               }
01153 
01154               if ( attrsonly ) {
01155                      if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
01156                             ACL_READ, &acl_state ) )
01157                      {
01158                             Debug( LDAP_DEBUG_ACL, "send_search_entry: "
01159                                    "conn %lu access to attribute %s not allowed\n",
01160                                     op->o_connid, desc->ad_cname.bv_val, 0 );
01161                             continue;
01162                      }
01163 
01164                      if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
01165                             Debug( LDAP_DEBUG_ANY, 
01166                                    "send_search_entry: conn %lu  ber_printf failed\n", 
01167                                    op->o_connid, 0, 0 );
01168 
01169                             if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01170                             send_ldap_error( op, rs, LDAP_OTHER,
01171                                    "encoding description error");
01172                             rc = rs->sr_err;
01173                             goto error_return;
01174                      }
01175                      finish = 1;
01176 
01177               } else {
01178                      int first = 1;
01179                      for ( i = 0; a->a_nvals[i].bv_val != NULL; i++ ) {
01180                             if ( ! access_allowed( op, rs->sr_entry,
01181                                    desc, &a->a_nvals[i], ACL_READ, &acl_state ) )
01182                             {
01183                                    Debug( LDAP_DEBUG_ACL,
01184                                           "send_search_entry: conn %lu "
01185                                           "access to attribute %s, value #%d not allowed\n",
01186                                           op->o_connid, desc->ad_cname.bv_val, i );
01187 
01188                                    continue;
01189                             }
01190 
01191                             if ( op->o_vrFilter && e_flags[j][i] == 0 ){
01192                                    continue;
01193                             }
01194 
01195                             if ( first ) {
01196                                    first = 0;
01197                                    finish = 1;
01198                                    if (( rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname )) == -1 ) {
01199                                           Debug( LDAP_DEBUG_ANY,
01200                                                  "send_search_entry: conn %lu  ber_printf failed\n", 
01201                                                  op->o_connid, 0, 0 );
01202 
01203                                           if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01204                                           send_ldap_error( op, rs, LDAP_OTHER,
01205                                                  "encoding description error");
01206                                           rc = rs->sr_err;
01207                                           goto error_return;
01208                                    }
01209                             }
01210                             if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
01211                                    Debug( LDAP_DEBUG_ANY,
01212                                           "send_search_entry: conn %lu  "
01213                                           "ber_printf failed.\n", op->o_connid, 0, 0 );
01214 
01215                                    if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01216                                    send_ldap_error( op, rs, LDAP_OTHER,
01217                                           "encoding values error" );
01218                                    rc = rs->sr_err;
01219                                    goto error_return;
01220                             }
01221                      }
01222               }
01223 
01224               if ( finish && ( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
01225                      Debug( LDAP_DEBUG_ANY,
01226                             "send_search_entry: conn %lu ber_printf failed\n", 
01227                             op->o_connid, 0, 0 );
01228 
01229                      if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01230                      send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
01231                      rc = rs->sr_err;
01232                      goto error_return;
01233               }
01234        }
01235 
01236        /* NOTE: moved before overlays callback circling because
01237         * they may modify entry and other stuff in rs */
01238        if ( rs->sr_operational_attrs != NULL && op->o_vrFilter != NULL ) {
01239               int    k = 0;
01240               size_t size;
01241 
01242               for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
01243                      for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
01244               }
01245 
01246               size = i * sizeof(char *) + k;
01247               if ( size > 0 ) {
01248                      char   *a_flags, **tmp;
01249               
01250                      /*
01251                       * Reuse previous memory - we likely need less space
01252                       * for operational attributes
01253                       */
01254                      tmp = slap_sl_realloc( e_flags, i * sizeof(char *) + k,
01255                             op->o_tmpmemctx );
01256                      if ( tmp == NULL ) {
01257                             Debug( LDAP_DEBUG_ANY,
01258                                    "send_search_entry: conn %lu "
01259                                    "not enough memory "
01260                                    "for matched values filtering\n",
01261                                    op->o_connid, 0, 0 );
01262                             if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01263                             send_ldap_error( op, rs, LDAP_OTHER,
01264                                    "not enough memory for matched values filtering" );
01265                             goto error_return;
01266                      }
01267                      e_flags = tmp;
01268                      a_flags = (char *)(e_flags + i);
01269                      memset( a_flags, 0, k );
01270                      for ( a = rs->sr_operational_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
01271                             for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
01272                             e_flags[i] = a_flags;
01273                             a_flags += j;
01274                      }
01275                      rc = filter_matched_values(op, rs->sr_operational_attrs, &e_flags) ; 
01276                   
01277                      if ( rc == -1 ) {
01278                             Debug( LDAP_DEBUG_ANY,
01279                                    "send_search_entry: conn %lu "
01280                                    "matched values filtering failed\n", 
01281                                    op->o_connid, 0, 0);
01282                             if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01283                             send_ldap_error( op, rs, LDAP_OTHER,
01284                                    "matched values filtering error" );
01285                             rc = rs->sr_err;
01286                             goto error_return;
01287                      }
01288               }
01289        }
01290 
01291        for (a = rs->sr_operational_attrs, j=0; a != NULL; a = a->a_next, j++ ) {
01292               AttributeDescription *desc = a->a_desc;
01293 
01294               if ( rs->sr_attrs == NULL ) {
01295                      /* all user attrs request, skip operational attributes */
01296                      if( is_at_operational( desc->ad_type ) ) {
01297                             continue;
01298                      }
01299 
01300               } else {
01301                      /* specific attrs requested */
01302                      if( is_at_operational( desc->ad_type ) ) {
01303                             if ( !SLAP_OPATTRS( rs->sr_attr_flags ) && 
01304                                    !ad_inlist( desc, rs->sr_attrs ) )
01305                             {
01306                                    continue;
01307                             }
01308                             /* if DSA-specific and replicating, skip */
01309                             if ( op->o_sync != SLAP_CONTROL_NONE &&
01310                                    desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION )
01311                                    continue;
01312                      } else {
01313                             if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) {
01314                                    continue;
01315                             }
01316                      }
01317               }
01318 
01319               if ( ! access_allowed( op, rs->sr_entry, desc, NULL,
01320                      ACL_READ, &acl_state ) )
01321               {
01322                      Debug( LDAP_DEBUG_ACL,
01323                             "send_search_entry: conn %lu "
01324                             "access to attribute %s not allowed\n",
01325                             op->o_connid, desc->ad_cname.bv_val, 0 );
01326 
01327                      continue;
01328               }
01329 
01330               rc = ber_printf( ber, "{O[" /*]}*/ , &desc->ad_cname );
01331               if ( rc == -1 ) {
01332                      Debug( LDAP_DEBUG_ANY,
01333                             "send_search_entry: conn %lu  "
01334                             "ber_printf failed\n", op->o_connid, 0, 0 );
01335 
01336                      if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01337                      send_ldap_error( op, rs, LDAP_OTHER,
01338                             "encoding description error" );
01339                      rc = rs->sr_err;
01340                      goto error_return;
01341               }
01342 
01343               if ( ! attrsonly ) {
01344                      for ( i = 0; a->a_vals[i].bv_val != NULL; i++ ) {
01345                             if ( ! access_allowed( op, rs->sr_entry,
01346                                    desc, &a->a_vals[i], ACL_READ, &acl_state ) )
01347                             {
01348                                    Debug( LDAP_DEBUG_ACL,
01349                                           "send_search_entry: conn %lu "
01350                                           "access to %s, value %d not allowed\n",
01351                                           op->o_connid, desc->ad_cname.bv_val, i );
01352 
01353                                    continue;
01354                             }
01355 
01356                             if ( op->o_vrFilter && e_flags[j][i] == 0 ){
01357                                    continue;
01358                             }
01359 
01360                             if (( rc = ber_printf( ber, "O", &a->a_vals[i] )) == -1 ) {
01361                                    Debug( LDAP_DEBUG_ANY,
01362                                           "send_search_entry: conn %lu  ber_printf failed\n", 
01363                                           op->o_connid, 0, 0 );
01364 
01365                                    if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01366                                    send_ldap_error( op, rs, LDAP_OTHER,
01367                                           "encoding values error" );
01368                                    rc = rs->sr_err;
01369                                    goto error_return;
01370                             }
01371                      }
01372               }
01373 
01374               if (( rc = ber_printf( ber, /*{[*/ "]N}" )) == -1 ) {
01375                      Debug( LDAP_DEBUG_ANY,
01376                             "send_search_entry: conn %lu  ber_printf failed\n",
01377                             op->o_connid, 0, 0 );
01378 
01379                      if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01380                      send_ldap_error( op, rs, LDAP_OTHER, "encode end error" );
01381                      rc = rs->sr_err;
01382                      goto error_return;
01383               }
01384        }
01385 
01386        /* free e_flags */
01387        if ( e_flags ) {
01388               slap_sl_free( e_flags, op->o_tmpmemctx );
01389               e_flags = NULL;
01390        }
01391 
01392        rc = ber_printf( ber, /*{{*/ "}N}" );
01393 
01394        if( rc != -1 ) {
01395               rc = send_ldap_controls( op, ber, rs->sr_ctrls );
01396        }
01397 
01398        if( rc != -1 ) {
01399 #ifdef LDAP_CONNECTIONLESS
01400               if( op->o_conn && op->o_conn->c_is_udp ) {
01401                      if ( op->o_protocol != LDAP_VERSION2 ) {
01402                             rc = ber_printf( ber, /*{*/ "N}" );
01403                      }
01404               } else
01405 #endif
01406               if ( op->o_res_ber == NULL ) {
01407                      rc = ber_printf( ber, /*{*/ "N}" );
01408               }
01409        }
01410 
01411        if ( rc == -1 ) {
01412               Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
01413 
01414               if ( op->o_res_ber == NULL ) ber_free_buf( ber );
01415               send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" );
01416               rc = rs->sr_err;
01417               goto error_return;
01418        }
01419 
01420        Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n",
01421            op->o_log_prefix, rs->sr_entry->e_nname.bv_val, 0, 0, 0 );
01422 
01423        rs_flush_entry( op, rs, NULL );
01424 
01425        if ( op->o_res_ber == NULL ) {
01426               bytes = send_ldap_ber( op, ber );
01427               ber_free_buf( ber );
01428 
01429               if ( bytes < 0 ) {
01430                      Debug( LDAP_DEBUG_ANY,
01431                             "send_search_entry: conn %lu  ber write failed.\n", 
01432                             op->o_connid, 0, 0 );
01433 
01434                      rc = LDAP_UNAVAILABLE;
01435                      goto error_return;
01436               }
01437               rs->sr_nentries++;
01438 
01439               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
01440               ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
01441               ldap_pvt_mp_add_ulong( op->o_counters->sc_entries, 1 );
01442               ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
01443               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
01444        }
01445 
01446        Debug( LDAP_DEBUG_TRACE,
01447               "<= send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 );
01448 
01449        rc = LDAP_SUCCESS;
01450 
01451 error_return:;
01452        if ( op->o_callback ) {
01453               (void)slap_cleanup_play( op, rs );
01454        }
01455 
01456        if ( e_flags ) {
01457               slap_sl_free( e_flags, op->o_tmpmemctx );
01458        }
01459 
01460        /* FIXME: Can break if rs now contains an extended response */
01461        if ( rs->sr_operational_attrs ) {
01462               attrs_free( rs->sr_operational_attrs );
01463               rs->sr_operational_attrs = NULL;
01464        }
01465        rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED;
01466 
01467        if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
01468               rs_flush_entry( op, rs, NULL );
01469        } else {
01470               RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 );
01471        }
01472 
01473        if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
01474               rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
01475               if ( rs->sr_ctrls ) {
01476                      slap_free_ctrls( op, rs->sr_ctrls );
01477                      rs->sr_ctrls = NULL;
01478               }
01479        }
01480 
01481        return( rc );
01482 }
01483 
01484 int
01485 slap_send_search_reference( Operation *op, SlapReply *rs )
01486 {
01487        BerElementBuffer berbuf;
01488        BerElement    *ber = (BerElement *) &berbuf;
01489        int rc = 0;
01490        int bytes;
01491        char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)";
01492 
01493        AttributeDescription *ad_ref = slap_schema.si_ad_ref;
01494        AttributeDescription *ad_entry = slap_schema.si_ad_entry;
01495 
01496        rs->sr_type = REP_SEARCHREF;
01497        if ( op->o_callback ) {
01498               rc = slap_response_play( op, rs );
01499               if ( rc != SLAP_CB_CONTINUE ) {
01500                      goto rel;
01501               }
01502        }
01503 
01504        Debug( LDAP_DEBUG_TRACE,
01505               "=> send_search_reference: dn=\"%s\"\n",
01506               edn, 0, 0 );
01507 
01508        if (  rs->sr_entry && ! access_allowed( op, rs->sr_entry,
01509               ad_entry, NULL, ACL_READ, NULL ) )
01510        {
01511               Debug( LDAP_DEBUG_ACL,
01512                      "send_search_reference: access to entry not allowed\n",
01513                   0, 0, 0 );
01514               rc = 1;
01515               goto rel;
01516        }
01517 
01518        if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry,
01519               ad_ref, NULL, ACL_READ, NULL ) )
01520        {
01521               Debug( LDAP_DEBUG_ACL,
01522                      "send_search_reference: access "
01523                      "to reference not allowed\n",
01524                   0, 0, 0 );
01525               rc = 1;
01526               goto rel;
01527        }
01528 
01529        if( op->o_domain_scope ) {
01530               Debug( LDAP_DEBUG_ANY,
01531                      "send_search_reference: domainScope control in (%s)\n", 
01532                      edn, 0, 0 );
01533               rc = 0;
01534               goto rel;
01535        }
01536 
01537        if( rs->sr_ref == NULL ) {
01538               Debug( LDAP_DEBUG_ANY,
01539                      "send_search_reference: null ref in (%s)\n", 
01540                      edn, 0, 0 );
01541               rc = 1;
01542               goto rel;
01543        }
01544 
01545        if( op->o_protocol < LDAP_VERSION3 ) {
01546               rc = 0;
01547               /* save the references for the result */
01548               if( rs->sr_ref[0].bv_val != NULL ) {
01549                      if( value_add( &rs->sr_v2ref, rs->sr_ref ) )
01550                             rc = LDAP_OTHER;
01551               }
01552               goto rel;
01553        }
01554 
01555 #ifdef LDAP_CONNECTIONLESS
01556        if( op->o_conn && op->o_conn->c_is_udp ) {
01557               ber = op->o_res_ber;
01558        } else
01559 #endif
01560        {
01561               ber_init_w_nullc( ber, LBER_USE_DER );
01562               ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
01563        }
01564 
01565        rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid,
01566               LDAP_RES_SEARCH_REFERENCE, rs->sr_ref );
01567 
01568        if( rc != -1 ) {
01569               rc = send_ldap_controls( op, ber, rs->sr_ctrls );
01570        }
01571 
01572        if( rc != -1 ) {
01573               rc = ber_printf( ber, /*"{"*/ "N}" );
01574        }
01575 
01576        if ( rc == -1 ) {
01577               Debug( LDAP_DEBUG_ANY,
01578                      "send_search_reference: ber_printf failed\n", 0, 0, 0 );
01579 
01580 #ifdef LDAP_CONNECTIONLESS
01581               if (!op->o_conn || op->o_conn->c_is_udp == 0)
01582 #endif
01583               ber_free_buf( ber );
01584               send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" );
01585               goto rel;
01586        }
01587 
01588        rc = 0;
01589        rs_flush_entry( op, rs, NULL );
01590 
01591 #ifdef LDAP_CONNECTIONLESS
01592        if (!op->o_conn || op->o_conn->c_is_udp == 0) {
01593 #endif
01594        bytes = send_ldap_ber( op, ber );
01595        ber_free_buf( ber );
01596 
01597        if ( bytes < 0 ) {
01598               rc = LDAP_UNAVAILABLE;
01599        } else {
01600               ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex );
01601               ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes );
01602               ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 );
01603               ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 );
01604               ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex );
01605        }
01606 #ifdef LDAP_CONNECTIONLESS
01607        }
01608 #endif
01609        if ( rs->sr_ref != NULL ) {
01610               int    r;
01611 
01612               for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) {
01613                      Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n",
01614                             op->o_log_prefix, r, rs->sr_ref[0].bv_val,
01615                             0, 0 );
01616               }
01617 
01618        } else {
01619               Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n",
01620                      op->o_log_prefix, 0, 0, 0, 0 );
01621        }
01622 
01623        Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 );
01624 
01625        if ( 0 ) {
01626 rel:
01627            rs_flush_entry( op, rs, NULL );
01628        }
01629 
01630        if ( op->o_callback ) {
01631               (void)slap_cleanup_play( op, rs );
01632        }
01633 
01634        if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) {
01635               rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */
01636               if ( rs->sr_ctrls ) {
01637                      slap_free_ctrls( op, rs->sr_ctrls );
01638                      rs->sr_ctrls = NULL;
01639               }
01640        }
01641 
01642        return rc;
01643 }
01644 
01645 int
01646 str2result(
01647     char      *s,
01648     int              *code,
01649     char      **matched,
01650     char      **info )
01651 {
01652        int    rc;
01653        char   *c;
01654 
01655        *code = LDAP_SUCCESS;
01656        *matched = NULL;
01657        *info = NULL;
01658 
01659        if ( strncasecmp( s, "RESULT", STRLENOF( "RESULT" ) ) != 0 ) {
01660               Debug( LDAP_DEBUG_ANY, "str2result (%s) expecting \"RESULT\"\n",
01661                   s, 0, 0 );
01662 
01663               return( -1 );
01664        }
01665 
01666        rc = 0;
01667        while ( (s = strchr( s, '\n' )) != NULL ) {
01668               *s++ = '\0';
01669               if ( *s == '\0' ) {
01670                      break;
01671               }
01672               if ( (c = strchr( s, ':' )) != NULL ) {
01673                      c++;
01674               }
01675 
01676               if ( strncasecmp( s, "code", STRLENOF( "code" ) ) == 0 ) {
01677                      char   *next = NULL;
01678                      long   retcode;
01679 
01680                      if ( c == NULL ) {
01681                             Debug( LDAP_DEBUG_ANY, "str2result (%s) missing value\n",
01682                                 s, 0, 0 );
01683                             rc = -1;
01684                             continue;
01685                      }
01686 
01687                      while ( isspace( (unsigned char) c[ 0 ] ) ) c++;
01688                      if ( c[ 0 ] == '\0' ) {
01689                             Debug( LDAP_DEBUG_ANY, "str2result (%s) missing or empty value\n",
01690                                 s, 0, 0 );
01691                             rc = -1;
01692                             continue;
01693                      }
01694 
01695                      retcode = strtol( c, &next, 10 );
01696                      if ( next == NULL || next == c ) {
01697                             Debug( LDAP_DEBUG_ANY, "str2result (%s) unable to parse value\n",
01698                                 s, 0, 0 );
01699                             rc = -1;
01700                             continue;
01701                      }
01702 
01703                      while ( isspace( (unsigned char) next[ 0 ] ) && next[ 0 ] != '\n' )
01704                             next++;
01705                      if ( next[ 0 ] != '\0' && next[ 0 ] != '\n' ) {
01706                             Debug( LDAP_DEBUG_ANY, "str2result (%s) extra cruft after value\n",
01707                                 s, 0, 0 );
01708                             rc = -1;
01709                             continue;
01710                      }
01711 
01712                      /* FIXME: what if it's larger than max int? */
01713                      *code = (int)retcode;
01714 
01715               } else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) {
01716                      if ( c != NULL ) {
01717                             *matched = c;
01718                      }
01719               } else if ( strncasecmp( s, "info", STRLENOF( "info" ) ) == 0 ) {
01720                      if ( c != NULL ) {
01721                             *info = c;
01722                      }
01723               } else {
01724                      Debug( LDAP_DEBUG_ANY, "str2result (%s) unknown\n",
01725                          s, 0, 0 );
01726 
01727                      rc = -1;
01728               }
01729        }
01730 
01731        return( rc );
01732 }
01733 
01734 int slap_read_controls(
01735        Operation *op,
01736        SlapReply *rs,
01737        Entry *e,
01738        const struct berval *oid,
01739        LDAPControl **ctrl )
01740 {
01741        int rc;
01742        struct berval bv;
01743        BerElementBuffer berbuf;
01744        BerElement *ber = (BerElement *) &berbuf;
01745        LDAPControl c;
01746        Operation myop;
01747 
01748        Debug( LDAP_DEBUG_ANY, "%s slap_read_controls: (%s) %s\n",
01749               op->o_log_prefix, oid->bv_val, e->e_dn );
01750 
01751        rs->sr_entry = e;
01752        rs->sr_attrs = ( oid == &slap_pre_read_bv ) ?
01753               op->o_preread_attrs : op->o_postread_attrs; 
01754 
01755        bv.bv_len = entry_flatsize( rs->sr_entry, 0 );
01756        bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );
01757 
01758        ber_init2( ber, &bv, LBER_USE_DER );
01759        ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );
01760 
01761        /* create new operation */
01762        myop = *op;
01763        /* FIXME: o_bd needed for ACL */
01764        myop.o_bd = op->o_bd;
01765        myop.o_res_ber = ber;
01766        myop.o_callback = NULL;
01767        myop.ors_slimit = 1;
01768        myop.ors_attrsonly = 0;
01769 
01770        rc = slap_send_search_entry( &myop, rs );
01771        if( rc ) return rc;
01772 
01773        rc = ber_flatten2( ber, &c.ldctl_value, 0 );
01774 
01775        if( rc == -1 ) return LDAP_OTHER;
01776 
01777        c.ldctl_oid = oid->bv_val;
01778        c.ldctl_iscritical = 0;
01779 
01780        if ( *ctrl == NULL ) {
01781               /* first try */
01782               *ctrl = (LDAPControl *) slap_sl_calloc( 1, sizeof(LDAPControl), NULL );
01783        } else {
01784               /* retry: free previous try */
01785               slap_sl_free( (*ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
01786        }
01787 
01788        **ctrl = c;
01789        return LDAP_SUCCESS;
01790 }
01791 
01792 /* Map API errors to protocol errors... */
01793 int
01794 slap_map_api2result( SlapReply *rs )
01795 {
01796        switch(rs->sr_err) {
01797        case LDAP_SERVER_DOWN:
01798               return LDAP_UNAVAILABLE;
01799        case LDAP_LOCAL_ERROR:
01800               return LDAP_OTHER;
01801        case LDAP_ENCODING_ERROR:
01802        case LDAP_DECODING_ERROR:
01803               return LDAP_PROTOCOL_ERROR;
01804        case LDAP_TIMEOUT:
01805               return LDAP_UNAVAILABLE;
01806        case LDAP_AUTH_UNKNOWN:
01807               return LDAP_AUTH_METHOD_NOT_SUPPORTED;
01808        case LDAP_FILTER_ERROR:
01809               rs->sr_text = "Filter error";
01810               return LDAP_OTHER;
01811        case LDAP_USER_CANCELLED:
01812               rs->sr_text = "User cancelled";
01813               return LDAP_OTHER;
01814        case LDAP_PARAM_ERROR:
01815               return LDAP_PROTOCOL_ERROR;
01816        case LDAP_NO_MEMORY:
01817               return LDAP_OTHER;
01818        case LDAP_CONNECT_ERROR:
01819               return LDAP_UNAVAILABLE;
01820        case LDAP_NOT_SUPPORTED:
01821               return LDAP_UNWILLING_TO_PERFORM;
01822        case LDAP_CONTROL_NOT_FOUND:
01823               return LDAP_PROTOCOL_ERROR;
01824        case LDAP_NO_RESULTS_RETURNED:
01825               return LDAP_NO_SUCH_OBJECT;
01826        case LDAP_MORE_RESULTS_TO_RETURN:
01827               rs->sr_text = "More results to return";
01828               return LDAP_OTHER;
01829        case LDAP_CLIENT_LOOP:
01830        case LDAP_REFERRAL_LIMIT_EXCEEDED:
01831               return LDAP_LOOP_DETECT;
01832        default:
01833               if ( LDAP_API_ERROR(rs->sr_err) ) return LDAP_OTHER;
01834               return rs->sr_err;
01835        }
01836 }
01837 
01838 
01839 slap_mask_t
01840 slap_attr_flags( AttributeName *an )
01841 {
01842        slap_mask_t   flags = SLAP_ATTRS_UNDEFINED;
01843 
01844        if ( an == NULL ) {
01845               flags |= ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES );
01846 
01847        } else {
01848               flags |= an_find( an, slap_bv_all_operational_attrs )
01849                      ? SLAP_OPATTRS_YES : SLAP_OPATTRS_NO;
01850               flags |= an_find( an, slap_bv_all_user_attrs )
01851                      ? SLAP_USERATTRS_YES : SLAP_USERATTRS_NO;
01852        }
01853 
01854        return flags;
01855 }