Пример #1
0
/* See if base is a child of any of the scopes
 */
int
mdb_idscopes(
	Operation *op,
	IdScopes *isc )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_dbi dbi = mdb->mi_dn2id;
	MDB_val		key, data;
	ID id, prev;
	ID2 id2;
	char	*ptr;
	int		rc = 0;
	unsigned int x;
	unsigned int nrlen, rlen;
	diskNode *d;

	key.mv_size = sizeof(ID);

	if ( !isc->mc ) {
		rc = mdb_cursor_open( isc->mt, dbi, &isc->mc );
		if ( rc ) return rc;
	}

	id = isc->id;

	/* Catch entries from deref'd aliases */
	x = mdb_id2l_search( isc->scopes, id );
	if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) {
		isc->nscope = x;
		return MDB_SUCCESS;
	}

	isc->sctmp[0].mid = 0;
	while (id) {
		if ( !rc ) {
			key.mv_data = &id;
			rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
			if ( rc )
				return rc;

			/* save RDN info */
		}
		d = data.mv_data;
		nrlen = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
		rlen = data.mv_size - sizeof(diskNode) - nrlen;
		isc->nrdns[isc->numrdns].bv_len = nrlen;
		isc->nrdns[isc->numrdns].bv_val = d->nrdn;
		isc->rdns[isc->numrdns].bv_len = rlen;
		isc->rdns[isc->numrdns].bv_val = d->nrdn+nrlen+1;
		isc->numrdns++;

		if (!rc && id != isc->id) {
			/* remember our chain of parents */
			id2.mid = id;
			id2.mval = data;
			rc = mdb_id2l_insert( isc->sctmp, &id2 );
			assert(rc == 0);
		}
		ptr = data.mv_data;
		ptr += data.mv_size - sizeof(ID);
		prev = id;
		memcpy( &id, ptr, sizeof(ID) );
		/* If we didn't advance, some parent is missing */
		if ( id == prev )
			return MDB_NOTFOUND;

		x = mdb_id2l_search( isc->scopes, id );
		if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) {
			if ( !isc->scopes[x].mval.mv_data ) {
				/* This node is in scope, add parent chain to scope */
				int i;
				for ( i = 1; i <= isc->sctmp[0].mid; i++ ) {
					rc = mdb_id2l_insert( isc->scopes, &isc->sctmp[i] );
					if ( rc )
						break;
				}
				/* check id again since inserts may have changed its position */
				if ( isc->scopes[x].mid != id )
					x = mdb_id2l_search( isc->scopes, id );
				isc->nscope = x;
				return MDB_SUCCESS;
			}
			data = isc->scopes[x].mval;
			rc = 1;
		}
		if ( op->ors_scope == LDAP_SCOPE_ONELEVEL )
			break;
	}
	return MDB_SUCCESS;
}
Пример #2
0
/* Look for and dereference all aliases within the search scope.
 * Requires "stack" to be able to hold 6 levels of DB_SIZE IDLs.
 * Of course we're hardcoded to require a minimum of 8 UM_SIZE
 * IDLs so this is never a problem.
 */
static int search_aliases(
	Operation *op,
	SlapReply *rs,
	ID e_id,
	IdScopes *isc,
	MDB_cursor *mci,
	ID *stack )
{
	ID *aliases, *curscop, *visited, *newsubs, *oldsubs, *tmp;
	ID cursora, ida, cursoro, ido;
	Entry *matched, *a;
	struct berval bv_alias = BER_BVC( "alias" );
	AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
	Filter	af;
	int first = 1;

	aliases = stack;	/* IDL of all aliases in the database */
	curscop = aliases + MDB_IDL_DB_SIZE;	/* Aliases in the current scope */
	visited = curscop + MDB_IDL_DB_SIZE;	/* IDs we've seen in this search */
	newsubs = visited + MDB_IDL_DB_SIZE;	/* New subtrees we've added */
	oldsubs = newsubs + MDB_IDL_DB_SIZE;	/* Subtrees added previously */
	tmp = oldsubs + MDB_IDL_DB_SIZE;	/* Scratch space for deref_base() */

	af.f_choice = LDAP_FILTER_EQUALITY;
	af.f_ava = &aa_alias;
	af.f_av_desc = slap_schema.si_ad_objectClass;
	af.f_av_value = bv_alias;
	af.f_next = NULL;

	/* Find all aliases in database */
	MDB_IDL_ZERO( aliases );
	rs->sr_err = mdb_filter_candidates( op, isc->mt, &af, aliases,
		curscop, visited );
	if (rs->sr_err != LDAP_SUCCESS || MDB_IDL_IS_ZERO( aliases )) {
		return rs->sr_err;
	}
	oldsubs[0] = 1;
	oldsubs[1] = e_id;

	MDB_IDL_ZERO( visited );
	MDB_IDL_ZERO( newsubs );

	cursoro = 0;
	ido = mdb_idl_first( oldsubs, &cursoro );

	for (;;) {
		/* Set curscop to only the aliases in the current scope. Start with
		 * all the aliases, then get the intersection with the scope.
		 */
		rs->sr_err = mdb_idscope( op, isc->mt, e_id, aliases, curscop );

		/* Dereference all of the aliases in the current scope. */
		cursora = 0;
		for (ida = mdb_idl_first(curscop, &cursora); ida != NOID;
			ida = mdb_idl_next(curscop, &cursora))
		{
			rs->sr_err = mdb_id2entry(op, mci, ida, &a);
			if (rs->sr_err != LDAP_SUCCESS) {
				continue;
			}

			/* This should only happen if the curscop IDL has maxed out and
			 * turned into a range that spans IDs indiscriminately
			 */
			if (!is_entry_alias(a)) {
				mdb_entry_return(op, a);
				continue;
			}

			/* Actually dereference the alias */
			MDB_IDL_ZERO(tmp);
			a = deref_base( op, rs, a, &matched, isc->mt,
				tmp, visited );
			if (a) {
				/* If the target was not already in our current scopes,
				 * make note of it in the newsubs list.
				 */
				ID2 mid;
				mid.mid = a->e_id;
				mid.mval.mv_data = NULL;
				if (op->ors_scope == LDAP_SCOPE_SUBTREE) {
					isc->id = a->e_id;
					/* if ID is a child of any of our current scopes,
					 * ignore it, it's already included.
					 */
					if (mdb_idscopechk(op, isc))
						goto skip;
				}
				if (mdb_id2l_insert(isc->scopes, &mid) == 0) {
					mdb_idl_insert(newsubs, a->e_id);
				}
skip:			mdb_entry_return( op, a );

			} else if (matched) {
				/* Alias could not be dereferenced, or it deref'd to
				 * an ID we've already seen. Ignore it.
				 */
				mdb_entry_return( op, matched );
				rs->sr_text = NULL;
				rs->sr_err = 0;
			}
		}
		/* If this is a OneLevel search, we're done; oldsubs only had one
		 * ID in it. For a Subtree search, oldsubs may be a list of scope IDs.
		 */
		if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) break;
nextido:
		ido = mdb_idl_next( oldsubs, &cursoro );
		
		/* If we're done processing the old scopes, did we add any new
		 * scopes in this iteration? If so, go back and do those now.
		 */
		if (ido == NOID) {
			if (MDB_IDL_IS_ZERO(newsubs)) break;
			MDB_IDL_CPY(oldsubs, newsubs);
			MDB_IDL_ZERO(newsubs);
			cursoro = 0;
			ido = mdb_idl_first( oldsubs, &cursoro );
		}

		/* Find the entry corresponding to the next scope. If it can't
		 * be found, ignore it and move on. This should never happen;
		 * we should never see the ID of an entry that doesn't exist.
		 */
		{
			MDB_val edata;
			rs->sr_err = mdb_id2edata(op, mci, ido, &edata);
			if ( rs->sr_err != MDB_SUCCESS ) {
				goto nextido;
			}
			e_id = ido;
		}
	}
	return rs->sr_err;
}
Пример #3
0
/* See if base is a child of any of the scopes
 */
int
mdb_idscopes(
	Operation *op,
	IdScopes *isc )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_dbi dbi = mdb->mi_dn2id;
	MDB_val		key, data;
	ID id;
	ID2 id2;
	char	*ptr;
	int		rc = 0;
	unsigned int x;
	unsigned int nrlen, rlen;
	diskNode *d;

	key.mv_size = sizeof(ID);

	if ( !isc->mc ) {
		rc = mdb_cursor_open( isc->mt, dbi, &isc->mc );
		if ( rc ) return rc;
	}

	id = isc->id;
	while (id) {
		if ( !rc ) {
			key.mv_data = &id;
			rc = mdb_cursor_get( isc->mc, &key, &data, MDB_SET );
			if ( rc )
				return rc;

			/* save RDN info */
		}
		d = data.mv_data;
		nrlen = (d->nrdnlen[0] << 8) | d->nrdnlen[1];
		rlen = data.mv_size - sizeof(diskNode) - nrlen;
		isc->nrdns[isc->numrdns].bv_len = nrlen;
		isc->nrdns[isc->numrdns].bv_val = d->nrdn;
		isc->rdns[isc->numrdns].bv_len = rlen;
		isc->rdns[isc->numrdns].bv_val = d->nrdn+nrlen+1;
		isc->numrdns++;

		if (!rc && id != isc->id) {
			id2.mid = id;
			id2.mval = data;
			mdb_id2l_insert( isc->scopes, &id2 );
		}
		ptr = data.mv_data;
		ptr += data.mv_size - sizeof(ID);
		memcpy( &id, ptr, sizeof(ID) );
		x = mdb_id2l_search( isc->scopes, id );
		if ( x <= isc->scopes[0].mid && isc->scopes[x].mid == id ) {
			if ( !isc->scopes[x].mval.mv_data ) {
				isc->nscope = x;
				return MDB_SUCCESS;
			}
			data = isc->scopes[x].mval;
			rc = 1;
		}
		if ( op->ors_scope == LDAP_SCOPE_ONELEVEL )
			break;
	}
	return MDB_SUCCESS;
}