Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • openldap/openldap
  • hyc/openldap
  • ryan/openldap
  • iboukris/openldap
  • ondra/openldap
  • sshanks-kx/openldap
  • blaggacao/openldap
  • pbrezina/openldap
  • quanah/openldap
  • dragos_h/openldap
  • lorenz/openldap
  • tsaarni/openldap
  • fei.ding/openldap
  • orent/openldap
  • arrowplum/openldap
  • barchiesi/openldap
  • jotik/openldap
  • hamano/openldap
  • ingovoss/openldap
  • henson/openldap
  • jlrine2/openldap
  • howeverAT/openldap
  • nivanova/openldap
  • orbea/openldap
  • rdubner/openldap
  • smckinney/openldap
  • jklowden/openldap
  • dpa-openldap/openldap
  • rouzier/openldap
  • orgads/openldap
  • ffontaine/openldap
  • jiaqingz/openldap
  • dcoutadeur/openldap
  • begeragus/openldap
  • pubellit/openldap
  • glandium/openldap
  • facboy/openldap
  • thesamesam/openldap
  • Johan/openldap
  • fkooman/openldap
  • gburd/openldap
  • h-homma/openldap
  • sgallagher/openldap
  • ahmed_zaki/openldap
  • gnoe/openldap
  • mid/openldap
  • clan/openldap
47 results
Show changes
Showing
with 477 additions and 155 deletions
......@@ -93,7 +93,6 @@ txnReturn:
ctrls[num_ctrls] = 0;
/* check entry's schema */
rs->sr_err = entry_schema_check( op, op->oq_add.rs_e, NULL,
get_relax(op), 1, &rs->sr_text, textbuf, textlen );
......@@ -130,7 +129,8 @@ retry: /* transaction retry */
}
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
......@@ -159,12 +159,12 @@ retry: /* transaction retry */
locker = TXN_ID ( ltid );
opinfo.boi_bdb = op->o_bd;
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
/*
* Get the parent dn and see if the corresponding entry exists.
*/
......@@ -439,7 +439,8 @@ retry: /* transaction retry */
}
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
if ( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
......@@ -465,7 +466,9 @@ return_results:
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
op->o_private = NULL;
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
if( success == LDAP_SUCCESS ) {
/* We own the entry now, and it can be purged at will
......
......@@ -292,6 +292,7 @@ bdb_attr_index_config(
b->ai_indexmask = b->ai_newmask;
b->ai_newmask = a->ai_newmask;
ch_free( a );
rc = 0;
continue;
}
fprintf( stderr,
......
......@@ -267,7 +267,7 @@ struct bdb_lock_info {
};
struct bdb_op_info {
BackendDB* boi_bdb;
OpExtra boi_oe;
DB_TXN* boi_txn;
u_int32_t boi_err;
int boi_acl_cache;
......
......@@ -925,7 +925,7 @@ load1:
if (( flag & ID_NOCACHE ) &&
( bdb_cache_entryinfo_trylock( *eip ) == 0 )) {
/* Set the cached state only if no other thread
* found the info while we was loading the entry.
* found the info while we were loading the entry.
*/
if ( (*eip)->bei_finders == 1 )
(*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
......@@ -1257,18 +1257,19 @@ bdb_cache_delete(
assert( e->e_private != NULL );
/* Lock the entry's info */
bdb_cache_entryinfo_lock( ei );
/* Set this early, warn off any queriers */
ei->bei_state |= CACHE_ENTRY_DELETED;
/* Lock the entry's info */
bdb_cache_entryinfo_lock( ei );
bdb_cache_entryinfo_unlock( ei );
/* Get write lock on the data */
rc = bdb_cache_entry_db_relock( bdb, locker, ei, 1, 0, lock );
if ( rc ) {
/* couldn't lock, undo and give up */
ei->bei_state ^= CACHE_ENTRY_DELETED;
bdb_cache_entryinfo_unlock( ei );
return rc;
}
......@@ -1283,8 +1284,6 @@ bdb_cache_delete(
/* free lru mutex */
ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
/* Leave entry info locked */
return( rc );
}
......@@ -1293,6 +1292,8 @@ bdb_cache_delete_cleanup(
Cache *cache,
EntryInfo *ei )
{
/* Enter with ei locked */
if ( ei->bei_e ) {
ei->bei_e->e_private = NULL;
#ifdef SLAP_ZONE_ALLOC
......
......@@ -124,7 +124,8 @@ retry: /* transaction retry */
0, 0, 0 );
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
......@@ -155,11 +156,11 @@ retry: /* transaction retry */
locker = TXN_ID ( ltid );
opinfo.boi_bdb = op->o_bd;
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) {
dnParent( &op->o_req_ndn, &pdn );
......@@ -536,7 +537,8 @@ retry: /* transaction retry */
rs->sr_err = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Committed delete %s(%d)",
e->e_nname.bv_val, e->e_id );
......@@ -572,6 +574,7 @@ return_results:
if( e != NULL ) {
if ( rs->sr_err == LDAP_SUCCESS ) {
/* Free the EntryInfo and the Entry */
bdb_cache_entryinfo_lock( BEI(e) );
bdb_cache_delete_cleanup( &bdb->bi_cache, BEI(e) );
} else {
bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
......@@ -581,7 +584,9 @@ return_results:
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
op->o_private = NULL;
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
send_ldap_result( op, rs );
slap_graduate_commit_csn( op );
......
......@@ -1156,7 +1156,11 @@ gotit:
}
cx->depth--;
cx->op->o_tmpfree( save, cx->op->o_tmpmemctx );
if ( nokids ) ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
if ( nokids ) {
bdb_cache_entryinfo_lock( ei );
ei->bei_state |= CACHE_ENTRY_NO_GRANDKIDS;
bdb_cache_entryinfo_unlock( ei );
}
}
/* Make sure caller knows it had kids! */
cx->tmp[0]=1;
......
......@@ -242,7 +242,8 @@ int bdb_entry_release(
int rw )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
struct bdb_op_info *boi = NULL;
struct bdb_op_info *boi;
OpExtra *oex;
/* slapMode : SLAP_SERVER_MODE, SLAP_TOOL_MODE,
SLAP_TRUNCATE_MODE, SLAP_UNDEFINED_MODE */
......@@ -257,7 +258,10 @@ int bdb_entry_release(
#endif
}
/* free entry and reader or writer lock */
boi = (struct bdb_op_info *)op->o_private;
LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
if ( oex->oe_key == bdb ) break;
}
boi = (struct bdb_op_info *)oex;
/* lock is freed with txn */
if ( !boi || boi->boi_txn ) {
......@@ -274,8 +278,8 @@ int bdb_entry_release(
}
}
if ( !boi->boi_locks ) {
LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
op->o_tmpfree( boi, op->o_tmpmemctx );
op->o_private = NULL;
}
}
} else {
......@@ -328,9 +332,14 @@ int bdb_entry_get(
"=> bdb_entry_get: oc: \"%s\", at: \"%s\"\n",
oc ? oc->soc_cname.bv_val : "(null)", at_name, 0);
if( op ) boi = (struct bdb_op_info *) op->o_private;
if( boi != NULL && op->o_bd->be_private == boi->boi_bdb->be_private ) {
txn = boi->boi_txn;
if( op ) {
OpExtra *oex;
LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
if ( oex->oe_key == bdb ) break;
}
boi = (struct bdb_op_info *)oex;
if ( boi )
txn = boi->boi_txn;
}
if ( txn != NULL ) {
......@@ -407,8 +416,8 @@ return_results:
if ( op ) {
if ( !boi ) {
boi = op->o_tmpcalloc(1,sizeof(struct bdb_op_info),op->o_tmpmemctx);
boi->boi_bdb = op->o_bd;
op->o_private = boi;
boi->boi_oe.oe_key = bdb;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &boi->boi_oe, oe_next );
}
if ( !boi->boi_txn ) {
struct bdb_lock_info *bli;
......
......@@ -410,7 +410,8 @@ retry: /* transaction retry */
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
......@@ -439,11 +440,11 @@ retry: /* transaction retry */
locker = TXN_ID ( ltid );
opinfo.boi_bdb = op->o_bd;
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
/* get entry or ancestor */
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
......@@ -666,7 +667,8 @@ retry: /* transaction retry */
rs->sr_err = TXN_COMMIT( ltid, 0 );
}
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
if( rs->sr_err != 0 ) {
Debug( LDAP_DEBUG_TRACE,
......@@ -705,7 +707,9 @@ done:
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
op->o_private = NULL;
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
if( e != NULL ) {
bdb_unlocked_cache_return_entry_w (&bdb->bi_cache, e);
......
......@@ -134,7 +134,8 @@ retry: /* transaction retry */
rs->sr_err = TXN_ABORT( ltid );
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
op->o_do_not_cache = opinfo.boi_acl_cache;
if( rs->sr_err != 0 ) {
rs->sr_err = LDAP_OTHER;
......@@ -165,11 +166,11 @@ retry: /* transaction retry */
locker = TXN_ID ( ltid );
opinfo.boi_bdb = op->o_bd;
opinfo.boi_oe.oe_key = bdb;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
opinfo.boi_acl_cache = op->o_do_not_cache;
op->o_private = &opinfo;
LDAP_SLIST_INSERT_HEAD( &op->o_extra, &opinfo.boi_oe, oe_next );
/* get entry */
rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei, 1,
......@@ -764,7 +765,8 @@ retry: /* transaction retry */
}
ltid = NULL;
op->o_private = NULL;
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
opinfo.boi_oe.oe_key = NULL;
if( rs->sr_err != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_TRACE,
......@@ -823,7 +825,9 @@ done:
if( ltid != NULL ) {
TXN_ABORT( ltid );
}
op->o_private = NULL;
if ( opinfo.boi_oe.oe_key ) {
LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.boi_oe, OpExtra, oe_next );
}
if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) {
slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx );
......
......@@ -395,7 +395,7 @@ bdb_monitor_db_open( BackendDB *be )
{
struct berval bv, nbv;
ber_len_t pathlen = 0, len = 0;
char path[ PATH_MAX ] = { '\0' };
char path[ MAXPATHLEN ] = { '\0' };
char *fname = bdb->bi_dbenv_home,
*ptr;
......
......@@ -322,11 +322,16 @@ bdb_search( Operation *op, SlapReply *rs )
DB_LOCK lock;
struct bdb_op_info *opinfo = NULL;
DB_TXN *ltid = NULL;
OpExtra *oex;
Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n", 0, 0, 0);
attrs = op->oq_search.rs_attrs;
opinfo = (struct bdb_op_info *) op->o_private;
LDAP_SLIST_FOREACH( oex, &op->o_extra, oe_next ) {
if ( oex->oe_key == bdb )
break;
}
opinfo = (struct bdb_op_info *) oex;
manageDSAit = get_manageDSAit( op );
......
......@@ -773,8 +773,9 @@ ldap_back_entry_get(
ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
ldapconn_t *lc = NULL;
int rc = 1,
int rc,
do_not_cache;
ber_tag_t tag;
struct berval bdn;
LDAPMessage *result = NULL,
*e = NULL;
......@@ -788,12 +789,18 @@ ldap_back_entry_get(
/* Tell getconn this is a privileged op */
do_not_cache = op->o_do_not_cache;
tag = op->o_tag;
/* do not cache */
op->o_do_not_cache = 1;
if ( !ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
op->o_do_not_cache = do_not_cache;
/* ldap_back_entry_get() is an entry lookup, so it does not need
* to know what the entry is being looked up for */
op->o_tag = LDAP_REQ_SEARCH;
rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND );
op->o_do_not_cache = do_not_cache;
op->o_tag = tag;
if ( !rc ) {
return rs.sr_err;
}
op->o_do_not_cache = do_not_cache;
if ( at ) {
attrp = attr;
......
......@@ -1239,7 +1239,7 @@ idassert-authzFrom "dn:<rootdn>"
return 1;
}
if ( mi->mi_ntargets ) {
if ( mi->mi_ntargets == 0 ) {
mi->mi_flags |= LDAP_BACK_F_QUARANTINE;
} else {
......
......@@ -154,13 +154,18 @@ monitor_cache_get(
*ep = NULL;
tmp_mc.mc_ndn = *ndn;
retry:;
ldap_pvt_thread_mutex_lock( &mi->mi_cache_mutex );
mc = ( monitor_cache_t * )avl_find( mi->mi_cache,
( caddr_t )&tmp_mc, monitor_cache_cmp );
if ( mc != NULL ) {
/* entry is returned with mutex locked */
monitor_cache_lock( mc->mc_e );
if ( monitor_cache_trylock( mc->mc_e ) ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_cache_mutex );
ldap_pvt_thread_yield();
goto retry;
}
*ep = mc->mc_e;
}
......
......@@ -33,14 +33,6 @@
static int monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e );
#endif /* defined(LDAP_SLAPI) */
/* for PATH_MAX on some systems (e.g. Solaris) */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif /* HAVE_LIMITS_H */
#ifndef PATH_MAX
#define PATH_MAX 4095
#endif /* ! PATH_MAX */
static int
monitor_subsys_database_modify(
Operation *op,
......
......@@ -928,9 +928,9 @@ slapd_clr_write( ber_socket_t s, int wake )
{
ldap_pvt_thread_mutex_lock( &slap_daemon.sd_mutex );
assert( SLAP_SOCK_IS_ACTIVE( s ));
if ( SLAP_SOCK_IS_WRITE( s )) {
assert( SLAP_SOCK_IS_ACTIVE( s ));
SLAP_SOCK_CLR_WRITE( s );
slap_daemon.sd_nwriters--;
}
......@@ -2620,7 +2620,6 @@ slapd_daemon( void )
{
int rc;
connections_init();
#ifdef LDAP_CONNECTIONLESS
connectionless_init();
#endif /* LDAP_CONNECTIONLESS */
......
......@@ -929,6 +929,8 @@ unhandled_option:;
*/
time( &starttime );
connections_init();
if ( slap_startup( NULL ) != 0 ) {
rc = 1;
SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
......
......@@ -1348,7 +1348,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) {
old = li->li_old;
li->li_old = NULL;
/* Disarm mod_cleanup */
for ( cb = op->o_callback->sc_next; cb; cb = cb->sc_next ) {
for ( cb = op->o_callback; cb; cb = cb->sc_next ) {
if ( cb->sc_private == (void *)on ) {
cb->sc_private = NULL;
break;
......
......@@ -41,6 +41,8 @@
#define REGEX_STR "regex"
#define URI_STR "uri"
#define SIZE_STR "size"
#define COUNT_STR "count"
/*
* Linked list of attribute constraints which we should enforce.
......@@ -55,6 +57,8 @@ typedef struct constraint {
AttributeDescription *ap;
regex_t *re;
LDAPURLDesc *lud;
size_t size;
size_t count;
AttributeDescription **attrs;
struct berval val; /* constraint value */
struct berval dn;
......@@ -129,6 +133,12 @@ constraint_cf_gen( ConfigArgs *c )
} else if (cp->lud) {
len += STRLENOF(URI_STR);
tstr = URI_STR;
} else if (cp->size) {
len += STRLENOF(SIZE_STR);
tstr = SIZE_STR;
} else if (cp->count) {
len += STRLENOF(COUNT_STR);
tstr = COUNT_STR;
}
len += cp->val.bv_len;
......@@ -216,7 +226,17 @@ constraint_cf_gen( ConfigArgs *c )
return( ARG_BAD_CONF );
}
ber_str2bv( c->argv[3], 0, 1, &ap.val );
} else if ( strcasecmp( c->argv[2], URI_STR ) == 0) {
} else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) {
size_t size;
if ( ( size = atoi(c->argv[3]) ) != 0 )
ap.size = size;
} else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) {
size_t count;
if ( ( count = atoi(c->argv[3]) ) != 0 )
ap.count = count;
} else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) {
int err;
err = ldap_url_parse(c->argv[3], &ap.lud);
......@@ -281,6 +301,8 @@ constraint_cf_gen( ConfigArgs *c )
a2->re = ap.re;
a2->val = ap.val;
a2->lud = ap.lud;
a2->size = ap.size;
a2->count = ap.count;
if ( a2->lud ) {
ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn);
ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter);
......@@ -323,6 +345,9 @@ constraint_violation( constraint *c, struct berval *bv, Operation *op, SlapReply
(regexec(c->re, bv->bv_val, 0, NULL, 0) == REG_NOMATCH))
return 1; /* regular expression violation */
if ((c->size) && (bv->bv_len > c->size))
return 1; /* size violation */
if (c->lud) {
Operation nop = *op;
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
......@@ -443,10 +468,21 @@ print_message( struct berval *errtext, AttributeDescription *a )
return ret;
}
static unsigned
constraint_count_attr(Entry *e, AttributeDescription *ad)
{
struct Attribute *a;
if ((a = attr_find(e->e_attrs, ad)) != NULL)
return a->a_numvals;
return 0;
}
static int
constraint_add( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
Backend *be = op->o_bd;
Attribute *a;
constraint *c = on->on_bi.bi_private, *cp;
BerVarray b = NULL;
......@@ -469,35 +505,45 @@ constraint_add( Operation *op, SlapReply *rs )
if (cp->ap != a->a_desc) continue;
if ((b = a->a_vals) == NULL) continue;
for(i=0; b[i].bv_val; i++) {
int cv = constraint_violation( cp, &b[i], op, rs);
if (cv) {
/* violation */
op->o_bd->bd_info = (BackendInfo *)(on->on_info);
msg = print_message( &rsv, a->a_desc );
send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
ch_free(msg);
return (rs->sr_err);
}
}
Debug(LDAP_DEBUG_TRACE,
"==> constraint_add, "
"a->a_numvals = %d, cp->count = %d\n",
a->a_numvals, cp->count, 0);
if ((cp->count != 0) && (a->a_numvals > cp->count))
goto add_violation;
for(i=0; b[i].bv_val; i++)
if (constraint_violation( cp, &b[i], op, rs))
goto add_violation;
}
}
/* Default is to just fall through to the normal processing */
return SLAP_CB_CONTINUE;
add_violation:
op->o_bd->bd_info = (BackendInfo *)(on->on_info);
msg = print_message( &rsv, a->a_desc );
send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
ch_free(msg);
return (rs->sr_err);
}
static int
constraint_modify( Operation *op, SlapReply *rs )
{
slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
Backend *be = op->o_bd;
constraint *c = on->on_bi.bi_private, *cp;
Entry *target_entry = NULL;
Modifications *m;
BerVarray b = NULL;
int i;
struct berval rsv = BER_BVC("modify breaks constraint");
char *msg;
Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "constraint_modify()", 0,0,0);
if ((m = op->orm_modlist) == NULL) {
op->o_bd->bd_info = (BackendInfo *)(on->on_info);
send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
......@@ -505,34 +551,96 @@ constraint_modify( Operation *op, SlapReply *rs )
return(rs->sr_err);
}
/* Do we need to count attributes? */
for(cp = c; cp; cp = cp->ap_next) {
if (cp->count != 0) {
int rc;
op->o_bd = on->on_info->oi_origdb;
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &target_entry );
op->o_bd = be;
if (rc != 0 || target_entry == NULL) {
Debug(LDAP_DEBUG_TRACE,
"==> constraint_modify rc = %d\n",
rc, 0, 0);
goto mod_violation;
}
break;
}
}
for(;m; m = m->sml_next) {
int ce = 0;
/* Get this attribute count, if needed */
if (target_entry)
ce = constraint_count_attr(target_entry, m->sml_desc);
if (is_at_operational( m->sml_desc->ad_type )) continue;
if ((( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_ADD) &&
(( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_REPLACE))
(( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_REPLACE) &&
(( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_DELETE))
continue;
/* we only care about ADD and REPLACE modifications */
/* and DELETE are used to track attribute count */
if ((( b = m->sml_values ) == NULL ) || (b[0].bv_val == NULL))
continue;
for(cp = c; cp; cp = cp->ap_next) {
if (cp->ap != m->sml_desc) continue;
for(i=0; b[i].bv_val; i++) {
int cv = constraint_violation( cp, &b[i], op, rs);
if (cv) {
/* violation */
op->o_bd->bd_info = (BackendInfo *)(on->on_info);
msg = print_message( &rsv, m->sml_desc );
send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
ch_free(msg);
return (rs->sr_err);
if (cp->count != 0) {
int ca;
if (m->sml_op == LDAP_MOD_DELETE)
ce = 0;
for (ca = 0; b[ca].bv_val; ++ca);
Debug(LDAP_DEBUG_TRACE,
"==> constraint_modify ce = %d, "
"ca = %d, cp->count = %d\n",
ce, ca, cp->count);
if (m->sml_op == LDAP_MOD_ADD)
if (ca + ce > cp->count)
goto mod_violation;
if (m->sml_op == LDAP_MOD_REPLACE) {
if (ca > cp->count)
goto mod_violation;
ce = ca;
}
}
}
/* DELETE are to be ignored beyond this point */
if (( m->sml_op & LDAP_MOD_OP ) == LDAP_MOD_DELETE)
continue;
for(i=0; b[i].bv_val; i++)
if (constraint_violation( cp, &b[i], op, rs))
goto mod_violation;
}
}
if (target_entry) {
op->o_bd = on->on_info->oi_origdb;
be_entry_release_r(op, target_entry);
op->o_bd = be;
}
return SLAP_CB_CONTINUE;
mod_violation:
/* violation */
if (target_entry) {
op->o_bd = on->on_info->oi_origdb;
be_entry_release_r(op, target_entry);
op->o_bd = be;
}
op->o_bd->bd_info = (BackendInfo *)(on->on_info);
msg = print_message( &rsv, m->sml_desc );
send_ldap_error(op, rs, LDAP_CONSTRAINT_VIOLATION, msg );
ch_free(msg);
return (rs->sr_err);
}
static int
......
......@@ -4,6 +4,7 @@
*
* Copyright 2003-2008 The OpenLDAP Foundation.
* Portions Copyright 2004-2005 Pierangelo Masarati.
* Portions Copyright 2008 Emmanuel Dreyfus.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -60,14 +61,23 @@ static AttributeName *slap_anlist_no_attrs = anlist_no_attrs;
static AttributeDescription *ad_dgIdentity, *ad_dgAuthz;
typedef struct dynlist_map_t {
AttributeDescription *dlm_member_ad;
AttributeDescription *dlm_mapped_ad;
struct dynlist_map_t *dlm_next;
} dynlist_map_t;
typedef struct dynlist_info_t {
ObjectClass *dli_oc;
AttributeDescription *dli_ad;
AttributeDescription *dli_member_ad;
struct dynlist_map_t *dli_dlm;
struct berval dli_default_filter;
struct dynlist_info_t *dli_next;
} dynlist_info_t;
#define DYNLIST_USAGE \
"\"dynlist-attrset <oc> <URL-ad> [[<mapped-ad>:]<member-ad> ...]\": "
static dynlist_info_t *
dynlist_is_dynlist_next( Operation *op, SlapReply *rs, dynlist_info_t *old_dli )
{
......@@ -149,6 +159,7 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
AccessControlState acl_state = ACL_STATE_INIT;
dynlist_sc_t *dlc;
dynlist_map_t *dlm;
if ( rs->sr_type != REP_SEARCH ) {
return 0;
......@@ -167,7 +178,9 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
goto done;
}
if ( dlc->dlc_dli->dli_member_ad ) {
for ( dlm = dlc->dlc_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if (dlm->dlm_mapped_ad != NULL)
continue;
/* if access allowed, try to add values, emulating permissive
* control to silently ignore duplicates */
......@@ -185,8 +198,8 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
BER_BVZERO( &nvals[ 1 ] );
mod.sm_op = LDAP_MOD_ADD;
mod.sm_desc = dlc->dlc_dli->dli_member_ad;
mod.sm_type = dlc->dlc_dli->dli_member_ad->ad_cname;
mod.sm_desc = dlm->dlm_member_ad;
mod.sm_type = dlm->dlm_member_ad->ad_cname;
mod.sm_values = vals;
mod.sm_nvalues = nvals;
mod.sm_numvals = 1;
......@@ -282,15 +295,25 @@ dynlist_sc_update( Operation *op, SlapReply *rs )
Modification mod;
const char *text = NULL;
char textbuf[1024];
dynlist_map_t *dlm;
AttributeDescription *ad;
BER_BVZERO( &vals[j] );
if ( nvals ) {
BER_BVZERO( &nvals[j] );
}
ad = a->a_desc;
for ( dlm = dlc->dlc_dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_member_ad == a->a_desc ) {
ad = dlm->dlm_mapped_ad;
break;
}
}
mod.sm_op = LDAP_MOD_ADD;
mod.sm_desc = a->a_desc;
mod.sm_type = a->a_desc->ad_cname;
mod.sm_desc = ad;
mod.sm_type = ad->ad_cname;
mod.sm_values = vals;
mod.sm_nvalues = nvals;
mod.sm_numvals = j;
......@@ -328,6 +351,7 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
int opattrs,
userattrs;
dynlist_sc_t dlc = { 0 };
dynlist_map_t *dlm;
a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad );
if ( a == NULL ) {
......@@ -344,9 +368,13 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
#endif /* SLAP_OPATTRS */
/* Don't generate member list if it wasn't requested */
if ( dli->dli_member_ad && !userattrs && !ad_inlist( dli->dli_member_ad, rs->sr_attrs ) ) {
return SLAP_CB_CONTINUE;
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( userattrs ||
ad_inlist( dlm->dlm_member_ad, rs->sr_attrs ) )
break;
}
if ( dli->dli_dlm && !dlm )
return SLAP_CB_CONTINUE;
if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) {
Attribute *authz = NULL;
......@@ -393,6 +421,7 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
int i, j;
struct berval dn;
int rc;
dynlist_map_t *dlm;
BER_BVZERO( &o.o_req_dn );
BER_BVZERO( &o.o_req_ndn );
......@@ -431,7 +460,13 @@ dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli )
}
o.ors_scope = lud->lud_scope;
if ( dli->dli_member_ad != NULL ) {
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
if ( dlm->dlm_mapped_ad != NULL ) {
break;
}
}
if ( dli->dli_dlm && !dlm ) {
/* if ( lud->lud_attrs != NULL ),
* the URL should be ignored */
o.ors_attrs = slap_anlist_no_attrs;
......@@ -564,9 +599,14 @@ dynlist_compare( Operation *op, SlapReply *rs )
dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private;
Operation o = *op;
Entry *e = NULL;
dynlist_map_t *dlm;
for ( ; dli != NULL; dli = dli->dli_next ) {
if ( op->oq_compare.rs_ava->aa_desc == dli->dli_member_ad ) {
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next )
if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad )
break;
if ( dli->dli_dlm && dlm ) {
/* This compare is for one of the attributes we're
* interested in. We'll use slapd's existing dyngroup
* evaluator to get the answer we want.
......@@ -834,11 +874,11 @@ dynlist_db_config(
ObjectClass *oc;
AttributeDescription *ad = NULL,
*member_ad = NULL;
dynlist_map_t *dlm = NULL;
const char *text;
if ( argc < 3 || argc > 4 ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
if ( argc < 3 ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: " DYNLIST_USAGE
"invalid arg number #%d.\n",
fname, lineno, argc );
return 1;
......@@ -846,8 +886,7 @@ dynlist_db_config(
oc = oc_find( argv[1] );
if ( oc == NULL ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
Debug( LDAP_DEBUG_ANY, "%s: line %d: " DYNLIST_USAGE
"unable to find ObjectClass \"%s\"\n",
fname, lineno, argv[ 1 ] );
return 1;
......@@ -855,41 +894,90 @@ dynlist_db_config(
rc = slap_str2ad( argv[2], &ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
Debug( LDAP_DEBUG_ANY, "%s: line %d: " DYNLIST_USAGE
"unable to find AttributeDescription \"%s\"\n",
fname, lineno, argv[2] );
return 1;
}
if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
Debug( LDAP_DEBUG_ANY, "%s: line %d: " DYNLIST_USAGE
"AttributeDescription \"%s\" "
"must be a subtype of \"labeledURI\"\n",
fname, lineno, argv[2] );
return 1;
}
if ( argc == 4 ) {
rc = slap_str2ad( argv[3], &member_ad, &text );
for ( i = 3; i < argc; i++ ) {
char *arg;
char *cp;
AttributeDescription *member_ad = NULL;
AttributeDescription *mapped_ad = NULL;
dynlist_map_t *dlmp;
dynlist_map_t *dlml;
/*
* If no mapped attribute is given, dn is used
* for backward compatibility.
*/
arg = argv[i];
if ( cp = strchr( arg, (int)':' ) != NULL ) {
struct berval bv;
ber_str2bv( arg, cp - arg, 0, &bv );
rc = slap_bv2ad( &bv, &mapped_ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
DYNLIST_USAGE
"unable to find mapped AttributeDescription \"%s\"\n",
fname, lineno, arg );
return 1;
}
arg = cp + 1;
}
rc = slap_str2ad( arg, &member_ad, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
DYNLIST_USAGE
"unable to find AttributeDescription \"%s\"\n",
fname, lineno, argv[3] );
fname, lineno, arg );
return 1;
}
dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
if ( dlm == NULL ) {
dlm = dlmp;
dlml = NULL;
}
dlmp->dlm_member_ad = member_ad;
dlmp->dlm_mapped_ad = mapped_ad;
dlmp->dlm_next = NULL;
if ( dlml != NULL )
dlml->dlm_next = dlmp;
dlml = dlmp;
}
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
/* The same URL attribute / member attribute pair
* cannot be repeated */
if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
/*
* The same URL attribute / member attribute pair
* cannot be repeated, but we enforce this only
* when the member attribute is unique. Performing
* the check for multiple values would require
* sorting and comparing the lists, which is left
* as a future improvement
*/
if ( (*dlip)->dli_ad == ad &&
(*dlip)->dli_dlm->dlm_next == NULL &&
dlm->dlm_next == NULL &&
dlm->dlm_member_ad == (*dlip)->dli_dlm->dlm_member_ad &&
dlm->dlm_mapped_ad == (*dlip)->dli_dlm->dlm_mapped_ad ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
DYNLIST_USAGE
"URL attributeDescription \"%s\" already mapped.\n",
fname, lineno, ad->ad_cname.bv_val );
#if 0
......@@ -902,9 +990,18 @@ dynlist_db_config(
*dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );
(*dlip)->dli_oc = oc;
(*dlip)->dli_ad = ad;
(*dlip)->dli_member_ad = member_ad;
(*dlip)->dli_dlm = dlm;
if ( dynlist_build_def_filter( *dlip ) ) {
dynlist_map_t *dlm = (*dlip)->ldi_dlm;
dynlist_map_t *dlm_next;
while ( dlm != NULL ) {
dlm_next = dlm->dlm_next;
ch_free( dlm );
dlm = dlm_next;
}
ch_free( *dlip );
*dlip = NULL;
return 1;
......@@ -965,9 +1062,17 @@ dynlist_db_config(
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
/* The same URL attribute / member attribute pair
* cannot be repeated */
if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
/*
* The same URL attribute / member attribute pair
* cannot be repeated, but we enforce this only
* when the member attribute is unique. Performing
* the check for multiple values would require
* sorting and comparing the lists, which is left
* as a future improvement
*/
if ( (*dlip)->dli_ad == ad &&
(*dlip)->dli_dlm->dlm_next == NULL &&
member_ad == (*dlip)->dli_dlm->dlm_member_ad ) {
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"URL attributeDescription \"%s\" already mapped.\n",
......@@ -982,9 +1087,12 @@ dynlist_db_config(
*dlip = (dynlist_info_t *)ch_calloc( 1, sizeof( dynlist_info_t ) );
(*dlip)->dli_oc = oc;
(*dlip)->dli_ad = ad;
(*dlip)->dli_member_ad = member_ad;
(*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
(*dlip)->dli_dlm->dlm_member_ad = member_ad;
(*dlip)->dli_dlm->dlm_mapped_ad = NULL;
if ( dynlist_build_def_filter( *dlip ) ) {
ch_free( (*dlip)->dli_dlm );
ch_free( *dlip );
*dlip = NULL;
return 1;
......@@ -1007,9 +1115,10 @@ enum {
static ConfigDriver dl_cfgen;
/* XXXmanu 255 is the maximum arguments we allow. Can we go beyond? */
static ConfigTable dlcfg[] = {
{ "dynlist-attrset", "group-oc> <URL-ad> <member-ad",
3, 4, 0, ARG_MAGIC|DL_ATTRSET, dl_cfgen,
3, 255, 0, ARG_MAGIC|DL_ATTRSET, dl_cfgen,
"( OLcfgOvAt:8.1 NAME 'olcDLattrSet' "
"DESC 'Dynamic list: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
"EQUALITY caseIgnoreMatch "
......@@ -1051,6 +1160,7 @@ dl_cfgen( ConfigArgs *c )
for ( i = 0; dli; i++, dli = dli->dli_next ) {
struct berval bv;
char *ptr = c->cr_msg;
dynlist_map_t *dlm;
assert( dli->dli_oc != NULL );
assert( dli->dli_ad != NULL );
......@@ -1060,10 +1170,16 @@ dl_cfgen( ConfigArgs *c )
dli->dli_oc->soc_cname.bv_val,
dli->dli_ad->ad_cname.bv_val );
if ( dli->dli_member_ad != NULL ) {
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
ptr[ 0 ] = ' ';
ptr++;
ptr = lutil_strcopy( ptr, dli->dli_member_ad->ad_cname.bv_val );
if ( dlm->dlm_mapped_ad ) {
ptr = lutil_strcopy( ptr, dlm->dlm_mapped_ad->ad_cname.bv_val );
ptr[ 0 ] = ':';
ptr++;
}
ptr = lutil_strcopy( ptr, dlm->dlm_member_ad->ad_cname.bv_val );
}
bv.bv_val = c->cr_msg;
......@@ -1091,9 +1207,18 @@ dl_cfgen( ConfigArgs *c )
dynlist_info_t *dli_next;
for ( dli_next = dli; dli_next; dli = dli_next ) {
dynlist_map_t *dlm = dli->dli_dlm;
dynlist_map_t *dlm_next;
dli_next = dli->dli_next;
ch_free( dli->dli_default_filter.bv_val );
while ( dlm != NULL ) {
dlm_next = dlm->dlm_next;
ch_free( dlm );
dlm = dlm_next;
}
ch_free( dli );
}
......@@ -1101,6 +1226,8 @@ dl_cfgen( ConfigArgs *c )
} else {
dynlist_info_t **dlip;
dynlist_map_t *dlm;
dynlist_map_t *dlm_next;
for ( i = 0, dlip = (dynlist_info_t **)&on->on_bi.bi_private;
i < c->valx; i++ )
......@@ -1114,6 +1241,13 @@ dl_cfgen( ConfigArgs *c )
dli = *dlip;
*dlip = dli->dli_next;
ch_free( dli->dli_default_filter.bv_val );
dlm = dli->dli_dlm;
while ( dlm != NULL ) {
dlm_next = dlm->dlm_next;
ch_free( dlm );
dlm = dlm_next;
}
ch_free( dli );
dli = (dynlist_info_t *)on->on_bi.bi_private;
......@@ -1138,14 +1272,13 @@ dl_cfgen( ConfigArgs *c )
dynlist_info_t **dlip,
*dli_next = NULL;
ObjectClass *oc = NULL;
AttributeDescription *ad = NULL,
*member_ad = NULL;
AttributeDescription *ad = NULL;
dynlist_map_t *dlm = NULL;
const char *text;
oc = oc_find( c->argv[ 1 ] );
if ( oc == NULL ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
"unable to find ObjectClass \"%s\"",
c->argv[ 1 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
......@@ -1155,8 +1288,7 @@ dl_cfgen( ConfigArgs *c )
rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
if ( rc != LDAP_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
"unable to find AttributeDescription \"%s\"",
c->argv[ 2 ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
......@@ -1165,8 +1297,7 @@ dl_cfgen( ConfigArgs *c )
}
if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
"AttributeDescription \"%s\" "
"must be a subtype of \"labeledURI\"",
c->argv[ 2 ] );
......@@ -1175,36 +1306,59 @@ dl_cfgen( ConfigArgs *c )
return 1;
}
if ( c->argc == 4 ) {
rc = slap_str2ad( c->argv[ 3 ], &member_ad, &text );
for ( i = 3; i < c->argc; i++ ) {
char *arg;
char *cp;
AttributeDescription *member_ad = NULL;
AttributeDescription *mapped_ad = NULL;
dynlist_map_t *dlmp;
dynlist_map_t *dlml;
/*
* If no mapped attribute is given, dn is used
* for backward compatibility.
*/
arg = c->argv[i];
if ( ( cp = strchr( arg, ':' ) ) != NULL ) {
struct berval bv;
ber_str2bv( arg, cp - arg, 0, &bv );
rc = slap_bv2ad( &bv, &mapped_ad, &text );
if ( rc != LDAP_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
DYNLIST_USAGE
"unable to find mapped AttributeDescription #%d \"%s\"\n",
i - 3, c->argv[ i ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
arg = cp + 1;
}
rc = slap_str2ad( arg, &member_ad, &text );
if ( rc != LDAP_SUCCESS ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"unable to find AttributeDescription \"%s\"\n",
c->argv[ 3 ] );
DYNLIST_USAGE
"unable to find AttributeDescription #%d \"%s\"\n",
i - 3, c->argv[ i ] );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
return 1;
}
}
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
/* The same URL attribute / member attribute pair
* cannot be repeated */
if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
"URL attributeDescription \"%s\" already mapped.\n",
ad->ad_cname.bv_val );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
c->log, c->cr_msg, 0 );
#if 0
/* make it a warning... */
return 1;
#endif
dlmp = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
if ( dlm == NULL ) {
dlm = dlmp;
dlml = NULL;
}
dlmp->dlm_member_ad = member_ad;
dlmp->dlm_mapped_ad = mapped_ad;
dlmp->dlm_next = NULL;
if ( dlml != NULL )
dlml->dlm_next = dlmp;
dlml = dlmp;
}
if ( c->valx > 0 ) {
......@@ -1215,7 +1369,7 @@ dl_cfgen( ConfigArgs *c )
{
if ( *dlip == NULL ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
DYNLIST_USAGE
"invalid index {%d}\n",
c->valx );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
......@@ -1236,7 +1390,7 @@ dl_cfgen( ConfigArgs *c )
(*dlip)->dli_oc = oc;
(*dlip)->dli_ad = ad;
(*dlip)->dli_member_ad = member_ad;
(*dlip)->dli_dlm = dlm;
(*dlip)->dli_next = dli_next;
rc = dynlist_build_def_filter( *dlip );
......@@ -1291,7 +1445,7 @@ dl_cfgen( ConfigArgs *c )
if ( !is_at_subtype( ad->ad_type, slap_schema.si_ad_labeledURI->ad_type ) ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrset <oc> <URL-ad> [<member-ad>]\": "
DYNLIST_USAGE
"AttributeDescription \"%s\" "
"must be a subtype of \"labeledURI\"",
c->argv[ 2 ] );
......@@ -1303,9 +1457,17 @@ dl_cfgen( ConfigArgs *c )
for ( dlip = (dynlist_info_t **)&on->on_bi.bi_private;
*dlip; dlip = &(*dlip)->dli_next )
{
/* The same URL attribute / member attribute pair
* cannot be repeated */
if ( (*dlip)->dli_ad == ad && (*dlip)->dli_member_ad == member_ad ) {
/*
* The same URL attribute / member attribute pair
* cannot be repeated, but we enforce this only
* when the member attribute is unique. Performing
* the check for multiple values would require
* sorting and comparing the lists, which is left
* as a future improvement
*/
if ( (*dlip)->dli_ad == ad &&
(*dlip)->dli_dlm->dlm_next == NULL &&
member_ad == (*dlip)->dli_dlm->dlm_member_ad ) {
snprintf( c->cr_msg, sizeof( c->cr_msg ),
"\"dynlist-attrpair <member-ad> <URL-ad>\": "
"URL attributeDescription \"%s\" already mapped.\n",
......@@ -1323,7 +1485,9 @@ dl_cfgen( ConfigArgs *c )
(*dlip)->dli_oc = oc;
(*dlip)->dli_ad = ad;
(*dlip)->dli_member_ad = member_ad;
(*dlip)->dli_dlm = (dynlist_map_t *)ch_calloc( 1, sizeof( dynlist_map_t ) );
(*dlip)->dli_dlm->dlm_member_ad = member_ad;
(*dlip)->dli_dlm->dlm_mapped_ad = NULL;
rc = dynlist_build_def_filter( *dlip );
......@@ -1426,9 +1590,18 @@ dynlist_db_destroy(
*dli_next;
for ( dli_next = dli; dli_next; dli = dli_next ) {
dynlist_map_t *dlm;
dynlist_map_t *dlm_next;
dli_next = dli->dli_next;
ch_free( dli->dli_default_filter.bv_val );
dlm = dli->dli_dlm;
while ( dlm != NULL ) {
dlm_next = dlm->dlm_next;
ch_free( dlm );
dlm = dlm_next;
}
ch_free( dli );
}
}
......