void asyncmeta_map ( struct ldapmap *map, struct berval *s, struct berval *bv, int remap ) { struct ldapmapping *mapping; int drop_missing; /* map->map may be NULL when mapping is configured, * but map->remap can't */ if ( map->remap == NULL ) { *bv = *s; return; } BER_BVZERO( bv ); drop_missing = asyncmeta_mapping( map, s, &mapping, remap ); if ( mapping != NULL ) { if ( !BER_BVISNULL( &mapping->dst ) ) { *bv = mapping->dst; } return; } if ( !drop_missing ) { *bv = *s; } }
meta_search_candidate_t asyncmeta_back_add_start(Operation *op, SlapReply *rs, a_metaconn_t *mc, bm_context_t *bc, int candidate) { int isupdate; Attribute *a; int i; LDAPMod **attrs; struct berval mapped; a_dncookie dc; a_metainfo_t *mi = mc->mc_info; a_metatarget_t *mt = mi->mi_targets[ candidate ]; struct berval mdn; meta_search_candidate_t retcode = META_SEARCH_CANDIDATE; BerElement *ber = NULL; a_metasingleconn_t *msc = &mc->mc_conns[ candidate ]; SlapReply *candidates = bc->candidates; ber_int_t msgid; LDAPControl **ctrls = NULL; int rc, nretries = 1; dc.target = mt; dc.conn = op->o_conn; dc.rs = rs; dc.ctx = "addDN"; mdn.bv_len = 0; switch (asyncmeta_dn_massage( &dc, &bc->op->o_req_dn, &mdn ) ) { case LDAP_SUCCESS: break; case LDAP_UNWILLING_TO_PERFORM: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "Operation not allowed"; retcode = META_SEARCH_ERR; goto doreturn; default: rs->sr_err = LDAP_NO_SUCH_OBJECT; retcode = META_SEARCH_NOT_CANDIDATE; goto doreturn; } /* Count number of attributes in entry ( +1 ) */ for ( i = 1, a = op->ora_e->e_attrs; a; i++, a = a->a_next ); /* Create array of LDAPMods for ldap_add() */ attrs = ch_malloc( sizeof( LDAPMod * )*i ); dc.ctx = "addAttrDN"; isupdate = be_shadow_update( op ); for ( i = 0, a = op->ora_e->e_attrs; a; a = a->a_next ) { int j, is_oc = 0; if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod ) { continue; } if ( a->a_desc == slap_schema.si_ad_objectClass || a->a_desc == slap_schema.si_ad_structuralObjectClass ) { is_oc = 1; mapped = a->a_desc->ad_cname; } else { asyncmeta_map( &mt->mt_rwmap.rwm_at, &a->a_desc->ad_cname, &mapped, BACKLDAP_MAP ); if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) { continue; } } attrs[ i ] = ch_malloc( sizeof( LDAPMod ) ); if ( attrs[ i ] == NULL ) { continue; } attrs[ i ]->mod_op = LDAP_MOD_BVALUES; attrs[ i ]->mod_type = mapped.bv_val; if ( is_oc ) { for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ); attrs[ i ]->mod_bvalues = (struct berval **)ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); ) { struct ldapmapping *mapping; asyncmeta_mapping( &mt->mt_rwmap.rwm_oc, &a->a_vals[ j ], &mapping, BACKLDAP_MAP ); if ( mapping == NULL ) { if ( mt->mt_rwmap.rwm_oc.drop_missing ) { continue; } attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ]; } else { attrs[ i ]->mod_bvalues[ j ] = &mapping->dst; } j++; } attrs[ i ]->mod_bvalues[ j ] = NULL; } else { /* * FIXME: dn-valued attrs should be rewritten * to allow their use in ACLs at the back-ldap * level. */ if ( a->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) { (void)asyncmeta_dnattr_rewrite( &dc, a->a_vals ); if ( a->a_vals == NULL ) { continue; } } for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) ; attrs[ i ]->mod_bvalues = ch_malloc( ( j + 1 ) * sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) { attrs[ i ]->mod_bvalues[ j ] = &a->a_vals[ j ]; } attrs[ i ]->mod_bvalues[ j ] = NULL; } i++; } attrs[ i ] = NULL; retry:; ctrls = op->o_ctrls; if ( asyncmeta_controls_add( op, rs, mc, candidate, &ctrls ) != LDAP_SUCCESS ) { candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_ERR; goto done; } ber = ldap_build_add_req( msc->msc_ld, mdn.bv_val, attrs, ctrls, NULL, &msgid); if (ber) { candidates[ candidate ].sr_msgid = msgid; rc = ldap_send_initial_request( msc->msc_ld, LDAP_REQ_ADD, mdn.bv_val, ber, msgid ); if (rc == msgid) rc = LDAP_SUCCESS; else rc = LDAP_SERVER_DOWN; switch ( rc ) { case LDAP_SUCCESS: retcode = META_SEARCH_CANDIDATE; asyncmeta_set_msc_time(msc); break; case LDAP_SERVER_DOWN: ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex); asyncmeta_clear_one_msc(NULL, mc, candidate); ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex); if ( nretries && asyncmeta_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND ) ) { nretries = 0; /* if the identity changed, there might be need to re-authz */ (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); goto retry; } default: candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_ERR; } } done: (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); for ( --i; i >= 0; --i ) { free( attrs[ i ]->mod_bvalues ); free( attrs[ i ] ); } free( attrs ); if ( mdn.bv_val != op->ora_e->e_dn ) { free( mdn.bv_val ); BER_BVZERO( &mdn ); } doreturn:; Debug( LDAP_DEBUG_TRACE, "%s <<< asyncmeta_back_add_start[%p]=%d\n", op->o_log_prefix, msc, candidates[candidate].sr_msgid ); return retcode; }