⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.c

📁 OpenLdap是LDAP的开源项目
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Rewrite the search base, if required	 */	dc->target = mt;	dc->ctx = "searchBase";	switch ( ldap_back_dn_massage( dc, &realbase, &mbase ) ) {	case LDAP_SUCCESS:		break;	case LDAP_UNWILLING_TO_PERFORM:		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;		rs->sr_text = "Operation not allowed";		send_ldap_result( op, rs );		retcode = META_SEARCH_ERR;		goto doreturn;	default:		/*		 * this target is no longer candidate		 */		retcode = META_SEARCH_NOT_CANDIDATE;		goto doreturn;	}	/*	 * Maps filter	 */	rc = ldap_back_filter_map_rewrite( dc, op->ors_filter,			&mfilter, BACKLDAP_MAP );	switch ( rc ) {	case LDAP_SUCCESS:		break;	case LDAP_COMPARE_FALSE:	default:		/*		 * this target is no longer candidate		 */		retcode = META_SEARCH_NOT_CANDIDATE;		goto done;	}	/*	 * Maps required attributes	 */	rc = ldap_back_map_attrs( &mt->mt_rwmap.rwm_at,			op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );	if ( rc != LDAP_SUCCESS ) {		/*		 * this target is no longer candidate		 */		retcode = META_SEARCH_NOT_CANDIDATE;		goto done;	}	/* should we check return values? */	if ( op->ors_deref != -1 ) {		assert( msc->msc_ld != NULL );		(void)ldap_set_option( msc->msc_ld, LDAP_OPT_DEREF,				( void * )&op->ors_deref );	}	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {		tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1;		tv.tv_usec = 0;		tvp = &tv;	}retry:;	ctrls = op->o_ctrls;	if ( ldap_back_proxy_authz_ctrl( &msc->msc_bound_ndn,		mt->mt_version, &mt->mt_idassert, op, rs, &ctrls )		!= LDAP_SUCCESS )	{		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;		retcode = META_SEARCH_NOT_CANDIDATE;		goto done;	}	/*	 * Starts the search	 */	assert( msc->msc_ld != NULL );	rc = ldap_search_ext( msc->msc_ld,			mbase.bv_val, realscope, mfilter.bv_val,			mapped_attrs, op->ors_attrsonly,			ctrls, NULL, tvp, op->ors_slimit,			&candidates[ candidate ].sr_msgid ); 	switch ( rc ) {	case LDAP_SUCCESS:		retcode = META_SEARCH_CANDIDATE;		break;		case LDAP_SERVER_DOWN:		if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {			nretries = 0;			/* if the identity changed, there might be need to re-authz */			(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );			goto retry;		}		if ( *mcp == NULL ) {			retcode = META_SEARCH_ERR;			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;			break;		}		/* fall thru */	default:		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;		retcode = META_SEARCH_NOT_CANDIDATE;	}done:;	(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );	if ( mapped_attrs ) {		free( mapped_attrs );	}	if ( mfilter.bv_val != op->ors_filterstr.bv_val ) {		free( mfilter.bv_val );	}	if ( mbase.bv_val != realbase.bv_val ) {		free( mbase.bv_val );	}doreturn:;	Debug( LDAP_DEBUG_TRACE, "%s <<< meta_back_search_start[%d]=%d\n", op->o_log_prefix, candidate, retcode );	return retcode;}intmeta_back_search( Operation *op, SlapReply *rs ){	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;	metaconn_t	*mc;	struct timeval	save_tv = { 0, 0 },			tv;	time_t		stoptime = (time_t)(-1),			lastres_time = slap_get_time(),			timeout = 0;	int		rc = 0, sres = LDAP_SUCCESS;	char		*matched = NULL;	int		last = 0, ncandidates = 0,			initial_candidates = 0, candidate_match = 0,			needbind = 0;	ldap_back_send_t	sendok = LDAP_BACK_SENDERR;	long		i;	dncookie	dc;	int		is_ok = 0;	void		*savepriv;	SlapReply	*candidates = meta_back_candidates_get( op );	/*	 * controls are set in ldap_back_dobind()	 * 	 * FIXME: in case of values return filter, we might want	 * to map attrs and maybe rewrite value	 */getconn:;	mc = meta_back_getconn( op, rs, NULL, sendok );	if ( !mc ) {		return rs->sr_err;	}	dc.conn = op->o_conn;	dc.rs = rs;	/*	 * Inits searches	 */	for ( i = 0; i < mi->mi_ntargets; i++ ) {		/* reset sr_msgid; it is used in most loops		 * to check if that target is still to be considered */		candidates[ i ].sr_msgid = META_MSGID_IGNORE;		/* a target is marked as candidate by meta_back_getconn();		 * if for any reason (an error, it's over or so) it is		 * no longer active, sr_msgid is set to META_MSGID_IGNORE		 * but it remains candidate, which means it has been active		 * at some point during the operation.  This allows to 		 * use its response code and more to compute the final		 * response */		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {			continue;		}		candidates[ i ].sr_matched = NULL;		candidates[ i ].sr_text = NULL;		candidates[ i ].sr_ref = NULL;		candidates[ i ].sr_ctrls = NULL;		/* get largest timeout among candidates */		if ( mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ]			&& mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ] > timeout )		{			timeout = mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ];		}	}	for ( i = 0; i < mi->mi_ntargets; i++ ) {		if ( !META_IS_CANDIDATE( &candidates[ i ] )			|| candidates[ i ].sr_err != LDAP_SUCCESS )		{			continue;		}		switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )		{		case META_SEARCH_NOT_CANDIDATE:			candidates[ i ].sr_msgid = META_MSGID_IGNORE;			break;		case META_SEARCH_NEED_BIND:			++needbind;			/* fallthru */		case META_SEARCH_CANDIDATE:		case META_SEARCH_BINDING:			candidates[ i ].sr_type = REP_INTERMEDIATE;			++ncandidates;			break;		case META_SEARCH_ERR:			savepriv = op->o_private;			op->o_private = (void *)i;			send_ldap_result( op, rs );			op->o_private = savepriv;			rc = -1;			goto finish;		default:			assert( 0 );			break;		}	}	if ( ncandidates > 0 && needbind == ncandidates ) {		/*		 * give up the second time...		 *		 * NOTE: this should not occur the second time, since a fresh		 * connection has ben created; however, targets may also		 * need bind because the bind timed out or so.		 */		if ( sendok & LDAP_BACK_BINDING ) {			Debug( LDAP_DEBUG_ANY,				"%s meta_back_search: unable to initialize conn\n",				op->o_log_prefix, 0, 0 );			rs->sr_err = LDAP_UNAVAILABLE;			rs->sr_text = "unable to initialize connection to remote targets";			send_ldap_result( op, rs );			rc = -1;			goto finish;		}		/* FIXME: better create a separate connection? */		sendok |= LDAP_BACK_BINDING;#ifdef DEBUG_205		Debug( LDAP_DEBUG_ANY, "*** %s drop mc=%p create new connection\n",			op->o_log_prefix, (void *)mc, 0 );#endif /* DEBUG_205 */		meta_back_release_conn( mi, mc );		mc = NULL;		needbind = 0;		ncandidates = 0;		goto getconn;	}	initial_candidates = ncandidates;	if ( StatslogTest( LDAP_DEBUG_TRACE ) ) {		char	cnd[ SLAP_TEXT_BUFLEN ];		int	c;		for ( c = 0; c < mi->mi_ntargets; c++ ) {			if ( META_IS_CANDIDATE( &candidates[ c ] ) ) {				cnd[ c ] = '*';			} else {				cnd[ c ] = ' ';			}		}		cnd[ c ] = '\0';		Debug( LDAP_DEBUG_TRACE, "%s meta_back_search: ncandidates=%d "			"cnd=\"%s\"\n", op->o_log_prefix, ncandidates, cnd );	}	if ( initial_candidates == 0 ) {		/* NOTE: here we are not sending any matchedDN;		 * this is intended, because if the back-meta		 * is serving this search request, but no valid		 * candidate could be looked up, it means that		 * there is a hole in the mapping of the targets		 * and thus no knowledge of any remote superior		 * is available */		Debug( LDAP_DEBUG_ANY, "%s meta_back_search: "			"base=\"%s\" scope=%d: "			"no candidate could be selected\n",			op->o_log_prefix, op->o_req_dn.bv_val,			op->ors_scope );		/* FIXME: we're sending the first error we encounter;		 * maybe we should pick the worst... */		rc = LDAP_NO_SUCH_OBJECT;		for ( i = 0; i < mi->mi_ntargets; i++ ) {			if ( META_IS_CANDIDATE( &candidates[ i ] )				&& candidates[ i ].sr_err != LDAP_SUCCESS )			{				rc = candidates[ i ].sr_err;				break;			}		}		send_ldap_error( op, rs, rc, NULL );		goto finish;	}	/* We pull apart the ber result, stuff it into a slapd entry, and	 * let send_search_entry stuff it back into ber format. Slow & ugly,	 * but this is necessary for version matching, and for ACL processing.	 */	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {		stoptime = op->o_time + op->ors_tlimit;	}	/*	 * In case there are no candidates, no cycle takes place...	 *	 * FIXME: we might use a queue, to better balance the load 	 * among the candidates	 */	for ( rc = 0; ncandidates > 0; ) {		int	gotit = 0,			doabandon = 0,			alreadybound = ncandidates;		/* check timeout */		if ( timeout && lastres_time > 0			&& ( slap_get_time() - lastres_time ) > timeout )		{			doabandon = 1;			rs->sr_text = "Operation timed out";			rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?				LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;			savepriv = op->o_private;			op->o_private = (void *)i;			send_ldap_result( op, rs );			op->o_private = savepriv;			goto finish;		}		/* check time limit */		if ( op->ors_tlimit != SLAP_NO_LIMIT				&& slap_get_time() > stoptime )		{			doabandon = 1;			rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;			savepriv = op->o_private;			op->o_private = (void *)i;			send_ldap_result( op, rs );			op->o_private = savepriv;			goto finish;		}		for ( i = 0; i < mi->mi_ntargets; i++ ) {			meta_search_candidate_t	retcode = META_SEARCH_UNDEFINED;			metasingleconn_t	*msc = &mc->mc_conns[ i ];			LDAPMessage		*res = NULL, *msg;			/* if msgid is invalid, don't ldap_result() */			if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {				continue;			}			/* if target still needs bind, retry */			if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND ) {				/* initiate dobind */				retcode = meta_search_dobind_init( op, rs, &mc, i, candidates );				Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%ld]=%d\n",					op->o_log_prefix, i, retcode );				switch ( retcode ) {				case META_SEARCH_NEED_BIND:					alreadybound--;					/* fallthru */				case META_SEARCH_BINDING:					break;				case META_SEARCH_ERR:					candidates[ i ].sr_err = rs->sr_err;					if ( META_BACK_ONERR_STOP( mi ) ) {						savepriv = op->o_private;						op->o_private = (void *)i;						send_ldap_result( op, rs );						op->o_private = savepriv;						goto finish;					}					/* fallthru */				case META_SEARCH_NOT_CANDIDATE:					/*					 * When no candidates are left,					 * the outer cycle finishes					 */					candidates[ i ].sr_msgid = META_MSGID_IGNORE;					assert( ncandidates > 0 );					--ncandidates;					break;				case META_SEARCH_CANDIDATE:					candidates[ i ].sr_msgid = META_MSGID_IGNORE;					switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )					{					case META_SEARCH_CANDIDATE:						assert( candidates[ i ].sr_msgid >= 0 );						break;					case META_SEARCH_ERR:						candidates[ i ].sr_err = rs->sr_err;						if ( META_BACK_ONERR_STOP( mi ) ) {							savepriv = op->o_private;							op->o_private = (void *)i;							send_ldap_result( op, rs );							op->o_private = savepriv;							goto finish;						}						/* fallthru */					case META_SEARCH_NOT_CANDIDATE:						/* means that meta_back_search_start()						 * failed but onerr == continue */						candidates[ i ].sr_msgid = META_MSGID_IGNORE;						assert( ncandidates > 0 );						--ncandidates;						break;					default:						/* impossible */						assert( 0 );						break;					}					break;				default:					/* impossible */					assert( 0 );					break;				}				continue;			}			/* check for abandon */			if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {				break;			}#ifdef DEBUG_205			if ( msc->msc_ld == NULL ) {				char	buf[ SLAP_TEXT_BUFLEN ];				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );				snprintf( buf, sizeof( buf ),					"%s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n",					op->o_log_prefix, (long)i, (void *)mc,					candidates[ i ].sr_msgid,					META_IS_BINDING( &candidates[ i ] ) ? " binding" : "",					LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ? " connbinding" : "",					META_BACK_CONN_CREATING( &mc->mc_conns[ i ] ) ? " conncreating" : "" );				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );									Debug( LDAP_DEBUG_ANY, "!!! %s\n", buf, 0, 0 );			}#endif /* DEBUG_205 */						/*			 * FIXME: handle time limit as well?			 * Note that target servers are likely 			 * to handle it, so at some time we'll			 * get a LDAP_TIMELIMIT_EXCEEDED from			 * one of them ...			 */			tv = save_tv;			rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,					LDAP_MSG_RECEIVED, &tv, &res );			switch ( rc ) {			case 0:				/* FIXME: res should not need to be freed */				assert( res == NULL );				continue;			case -1:really_bad:;				/* something REALLY bad happened! */				if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {					candidates[ i ].sr_type = REP_RESULT;					if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {						candidates[ i ].sr_msgid = META_MSGID_IGNORE;						switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )						{							/* means that failed but onerr == continue */						case META_SEARCH_NOT_CANDIDATE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -