X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fresult.c;h=49d742933900c385fa858e09f43a20b82c9a10b8;hb=914253c5635165f60f6bf510b7f1b90f73a4033a;hp=f89b87304c5e8acabcf07077b72ec189b91e81a6;hpb=02e14e9c8d50a21f632a499b1c09918c8c9a802e;p=openldap diff --git a/servers/slapd/result.c b/servers/slapd/result.c index f89b87304c..49d7429339 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2008 The OpenLDAP Foundation. + * Copyright 1998-2013 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -132,32 +132,196 @@ slap_req2res( ber_tag_t tag ) return tag; } +/* SlapReply debugging, prodo-slap.h overrides it in OpenLDAP releases */ +#if defined(LDAP_TEST) || (defined(USE_RS_ASSERT) && (USE_RS_ASSERT)) + +int rs_suppress_assert = 0; + +/* RS_ASSERT() helper function */ +void rs_assert_(const char*file, unsigned line, const char*fn, const char*cond) +{ + int no_assert = rs_suppress_assert, save_errno = errno; + const char *s; + + if ( no_assert >= 0 ) { + if ( no_assert == 0 && (s = getenv( "NO_RS_ASSERT" )) && *s ) { + no_assert = rs_suppress_assert = atoi( s ); + } + if ( no_assert > 0 ) { + errno = save_errno; + return; + } + } + +#ifdef rs_assert_ /* proto-slap.h #defined away the fn parameter */ + fprintf( stderr,"%s:%u: " "RS_ASSERT(%s) failed.\n", file,line,cond ); +#else + fprintf( stderr,"%s:%u: %s: RS_ASSERT(%s) failed.\n", file,line,fn,cond ); +#endif + fflush( stderr ); + + errno = save_errno; + /* $NO_RS_ASSERT > 0: ignore rs_asserts, 0: abort, < 0: just warn */ + if ( !no_assert /* from $NO_RS_ASSERT */ ) abort(); +} + +/* SlapReply is consistent */ +void +(rs_assert_ok)( const SlapReply *rs ) +{ + const slap_mask_t flags = rs->sr_flags; + + if ( flags & REP_ENTRY_MASK ) { + RS_ASSERT( !(flags & REP_ENTRY_MUSTRELEASE) + || !(flags & (REP_ENTRY_MASK ^ REP_ENTRY_MUSTRELEASE)) ); + RS_ASSERT( rs->sr_entry != NULL ); + RS_ASSERT( (1 << rs->sr_type) & + ((1 << REP_SEARCH) | (1 << REP_SEARCHREF) | + (1 << REP_RESULT) | (1 << REP_GLUE_RESULT)) ); + } +#if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */ + if ( (flags & (REP_MATCHED_MASK | REP_REF_MASK | REP_CTRLS_MASK)) ) { + RS_ASSERT( !(flags & REP_MATCHED_MASK) || rs->sr_matched ); + RS_ASSERT( !(flags & REP_CTRLS_MASK ) || rs->sr_ctrls ); + /* Note: LDAP_REFERRAL + !sr_ref is OK, becomes LDAP_NO_SUCH_OBJECT */ + } +#if (USE_RS_ASSERT) > 2 + if ( rs->sr_err == LDAP_SUCCESS ) { + RS_ASSERT( rs->sr_text == NULL ); + RS_ASSERT( rs->sr_matched == NULL ); + } +#endif +#endif +} + +/* Ready for calling a new backend operation */ +void +(rs_assert_ready)( const SlapReply *rs ) +{ + RS_ASSERT( !rs->sr_entry ); +#if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */ + RS_ASSERT( !rs->sr_text ); + RS_ASSERT( !rs->sr_ref ); + RS_ASSERT( !rs->sr_matched ); + RS_ASSERT( !rs->sr_ctrls ); + RS_ASSERT( !rs->sr_flags ); +#if (USE_RS_ASSERT) > 2 + RS_ASSERT( rs->sr_err == LDAP_SUCCESS ); +#endif +#else + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); +#endif +} + +/* Backend operation done */ +void +(rs_assert_done)( const SlapReply *rs ) +{ +#if defined(USE_RS_ASSERT) && (USE_RS_ASSERT) > 1 /* TODO: Enable when safe */ + RS_ASSERT( !(rs->sr_flags & ~(REP_ENTRY_MODIFIABLE|REP_NO_OPERATIONALS)) ); + rs_assert_ok( rs ); +#else + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MUSTFLUSH) ); +#endif +} + +#endif /* LDAP_TEST || USE_RS_ASSERT */ + +/* Reset a used SlapReply whose contents has been flushed (freed/released) */ +void +(rs_reinit)( SlapReply *rs, slap_reply_t type ) +{ + rs_reinit( rs, type ); /* proto-slap.h macro */ +} + +/* Obey and clear rs->sr_flags & REP_ENTRY_MASK. Clear sr_entry if freed. */ +void +rs_flush_entry( Operation *op, SlapReply *rs, slap_overinst *on ) +{ + rs_assert_ok( rs ); + + if ( (rs->sr_flags & REP_ENTRY_MUSTFLUSH) && rs->sr_entry != NULL ) { + if ( !(rs->sr_flags & REP_ENTRY_MUSTRELEASE) ) { + entry_free( rs->sr_entry ); + } else if ( on != NULL ) { + overlay_entry_release_ov( op, rs->sr_entry, 0, on ); + } else { + be_entry_release_rw( op, rs->sr_entry, 0 ); + } + rs->sr_entry = NULL; + } + + rs->sr_flags &= ~REP_ENTRY_MASK; +} + +/* Set rs->sr_entry after obeying and clearing sr_flags & REP_ENTRY_MASK. */ +void +rs_replace_entry( Operation *op, SlapReply *rs, slap_overinst *on, Entry *e ) +{ + rs_flush_entry( op, rs, on ); + rs->sr_entry = e; +} + +/* + * Ensure rs->sr_entry is modifiable, by duplicating it if necessary. + * Obey sr_flags. Set REP_ENTRY_. + * Return nonzero if rs->sr_entry was replaced. + */ +int +rs_entry2modifiable( Operation *op, SlapReply *rs, slap_overinst *on ) +{ + if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) { + rs_assert_ok( rs ); + return 0; + } + rs_replace_entry( op, rs, on, entry_dup( rs->sr_entry )); + rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; + return 1; +} + static long send_ldap_ber( - Connection *conn, + Operation *op, BerElement *ber ) { + Connection *conn = op->o_conn; ber_len_t bytes; + long ret = 0; ber_get_option( ber, LBER_OPT_BER_BYTES_TO_WRITE, &bytes ); /* write only one pdu at a time - wait til it's our turn */ - ldap_pvt_thread_mutex_lock( &conn->c_write_mutex ); + ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex ); + if (( op->o_abandon && !op->o_cancel ) || !connection_valid( conn ) || + conn->c_writers < 0 ) { + ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); + return 0; + } + + conn->c_writers++; + + while ( conn->c_writers > 0 && conn->c_writing ) { + ldap_pvt_thread_cond_wait( &conn->c_write1_cv, &conn->c_write1_mutex ); + } - /* lock the connection */ - ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + /* connection was closed under us */ + if ( conn->c_writers < 0 ) { + /* we're the last waiter, let the closer continue */ + if ( conn->c_writers == -1 ) + ldap_pvt_thread_cond_signal( &conn->c_write1_cv ); + conn->c_writers++; + ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); + return 0; + } + + /* Our turn */ + conn->c_writing = 1; /* write the pdu */ while( 1 ) { int err; - if ( connection_state_closing( conn ) ) { - ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); - ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex ); - - return 0; - } - if ( ber_flush2( conn->c_sb, ber, LBER_FLUSH_FREE_NEVER ) == 0 ) { + ret = bytes; break; } @@ -173,26 +337,46 @@ static long send_ldap_ber( err, sock_errstr(err), 0 ); if ( err != EWOULDBLOCK && err != EAGAIN ) { + conn->c_writers--; + conn->c_writing = 0; + ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); connection_closing( conn, "connection lost on write" ); ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); - ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex ); - - return( -1 ); + return -1; } /* wait for socket to be write-ready */ + ldap_pvt_thread_mutex_lock( &conn->c_write2_mutex ); conn->c_writewaiter = 1; - slapd_set_write( conn->c_sd, 1 ); + slapd_set_write( conn->c_sd, 2 ); - ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex ); + ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); + ldap_pvt_thread_pool_idle( &connection_pool ); + ldap_pvt_thread_cond_wait( &conn->c_write2_cv, &conn->c_write2_mutex ); conn->c_writewaiter = 0; + ldap_pvt_thread_mutex_unlock( &conn->c_write2_mutex ); + ldap_pvt_thread_pool_unidle( &connection_pool ); + ldap_pvt_thread_mutex_lock( &conn->c_write1_mutex ); + if ( conn->c_writers < 0 ) { + ret = 0; + break; + } } - ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); - ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex ); + conn->c_writing = 0; + if ( conn->c_writers < 0 ) { + conn->c_writers++; + if ( !conn->c_writers ) + ldap_pvt_thread_cond_signal( &conn->c_write1_cv ); + } else { + conn->c_writers--; + ldap_pvt_thread_cond_signal( &conn->c_write1_cv ); + } + ldap_pvt_thread_mutex_unlock( &conn->c_write1_mutex ); - return bytes; + return ret; } static int @@ -251,11 +435,11 @@ send_ldap_controls( Operation *o, BerElement *ber, LDAPControl **c ) ber_printf( sber, "{e}", LDAP_UNWILLING_TO_PERFORM ); - if( ber_flatten2( ber, &sorted.ldctl_value, 0 ) == -1 ) { + if( ber_flatten2( sber, &sorted.ldctl_value, 0 ) == -1 ) { return -1; } - (void) ber_free_buf( ber ); + (void) ber_free_buf( sber ); rc = send_ldap_control( ber, &sorted ); if( rc == -1 ) return rc; @@ -372,7 +556,8 @@ send_ldap_response( int rc = LDAP_SUCCESS; long bytes; - if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon ) { + /* op was actually aborted, bypass everything if client didn't Cancel */ + if (( rs->sr_err == SLAPD_ABANDON ) && !op->o_cancel ) { rc = SLAPD_ABANDON; goto clean2; } @@ -384,6 +569,12 @@ send_ldap_response( } } + /* op completed, connection aborted, bypass sending response */ + if ( op->o_abandon && !op->o_cancel ) { + rc = SLAPD_ABANDON; + goto clean2; + } + #ifdef LDAP_CONNECTIONLESS if (op->o_conn && op->o_conn->c_is_udp) ber = op->o_res_ber; @@ -394,9 +585,13 @@ send_ldap_response( ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } + rc = rs->sr_err; + if ( rc == SLAPD_ABANDON && op->o_cancel ) + rc = LDAP_CANCELLED; + Debug( LDAP_DEBUG_TRACE, "send_ldap_response: msgid=%d tag=%lu err=%d\n", - rs->sr_msgid, rs->sr_tag, rs->sr_err ); + rs->sr_msgid, rs->sr_tag, rc ); if( rs->sr_ref ) { Debug( LDAP_DEBUG_ARGS, "send_ldap_response: ref=\"%s\"\n", @@ -409,7 +604,7 @@ send_ldap_response( op->o_protocol == LDAP_VERSION2 ) { rc = ber_printf( ber, "t{ess" /*"}"*/, - rs->sr_tag, rs->sr_err, + rs->sr_tag, rc, rs->sr_matched == NULL ? "" : rs->sr_matched, rs->sr_text == NULL ? "" : rs->sr_text ); } else @@ -420,7 +615,7 @@ send_ldap_response( } else { rc = ber_printf( ber, "{it{ess" /*"}}"*/, - rs->sr_msgid, rs->sr_tag, rs->sr_err, + rs->sr_msgid, rs->sr_tag, rc, rs->sr_matched == NULL ? "" : rs->sr_matched, rs->sr_text == NULL ? "" : rs->sr_text ); } @@ -490,7 +685,7 @@ send_ldap_response( } /* send BER */ - bytes = send_ldap_ber( op->o_conn, ber ); + bytes = send_ldap_ber( op, ber ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) #endif @@ -558,13 +753,17 @@ send_ldap_disconnect( Operation *op, SlapReply *rs ) || (e) == LDAP_STRONG_AUTH_REQUIRED \ || (e) == LDAP_UNAVAILABLE ) - assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) ); - - rs->sr_type = REP_EXTENDED; - Debug( LDAP_DEBUG_TRACE, "send_ldap_disconnect %d:%s\n", rs->sr_err, rs->sr_text ? rs->sr_text : "", NULL ); + assert( LDAP_UNSOLICITED_ERROR( rs->sr_err ) ); + + /* TODO: Flush the entry if sr_type == REP_SEARCH/REP_SEARCHREF? */ + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ + + rs->sr_type = REP_EXTENDED; + rs->sr_rspdata = NULL; if ( op->o_protocol < LDAP_VERSION3 ) { rs->sr_rspoid = NULL; @@ -598,25 +797,20 @@ slap_send_ldap_result( Operation *op, SlapReply *rs ) if ( rs->sr_err == SLAPD_ABANDON || op->o_abandon ) goto abandon; - assert( !LDAP_API_ERROR( rs->sr_err ) ); - Debug( LDAP_DEBUG_TRACE, "send_ldap_result: %s p=%d\n", op->o_log_prefix, op->o_protocol, 0 ); - Debug( LDAP_DEBUG_ARGS, "send_ldap_result: err=%d matched=\"%s\" text=\"%s\"\n", rs->sr_err, rs->sr_matched ? rs->sr_matched : "", rs->sr_text ? rs->sr_text : "" ); - - if( rs->sr_ref ) { Debug( LDAP_DEBUG_ARGS, "send_ldap_result: referral=\"%s\"\n", rs->sr_ref[0].bv_val ? rs->sr_ref[0].bv_val : "NULL", NULL, NULL ); } - + assert( !LDAP_API_ERROR( rs->sr_err ) ); assert( rs->sr_err != LDAP_PARTIAL_RESULTS ); if ( rs->sr_err == LDAP_REFERRAL ) { @@ -649,14 +843,10 @@ abandon: if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { if ( op->o_tag == LDAP_REQ_SEARCH ) { - char nbuf[64]; - snprintf( nbuf, sizeof nbuf, "%d nentries=%d", - rs->sr_err, rs->sr_nentries ); - Statslog( LDAP_DEBUG_STATS, - "%s SEARCH RESULT tag=%lu err=%s text=%s\n", - op->o_log_prefix, rs->sr_tag, nbuf, - rs->sr_text ? rs->sr_text : "", 0 ); + "%s SEARCH RESULT tag=%lu err=%d nentries=%d text=%s\n", + op->o_log_prefix, rs->sr_tag, rs->sr_err, + rs->sr_nentries, rs->sr_text ? rs->sr_text : "" ); } else { Statslog( LDAP_DEBUG_STATS, "%s RESULT tag=%lu err=%d text=%s\n", @@ -673,11 +863,14 @@ abandon: void send_ldap_sasl( Operation *op, SlapReply *rs ) { - rs->sr_type = REP_SASL; Debug( LDAP_DEBUG_TRACE, "send_ldap_sasl: err=%d len=%ld\n", rs->sr_err, rs->sr_sasldata ? (long) rs->sr_sasldata->bv_len : -1, NULL ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ + + rs->sr_type = REP_SASL; rs->sr_tag = slap_req2res( op->o_tag ); rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; @@ -692,14 +885,16 @@ send_ldap_sasl( Operation *op, SlapReply *rs ) void slap_send_ldap_extended( Operation *op, SlapReply *rs ) { - rs->sr_type = REP_EXTENDED; - Debug( LDAP_DEBUG_TRACE, "send_ldap_extended: err=%d oid=%s len=%ld\n", rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "", rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ + + rs->sr_type = REP_EXTENDED; rs->sr_tag = slap_req2res( op->o_tag ); rs->sr_msgid = (rs->sr_tag != LBER_SEQUENCE) ? op->o_msgid : 0; @@ -714,12 +909,16 @@ slap_send_ldap_extended( Operation *op, SlapReply *rs ) void slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) { - rs->sr_type = REP_INTERMEDIATE; Debug( LDAP_DEBUG_TRACE, "send_ldap_intermediate: err=%d oid=%s len=%ld\n", rs->sr_err, rs->sr_rspoid ? rs->sr_rspoid : "", rs->sr_rspdata != NULL ? rs->sr_rspdata->bv_len : 0 ); + + RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); + rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia */ + + rs->sr_type = REP_INTERMEDIATE; rs->sr_tag = LDAP_RES_INTERMEDIATE; rs->sr_msgid = op->o_msgid; if ( send_ldap_response( op, rs ) == SLAP_CB_CONTINUE ) { @@ -730,6 +929,9 @@ slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) } } +#define set_ldap_error( rs, err, text ) do { \ + (rs)->sr_err = err; (rs)->sr_text = text; } while(0) + /* * returns: * @@ -747,7 +949,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) BerElement *ber = (BerElement *) &berbuf; Attribute *a; int i, j, rc = LDAP_UNAVAILABLE, bytes; - char *edn; int userattrs; AccessControlState acl_state = ACL_STATE_INIT; int attrsonly; @@ -759,19 +960,21 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) */ char **e_flags = NULL; + rs->sr_type = REP_SEARCH; + if ( op->ors_slimit >= 0 && rs->sr_nentries >= op->ors_slimit ) { - return LDAP_SIZELIMIT_EXCEEDED; + rc = LDAP_SIZELIMIT_EXCEEDED; + goto error_return; } /* Every 64 entries, check for thread pool pause */ if ( ( ( rs->sr_nentries & 0x3f ) == 0x3f ) && ldap_pvt_thread_pool_pausing( &connection_pool ) > 0 ) { - return LDAP_BUSY; + rc = LDAP_BUSY; + goto error_return; } - rs->sr_type = REP_SEARCH; - /* eventually will loop through generated operational attribute types * currently implemented types include: * entryDN, subschemaSubentry, and hasSubordinates */ @@ -810,8 +1013,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) goto error_return; } - edn = rs->sr_entry->e_nname.bv_val; - if ( op->o_res_ber ) { /* read back control or LDAP_CONNECTIONLESS */ ber = op->o_res_ber; @@ -839,7 +1040,8 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) #endif if ( op->o_res_ber ) { /* read back control */ - rc = ber_printf( ber, "{O{" /*}}*/, &rs->sr_entry->e_name ); + rc = ber_printf( ber, "t{O{" /*}}*/, + LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); } else { rc = ber_printf( ber, "{it{O{" /*}}}*/, op->o_msgid, LDAP_RES_SEARCH_ENTRY, &rs->sr_entry->e_name ); @@ -851,7 +1053,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encoding DN error" ); + set_ldap_error( rs, LDAP_OTHER, "encoding DN error" ); rc = rs->sr_err; goto error_return; } @@ -878,10 +1080,10 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) if( e_flags == NULL ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu slap_sl_calloc failed\n", - op->o_connid ? op->o_connid : 0, 0, 0 ); + op->o_connid, 0, 0 ); ber_free( ber, 1 ); - send_ldap_error( op, rs, LDAP_OTHER, "out of memory" ); + set_ldap_error( rs, LDAP_OTHER, "out of memory" ); goto error_return; } a_flags = (char *)(e_flags + i); @@ -896,9 +1098,9 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_entry: " "conn %lu matched values filtering failed\n", - op->o_connid ? op->o_connid : 0, 0, 0 ); + op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "matched values filtering error" ); rc = rs->sr_err; goto error_return; @@ -952,7 +1154,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "encoding description error"); rc = rs->sr_err; goto error_return; @@ -986,7 +1188,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "encoding description error"); rc = rs->sr_err; goto error_return; @@ -998,7 +1200,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "ber_printf failed.\n", op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "encoding values error" ); rc = rs->sr_err; goto error_return; @@ -1012,7 +1214,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encode end error" ); + set_ldap_error( rs, LDAP_OTHER, "encode end error" ); rc = rs->sr_err; goto error_return; } @@ -1045,7 +1247,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "for matched values filtering\n", op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "not enough memory for matched values filtering" ); goto error_return; } @@ -1063,9 +1265,9 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "send_search_entry: conn %lu " "matched values filtering failed\n", - op->o_connid ? op->o_connid : 0, 0, 0); + op->o_connid, 0, 0); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "matched values filtering error" ); rc = rs->sr_err; goto error_return; @@ -1090,6 +1292,10 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) { continue; } + /* if DSA-specific and replicating, skip */ + if ( op->o_sync != SLAP_CONTROL_NONE && + desc->ad_type->sat_usage == LDAP_SCHEMA_DSA_OPERATION ) + continue; } else { if ( !userattrs && !ad_inlist( desc, rs->sr_attrs ) ) { continue; @@ -1115,7 +1321,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) "ber_printf failed\n", op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "encoding description error" ); rc = rs->sr_err; goto error_return; @@ -1144,7 +1350,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, + set_ldap_error( rs, LDAP_OTHER, "encoding values error" ); rc = rs->sr_err; goto error_return; @@ -1158,7 +1364,7 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) op->o_connid, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encode end error" ); + set_ldap_error( rs, LDAP_OTHER, "encode end error" ); rc = rs->sr_err; goto error_return; } @@ -1193,19 +1399,18 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 ); if ( op->o_res_ber == NULL ) ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encode entry end error" ); + set_ldap_error( rs, LDAP_OTHER, "encode entry end error" ); rc = rs->sr_err; goto error_return; } - if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { - be_entry_release_rw( op, rs->sr_entry, 0 ); - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; - rs->sr_entry = NULL; - } + Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n", + op->o_log_prefix, rs->sr_entry->e_nname.bv_val, 0, 0, 0 ); + + rs_flush_entry( op, rs, NULL ); if ( op->o_res_ber == NULL ) { - bytes = send_ldap_ber( op->o_conn, ber ); + bytes = send_ldap_ber( op, ber ); ber_free_buf( ber ); if ( bytes < 0 ) { @@ -1225,9 +1430,6 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); } - Statslog( LDAP_DEBUG_STATS2, "%s ENTRY dn=\"%s\"\n", - op->o_log_prefix, edn, 0, 0, 0 ); - Debug( LDAP_DEBUG_TRACE, "<= send_search_entry: conn %lu exit.\n", op->o_connid, 0, 0 ); @@ -1242,25 +1444,25 @@ error_return:; slap_sl_free( e_flags, op->o_tmpmemctx ); } + /* FIXME: Can break if rs now contains an extended response */ if ( rs->sr_operational_attrs ) { attrs_free( rs->sr_operational_attrs ); rs->sr_operational_attrs = NULL; } rs->sr_attr_flags = SLAP_ATTRS_UNDEFINED; - /* FIXME: I think rs->sr_type should be explicitly set to - * REP_SEARCH here. That's what it was when we entered this - * function. send_ldap_error may have changed it, but we - * should set it back so that the cleanup functions know - * what they're doing. - */ - if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH - && rs->sr_entry - && ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) ) - { - entry_free( rs->sr_entry ); - rs->sr_entry = NULL; - rs->sr_flags &= ~REP_ENTRY_MUSTBEFREED; + if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) { + rs_flush_entry( op, rs, NULL ); + } else { + RS_ASSERT( (rs->sr_flags & REP_ENTRY_MASK) == 0 ); + } + + if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { + rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ + if ( rs->sr_ctrls ) { + slap_free_ctrls( op, rs->sr_ctrls ); + rs->sr_ctrls = NULL; + } } return( rc ); @@ -1273,6 +1475,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) BerElement *ber = (BerElement *) &berbuf; int rc = 0; int bytes; + char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)"; AttributeDescription *ad_ref = slap_schema.si_ad_ref; AttributeDescription *ad_entry = slap_schema.si_ad_entry; @@ -1287,7 +1490,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, "=> send_search_reference: dn=\"%s\"\n", - rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)", 0, 0 ); + edn, 0, 0 ); if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL ) ) @@ -1313,7 +1516,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) if( op->o_domain_scope ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: domainScope control in (%s)\n", - rs->sr_entry->e_dn, 0, 0 ); + edn, 0, 0 ); rc = 0; goto rel; } @@ -1321,7 +1524,7 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) if( rs->sr_ref == NULL ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: null ref in (%s)\n", - rs->sr_entry ? rs->sr_entry->e_dn : "(null)", 0, 0 ); + edn, 0, 0 ); rc = 1; goto rel; } @@ -1365,21 +1568,17 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) if (!op->o_conn || op->o_conn->c_is_udp == 0) #endif ber_free_buf( ber ); - send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" ); + set_ldap_error( rs, LDAP_OTHER, "encode DN error" ); goto rel; } rc = 0; - if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { - be_entry_release_rw( op, rs->sr_entry, 0 ); - rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; - rs->sr_entry = NULL; - } + rs_flush_entry( op, rs, NULL ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) { #endif - bytes = send_ldap_ber( op->o_conn, ber ); + bytes = send_ldap_ber( op, ber ); ber_free_buf( ber ); if ( bytes < 0 ) { @@ -1410,11 +1609,23 @@ slap_send_search_reference( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 ); + if ( 0 ) { rel: + rs_flush_entry( op, rs, NULL ); + } + if ( op->o_callback ) { (void)slap_cleanup_play( op, rs ); } + if ( rs->sr_flags & REP_CTRLS_MUSTBEFREED ) { + rs->sr_flags ^= REP_CTRLS_MUSTBEFREED; /* paranoia */ + if ( rs->sr_ctrls ) { + slap_free_ctrls( op, rs->sr_ctrls ); + rs->sr_ctrls = NULL; + } + } + return rc; } @@ -1476,15 +1687,16 @@ str2result( continue; } - while ( isspace( (unsigned char) next[ 0 ] ) ) next++; - if ( next[ 0 ] != '\0' ) { + while ( isspace( (unsigned char) next[ 0 ] ) && next[ 0 ] != '\n' ) + next++; + if ( next[ 0 ] != '\0' && next[ 0 ] != '\n' ) { Debug( LDAP_DEBUG_ANY, "str2result (%s) extra cruft after value\n", s, 0, 0 ); rc = -1; continue; } - /* FIXME: what if it's larger that max int? */ + /* FIXME: what if it's larger than max int? */ *code = (int)retcode; } else if ( strncasecmp( s, "matched", STRLENOF( "matched" ) ) == 0 ) { @@ -1520,8 +1732,8 @@ int slap_read_controls( LDAPControl c; Operation myop; - Debug( LDAP_DEBUG_ANY, "slap_read_controls: (%s) %s\n", - oid->bv_val, e->e_dn, 0 ); + Debug( LDAP_DEBUG_ANY, "%s slap_read_controls: (%s) %s\n", + op->o_log_prefix, oid->bv_val, e->e_dn ); rs->sr_entry = e; rs->sr_attrs = ( oid == &slap_pre_read_bv ) ? @@ -1540,13 +1752,14 @@ int slap_read_controls( myop.o_res_ber = ber; myop.o_callback = NULL; myop.ors_slimit = 1; + myop.ors_attrsonly = 0; rc = slap_send_search_entry( &myop, rs ); if( rc ) return rc; rc = ber_flatten2( ber, &c.ldctl_value, 0 ); - if( rc == LBER_ERROR ) return LDAP_OTHER; + if( rc == -1 ) return LDAP_OTHER; c.ldctl_oid = oid->bv_val; c.ldctl_iscritical = 0; @@ -1619,12 +1832,11 @@ slap_attr_flags( AttributeName *an ) flags |= ( SLAP_OPATTRS_NO | SLAP_USERATTRS_YES ); } else { - flags |= an_find( an, &AllOper ) + flags |= an_find( an, slap_bv_all_operational_attrs ) ? SLAP_OPATTRS_YES : SLAP_OPATTRS_NO; - flags |= an_find( an, &AllUser ) + flags |= an_find( an, slap_bv_all_user_attrs ) ? SLAP_USERATTRS_YES : SLAP_USERATTRS_NO; } return flags; } -