Home | History | Annotate | Line # | Download | only in overlays
rwm.c revision 1.1.1.8
      1  1.1.1.6  christos /*	$NetBSD: rwm.c,v 1.1.1.8 2020/08/11 13:12:15 christos Exp $	*/
      2  1.1.1.2     lukem 
      3      1.1     lukem /* rwm.c - rewrite/remap operations */
      4  1.1.1.4      tron /* $OpenLDAP$ */
      5      1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6      1.1     lukem  *
      7  1.1.1.8  christos  * Copyright 2003-2020 The OpenLDAP Foundation.
      8      1.1     lukem  * Portions Copyright 2003 Pierangelo Masarati.
      9      1.1     lukem  * All rights reserved.
     10      1.1     lukem  *
     11      1.1     lukem  * Redistribution and use in source and binary forms, with or without
     12      1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     13      1.1     lukem  * Public License.
     14      1.1     lukem  *
     15      1.1     lukem  * A copy of this license is available in the file LICENSE in the
     16      1.1     lukem  * top-level directory of the distribution or, alternatively, at
     17      1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     18      1.1     lukem  */
     19      1.1     lukem 
     20  1.1.1.5  christos #include <sys/cdefs.h>
     21  1.1.1.6  christos __RCSID("$NetBSD: rwm.c,v 1.1.1.8 2020/08/11 13:12:15 christos Exp $");
     22  1.1.1.5  christos 
     23      1.1     lukem #include "portable.h"
     24      1.1     lukem 
     25      1.1     lukem #ifdef SLAPD_OVER_RWM
     26      1.1     lukem 
     27      1.1     lukem #include <stdio.h>
     28      1.1     lukem 
     29      1.1     lukem #include <ac/string.h>
     30      1.1     lukem 
     31      1.1     lukem #include "slap.h"
     32      1.1     lukem #include "config.h"
     33      1.1     lukem #include "lutil.h"
     34      1.1     lukem #include "rwm.h"
     35      1.1     lukem 
     36      1.1     lukem typedef struct rwm_op_state {
     37      1.1     lukem 	ber_tag_t r_tag;
     38      1.1     lukem 	struct berval ro_dn;
     39      1.1     lukem 	struct berval ro_ndn;
     40      1.1     lukem 	struct berval r_dn;
     41      1.1     lukem 	struct berval r_ndn;
     42  1.1.1.4      tron 	struct berval rx_dn;
     43  1.1.1.4      tron 	struct berval rx_ndn;
     44      1.1     lukem 	AttributeName *mapped_attrs;
     45      1.1     lukem 	OpRequest o_request;
     46      1.1     lukem } rwm_op_state;
     47      1.1     lukem 
     48      1.1     lukem typedef struct rwm_op_cb {
     49      1.1     lukem 	slap_callback cb;
     50      1.1     lukem 	rwm_op_state ros;
     51      1.1     lukem } rwm_op_cb;
     52      1.1     lukem 
     53      1.1     lukem static int
     54  1.1.1.2     lukem rwm_db_destroy( BackendDB *be, ConfigReply *cr );
     55      1.1     lukem 
     56  1.1.1.2     lukem static int
     57  1.1.1.2     lukem rwm_send_entry( Operation *op, SlapReply *rs );
     58      1.1     lukem 
     59  1.1.1.2     lukem static void
     60  1.1.1.2     lukem rwm_op_rollback( Operation *op, SlapReply *rs, rwm_op_state *ros )
     61  1.1.1.2     lukem {
     62  1.1.1.4      tron 	/* in case of successful extended operation cleanup
     63  1.1.1.4      tron 	 * gets called *after* (ITS#6632); this hack counts
     64  1.1.1.4      tron 	 * on others to cleanup our o_req_dn/o_req_ndn,
     65  1.1.1.4      tron 	 * while we cleanup theirs. */
     66  1.1.1.4      tron 	if ( ros->r_tag == LDAP_REQ_EXTENDED && rs->sr_err == LDAP_SUCCESS ) {
     67  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->rx_dn ) ) {
     68  1.1.1.4      tron 			ch_free( ros->rx_dn.bv_val );
     69  1.1.1.4      tron 		}
     70  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->rx_ndn ) ) {
     71  1.1.1.4      tron 			ch_free( ros->rx_ndn.bv_val );
     72  1.1.1.4      tron 		}
     73      1.1     lukem 
     74  1.1.1.4      tron 	} else {
     75  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->ro_dn ) ) {
     76  1.1.1.4      tron 			op->o_req_dn = ros->ro_dn;
     77  1.1.1.4      tron 		}
     78  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->ro_ndn ) ) {
     79  1.1.1.4      tron 			op->o_req_ndn = ros->ro_ndn;
     80  1.1.1.4      tron 		}
     81      1.1     lukem 
     82  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->r_dn )
     83  1.1.1.4      tron 			&& ros->r_dn.bv_val != ros->ro_dn.bv_val )
     84  1.1.1.4      tron 		{
     85  1.1.1.4      tron 			assert( ros->r_dn.bv_val != ros->r_ndn.bv_val );
     86  1.1.1.4      tron 			ch_free( ros->r_dn.bv_val );
     87  1.1.1.4      tron 		}
     88  1.1.1.4      tron 
     89  1.1.1.4      tron 		if ( !BER_BVISNULL( &ros->r_ndn )
     90  1.1.1.4      tron 			&& ros->r_ndn.bv_val != ros->ro_ndn.bv_val )
     91  1.1.1.4      tron 		{
     92  1.1.1.4      tron 			ch_free( ros->r_ndn.bv_val );
     93  1.1.1.4      tron 		}
     94  1.1.1.2     lukem 	}
     95      1.1     lukem 
     96  1.1.1.4      tron 	BER_BVZERO( &ros->r_dn );
     97  1.1.1.4      tron 	BER_BVZERO( &ros->r_ndn );
     98  1.1.1.2     lukem 	BER_BVZERO( &ros->ro_dn );
     99  1.1.1.2     lukem 	BER_BVZERO( &ros->ro_ndn );
    100  1.1.1.4      tron 	BER_BVZERO( &ros->rx_dn );
    101  1.1.1.4      tron 	BER_BVZERO( &ros->rx_ndn );
    102  1.1.1.2     lukem 
    103  1.1.1.2     lukem 	switch( ros->r_tag ) {
    104  1.1.1.2     lukem 	case LDAP_REQ_COMPARE:
    105  1.1.1.2     lukem 		if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
    106  1.1.1.2     lukem 			op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
    107  1.1.1.2     lukem 		op->orc_ava = ros->orc_ava;
    108  1.1.1.2     lukem 		break;
    109  1.1.1.2     lukem 	case LDAP_REQ_MODIFY:
    110  1.1.1.2     lukem 		slap_mods_free( op->orm_modlist, 1 );
    111  1.1.1.2     lukem 		op->orm_modlist = ros->orm_modlist;
    112  1.1.1.2     lukem 		break;
    113  1.1.1.2     lukem 	case LDAP_REQ_MODRDN:
    114  1.1.1.2     lukem 		if ( op->orr_newSup != ros->orr_newSup ) {
    115  1.1.1.4      tron 			if ( op->orr_newSup ) {
    116  1.1.1.4      tron 				ch_free( op->orr_newSup->bv_val );
    117  1.1.1.4      tron 				ch_free( op->orr_nnewSup->bv_val );
    118  1.1.1.4      tron 				op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
    119  1.1.1.4      tron 				op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
    120  1.1.1.4      tron 			}
    121  1.1.1.2     lukem 			op->orr_newSup = ros->orr_newSup;
    122  1.1.1.2     lukem 			op->orr_nnewSup = ros->orr_nnewSup;
    123  1.1.1.2     lukem 		}
    124  1.1.1.2     lukem 		if ( op->orr_newrdn.bv_val != ros->orr_newrdn.bv_val ) {
    125  1.1.1.2     lukem 			ch_free( op->orr_newrdn.bv_val );
    126  1.1.1.2     lukem 			ch_free( op->orr_nnewrdn.bv_val );
    127  1.1.1.2     lukem 			op->orr_newrdn = ros->orr_newrdn;
    128  1.1.1.2     lukem 			op->orr_nnewrdn = ros->orr_nnewrdn;
    129  1.1.1.2     lukem 		}
    130  1.1.1.2     lukem 		break;
    131  1.1.1.2     lukem 	case LDAP_REQ_SEARCH:
    132  1.1.1.3      adam 		op->o_tmpfree( ros->mapped_attrs, op->o_tmpmemctx );
    133  1.1.1.2     lukem 		op->ors_attrs = ros->ors_attrs;
    134  1.1.1.7  christos 		if ( op->ors_filter != ros->ors_filter ) {
    135  1.1.1.7  christos 			filter_free_x( op, op->ors_filter, 1 );
    136  1.1.1.7  christos 			op->ors_filter = ros->ors_filter;
    137  1.1.1.7  christos 		}
    138  1.1.1.7  christos 		if ( op->ors_filterstr.bv_val != ros->ors_filterstr.bv_val ) {
    139  1.1.1.7  christos 			op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
    140  1.1.1.7  christos 			op->ors_filterstr = ros->ors_filterstr;
    141  1.1.1.7  christos 		}
    142  1.1.1.2     lukem 		break;
    143  1.1.1.2     lukem 	case LDAP_REQ_EXTENDED:
    144  1.1.1.2     lukem 		if ( op->ore_reqdata != ros->ore_reqdata ) {
    145  1.1.1.2     lukem 			ber_bvfree( op->ore_reqdata );
    146  1.1.1.2     lukem 			op->ore_reqdata = ros->ore_reqdata;
    147      1.1     lukem 		}
    148  1.1.1.2     lukem 		break;
    149  1.1.1.2     lukem 	case LDAP_REQ_BIND:
    150  1.1.1.2     lukem 		if ( rs->sr_err == LDAP_SUCCESS ) {
    151  1.1.1.2     lukem #if 0
    152  1.1.1.2     lukem 			ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
    153  1.1.1.2     lukem 			/* too late, c_mutex released */
    154  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY, "*** DN: \"%s\" => \"%s\"\n",
    155  1.1.1.2     lukem 				op->o_conn->c_ndn.bv_val,
    156  1.1.1.2     lukem 				op->o_req_ndn.bv_val );
    157  1.1.1.2     lukem 			ber_bvreplace( &op->o_conn->c_ndn,
    158  1.1.1.2     lukem 				&op->o_req_ndn );
    159  1.1.1.2     lukem 			ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
    160  1.1.1.2     lukem #endif
    161  1.1.1.2     lukem 		}
    162  1.1.1.2     lukem 		break;
    163  1.1.1.2     lukem 	default:	break;
    164  1.1.1.2     lukem 	}
    165  1.1.1.2     lukem }
    166  1.1.1.2     lukem 
    167  1.1.1.2     lukem static int
    168  1.1.1.2     lukem rwm_op_cleanup( Operation *op, SlapReply *rs )
    169  1.1.1.2     lukem {
    170  1.1.1.2     lukem 	slap_callback	*cb = op->o_callback;
    171  1.1.1.2     lukem 	rwm_op_state *ros = cb->sc_private;
    172  1.1.1.2     lukem 
    173  1.1.1.2     lukem 	if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
    174  1.1.1.2     lukem 		op->o_abandon || rs->sr_err == SLAPD_ABANDON )
    175  1.1.1.2     lukem 	{
    176  1.1.1.2     lukem 		rwm_op_rollback( op, rs, ros );
    177  1.1.1.2     lukem 
    178      1.1     lukem 		op->o_callback = op->o_callback->sc_next;
    179      1.1     lukem 		op->o_tmpfree( cb, op->o_tmpmemctx );
    180      1.1     lukem 	}
    181      1.1     lukem 
    182      1.1     lukem 	return SLAP_CB_CONTINUE;
    183      1.1     lukem }
    184      1.1     lukem 
    185      1.1     lukem static rwm_op_cb *
    186  1.1.1.4      tron rwm_callback_get( Operation *op )
    187      1.1     lukem {
    188  1.1.1.4      tron 	rwm_op_cb	*roc;
    189      1.1     lukem 
    190  1.1.1.5  christos 	roc = op->o_tmpcalloc( 1, sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
    191      1.1     lukem 	roc->cb.sc_cleanup = rwm_op_cleanup;
    192      1.1     lukem 	roc->cb.sc_response = NULL;
    193      1.1     lukem 	roc->cb.sc_next = op->o_callback;
    194      1.1     lukem 	roc->cb.sc_private = &roc->ros;
    195      1.1     lukem 	roc->ros.r_tag = op->o_tag;
    196      1.1     lukem 	roc->ros.ro_dn = op->o_req_dn;
    197      1.1     lukem 	roc->ros.ro_ndn = op->o_req_ndn;
    198      1.1     lukem 	BER_BVZERO( &roc->ros.r_dn );
    199      1.1     lukem 	BER_BVZERO( &roc->ros.r_ndn );
    200  1.1.1.4      tron 	BER_BVZERO( &roc->ros.rx_dn );
    201  1.1.1.4      tron 	BER_BVZERO( &roc->ros.rx_ndn );
    202  1.1.1.4      tron 	roc->ros.mapped_attrs = NULL;
    203  1.1.1.4      tron 	roc->ros.o_request = op->o_request;
    204      1.1     lukem 
    205      1.1     lukem 	return roc;
    206      1.1     lukem }
    207      1.1     lukem 
    208      1.1     lukem 
    209      1.1     lukem static int
    210      1.1     lukem rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
    211      1.1     lukem 	rwm_op_state *ros )
    212      1.1     lukem {
    213      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    214      1.1     lukem 	struct ldaprwmap	*rwmap =
    215      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    216      1.1     lukem 
    217      1.1     lukem 	struct berval		dn = BER_BVNULL,
    218      1.1     lukem 				ndn = BER_BVNULL;
    219      1.1     lukem 	int			rc = 0;
    220      1.1     lukem 	dncookie		dc;
    221      1.1     lukem 
    222      1.1     lukem 	/*
    223      1.1     lukem 	 * Rewrite the dn if needed
    224      1.1     lukem 	 */
    225      1.1     lukem 	dc.rwmap = rwmap;
    226      1.1     lukem 	dc.conn = op->o_conn;
    227      1.1     lukem 	dc.rs = rs;
    228      1.1     lukem 	dc.ctx = (char *)cookie;
    229      1.1     lukem 
    230      1.1     lukem 	/* NOTE: in those cases where only the ndn is available,
    231      1.1     lukem 	 * and the caller sets op->o_req_dn = op->o_req_ndn,
    232      1.1     lukem 	 * only rewrite the op->o_req_ndn and use it as
    233      1.1     lukem 	 * op->o_req_dn as well */
    234      1.1     lukem 	ndn = op->o_req_ndn;
    235      1.1     lukem 	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
    236      1.1     lukem 		dn = op->o_req_dn;
    237      1.1     lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
    238      1.1     lukem 	} else {
    239      1.1     lukem 		rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
    240      1.1     lukem 	}
    241      1.1     lukem 
    242      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    243      1.1     lukem 		return rc;
    244      1.1     lukem 	}
    245      1.1     lukem 
    246      1.1     lukem 	if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
    247      1.1     lukem 			|| ndn.bv_val == op->o_req_ndn.bv_val )
    248      1.1     lukem 	{
    249      1.1     lukem 		return LDAP_SUCCESS;
    250      1.1     lukem 	}
    251      1.1     lukem 
    252      1.1     lukem 	if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
    253      1.1     lukem 		op->o_req_dn = dn;
    254  1.1.1.2     lukem 		assert( BER_BVISNULL( &ros->r_dn ) );
    255      1.1     lukem 		ros->r_dn = dn;
    256      1.1     lukem 	} else {
    257      1.1     lukem 		op->o_req_dn = ndn;
    258      1.1     lukem 	}
    259      1.1     lukem 	op->o_req_ndn = ndn;
    260  1.1.1.2     lukem 	assert( BER_BVISNULL( &ros->r_ndn ) );
    261      1.1     lukem 	ros->r_ndn = ndn;
    262      1.1     lukem 
    263  1.1.1.4      tron 	if ( ros->r_tag == LDAP_REQ_EXTENDED ) {
    264  1.1.1.4      tron 		ros->rx_dn = ros->r_dn;
    265  1.1.1.4      tron 		ros->rx_ndn = ros->r_ndn;
    266  1.1.1.4      tron 	}
    267  1.1.1.4      tron 
    268      1.1     lukem 	return LDAP_SUCCESS;
    269      1.1     lukem }
    270      1.1     lukem 
    271      1.1     lukem static int
    272      1.1     lukem rwm_op_add( Operation *op, SlapReply *rs )
    273      1.1     lukem {
    274      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    275      1.1     lukem 	struct ldaprwmap	*rwmap =
    276      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    277      1.1     lukem 
    278      1.1     lukem 	int			rc,
    279      1.1     lukem 				i;
    280      1.1     lukem 	Attribute		**ap = NULL;
    281      1.1     lukem 	char			*olddn = op->o_req_dn.bv_val;
    282      1.1     lukem 	int			isupdate;
    283      1.1     lukem 
    284  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    285      1.1     lukem 
    286      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
    287      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    288      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    289      1.1     lukem 		send_ldap_error( op, rs, rc, "addDN massage error" );
    290      1.1     lukem 		return -1;
    291      1.1     lukem 	}
    292      1.1     lukem 
    293      1.1     lukem 	if ( olddn != op->o_req_dn.bv_val ) {
    294      1.1     lukem 		ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
    295      1.1     lukem 		ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
    296      1.1     lukem 	}
    297      1.1     lukem 
    298      1.1     lukem 	/* Count number of attributes in entry */
    299      1.1     lukem 	isupdate = be_shadow_update( op );
    300      1.1     lukem 	for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
    301      1.1     lukem 		Attribute	*a;
    302      1.1     lukem 
    303      1.1     lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
    304      1.1     lukem 				(*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
    305      1.1     lukem 		{
    306      1.1     lukem 			int		j, last;
    307      1.1     lukem 
    308      1.1     lukem 			last = (*ap)->a_numvals - 1;
    309      1.1     lukem 			for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
    310      1.1     lukem 				struct ldapmapping	*mapping = NULL;
    311      1.1     lukem 
    312      1.1     lukem 				( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
    313      1.1     lukem 						&mapping, RWM_MAP );
    314      1.1     lukem 				if ( mapping == NULL ) {
    315      1.1     lukem 					if ( rwmap->rwm_at.drop_missing ) {
    316      1.1     lukem 						/* FIXME: we allow to remove objectClasses as well;
    317      1.1     lukem 						 * if the resulting entry is inconsistent, that's
    318      1.1     lukem 						 * the relayed database's business...
    319      1.1     lukem 						 */
    320      1.1     lukem 						ch_free( (*ap)->a_vals[ j ].bv_val );
    321      1.1     lukem 						if ( last > j ) {
    322      1.1     lukem 							(*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
    323      1.1     lukem 						}
    324      1.1     lukem 						BER_BVZERO( &(*ap)->a_vals[ last ] );
    325      1.1     lukem 						(*ap)->a_numvals--;
    326      1.1     lukem 						last--;
    327      1.1     lukem 						j--;
    328      1.1     lukem 					}
    329      1.1     lukem 
    330      1.1     lukem 				} else {
    331      1.1     lukem 					ch_free( (*ap)->a_vals[ j ].bv_val );
    332      1.1     lukem 					ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
    333      1.1     lukem 				}
    334      1.1     lukem 			}
    335      1.1     lukem 
    336      1.1     lukem 		} else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
    337      1.1     lukem 		{
    338      1.1     lukem 			goto next_attr;
    339      1.1     lukem 
    340      1.1     lukem 		} else {
    341      1.1     lukem 			struct ldapmapping	*mapping = NULL;
    342      1.1     lukem 
    343      1.1     lukem 			( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
    344      1.1     lukem 					&mapping, RWM_MAP );
    345      1.1     lukem 			if ( mapping == NULL ) {
    346      1.1     lukem 				if ( rwmap->rwm_at.drop_missing ) {
    347      1.1     lukem 					goto cleanup_attr;
    348      1.1     lukem 				}
    349      1.1     lukem 			}
    350      1.1     lukem 
    351      1.1     lukem 			if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    352      1.1     lukem 					|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    353      1.1     lukem 			{
    354      1.1     lukem 				/*
    355      1.1     lukem 				 * FIXME: rewrite could fail; in this case
    356      1.1     lukem 				 * the operation should give up, right?
    357      1.1     lukem 				 */
    358      1.1     lukem 				rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
    359      1.1     lukem 						(*ap)->a_vals,
    360      1.1     lukem 						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
    361      1.1     lukem 				if ( rc ) {
    362      1.1     lukem 					goto cleanup_attr;
    363      1.1     lukem 				}
    364      1.1     lukem 
    365      1.1     lukem 			} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
    366      1.1     lukem 				rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
    367      1.1     lukem 						(*ap)->a_vals,
    368      1.1     lukem 						(*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
    369      1.1     lukem 				if ( rc != LDAP_SUCCESS ) {
    370      1.1     lukem 					goto cleanup_attr;
    371      1.1     lukem 				}
    372      1.1     lukem 			}
    373      1.1     lukem 
    374      1.1     lukem 			if ( mapping != NULL ) {
    375      1.1     lukem 				assert( mapping->m_dst_ad != NULL );
    376      1.1     lukem 				(*ap)->a_desc = mapping->m_dst_ad;
    377      1.1     lukem 			}
    378      1.1     lukem 		}
    379      1.1     lukem 
    380      1.1     lukem next_attr:;
    381      1.1     lukem 		ap = &(*ap)->a_next;
    382      1.1     lukem 		continue;
    383      1.1     lukem 
    384      1.1     lukem cleanup_attr:;
    385      1.1     lukem 		/* FIXME: leaking attribute/values? */
    386      1.1     lukem 		a = *ap;
    387      1.1     lukem 
    388      1.1     lukem 		*ap = (*ap)->a_next;
    389      1.1     lukem 		attr_free( a );
    390      1.1     lukem 	}
    391      1.1     lukem 
    392      1.1     lukem 	op->o_callback = &roc->cb;
    393      1.1     lukem 
    394      1.1     lukem 	return SLAP_CB_CONTINUE;
    395      1.1     lukem }
    396      1.1     lukem 
    397      1.1     lukem static int
    398      1.1     lukem rwm_conn_init( BackendDB *be, Connection *conn )
    399      1.1     lukem {
    400      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
    401      1.1     lukem 	struct ldaprwmap	*rwmap =
    402      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    403      1.1     lukem 
    404      1.1     lukem 	( void )rewrite_session_init( rwmap->rwm_rw, conn );
    405      1.1     lukem 
    406      1.1     lukem 	return SLAP_CB_CONTINUE;
    407      1.1     lukem }
    408      1.1     lukem 
    409      1.1     lukem static int
    410      1.1     lukem rwm_conn_destroy( BackendDB *be, Connection *conn )
    411      1.1     lukem {
    412      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
    413      1.1     lukem 	struct ldaprwmap	*rwmap =
    414      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    415      1.1     lukem 
    416      1.1     lukem 	( void )rewrite_session_delete( rwmap->rwm_rw, conn );
    417      1.1     lukem 
    418      1.1     lukem 	return SLAP_CB_CONTINUE;
    419      1.1     lukem }
    420      1.1     lukem 
    421      1.1     lukem static int
    422      1.1     lukem rwm_op_bind( Operation *op, SlapReply *rs )
    423      1.1     lukem {
    424      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    425      1.1     lukem 	int			rc;
    426      1.1     lukem 
    427  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    428      1.1     lukem 
    429      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
    430      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    431      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    432      1.1     lukem 		send_ldap_error( op, rs, rc, "bindDN massage error" );
    433      1.1     lukem 		return -1;
    434      1.1     lukem 	}
    435      1.1     lukem 
    436  1.1.1.2     lukem 	overlay_callback_after_backover( op, &roc->cb, 1 );
    437      1.1     lukem 
    438      1.1     lukem 	return SLAP_CB_CONTINUE;
    439      1.1     lukem }
    440      1.1     lukem 
    441      1.1     lukem static int
    442      1.1     lukem rwm_op_unbind( Operation *op, SlapReply *rs )
    443      1.1     lukem {
    444      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    445      1.1     lukem 	struct ldaprwmap	*rwmap =
    446      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    447      1.1     lukem 
    448      1.1     lukem 	rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
    449      1.1     lukem 
    450      1.1     lukem 	return SLAP_CB_CONTINUE;
    451      1.1     lukem }
    452      1.1     lukem 
    453      1.1     lukem static int
    454      1.1     lukem rwm_op_compare( Operation *op, SlapReply *rs )
    455      1.1     lukem {
    456      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    457      1.1     lukem 	struct ldaprwmap	*rwmap =
    458      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    459      1.1     lukem 
    460      1.1     lukem 	int			rc;
    461      1.1     lukem 	struct berval		mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
    462      1.1     lukem 
    463  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    464      1.1     lukem 
    465      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
    466      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    467      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    468      1.1     lukem 		send_ldap_error( op, rs, rc, "compareDN massage error" );
    469      1.1     lukem 		return -1;
    470      1.1     lukem 	}
    471      1.1     lukem 
    472      1.1     lukem 	/* if the attribute is an objectClass, try to remap its value */
    473      1.1     lukem 	if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
    474      1.1     lukem 			|| op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
    475      1.1     lukem 	{
    476      1.1     lukem 		rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
    477      1.1     lukem 				&mapped_vals[0], RWM_MAP );
    478      1.1     lukem 		if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
    479      1.1     lukem 		{
    480      1.1     lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    481      1.1     lukem 			send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
    482      1.1     lukem 			return -1;
    483      1.1     lukem 
    484      1.1     lukem 		} else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
    485      1.1     lukem 			ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
    486      1.1     lukem 				op->o_tmpmemctx );
    487      1.1     lukem 		}
    488      1.1     lukem 
    489      1.1     lukem 	} else {
    490      1.1     lukem 		struct ldapmapping	*mapping = NULL;
    491      1.1     lukem 		AttributeDescription	*ad = op->orc_ava->aa_desc;
    492      1.1     lukem 
    493      1.1     lukem 		( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
    494      1.1     lukem 				&mapping, RWM_MAP );
    495      1.1     lukem 		if ( mapping == NULL ) {
    496      1.1     lukem 			if ( rwmap->rwm_at.drop_missing ) {
    497      1.1     lukem 				op->o_bd->bd_info = (BackendInfo *)on->on_info;
    498      1.1     lukem 				send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
    499      1.1     lukem 				return -1;
    500      1.1     lukem 			}
    501      1.1     lukem 
    502      1.1     lukem 		} else {
    503      1.1     lukem 			assert( mapping->m_dst_ad != NULL );
    504      1.1     lukem 			ad = mapping->m_dst_ad;
    505      1.1     lukem 		}
    506      1.1     lukem 
    507      1.1     lukem 		if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    508      1.1     lukem 				|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    509      1.1     lukem 		{
    510      1.1     lukem 			struct berval	*mapped_valsp[2];
    511      1.1     lukem 
    512      1.1     lukem 			mapped_valsp[0] = &mapped_vals[0];
    513      1.1     lukem 			mapped_valsp[1] = &mapped_vals[1];
    514      1.1     lukem 
    515      1.1     lukem 			mapped_vals[0] = op->orc_ava->aa_value;
    516      1.1     lukem 
    517      1.1     lukem 			rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
    518      1.1     lukem 
    519      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
    520      1.1     lukem 				op->o_bd->bd_info = (BackendInfo *)on->on_info;
    521      1.1     lukem 				send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
    522      1.1     lukem 				return -1;
    523      1.1     lukem 			}
    524      1.1     lukem 
    525      1.1     lukem 			if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
    526      1.1     lukem 				/* NOTE: if we get here, rwm_dnattr_rewrite()
    527      1.1     lukem 				 * already freed the old value, so now
    528      1.1     lukem 				 * it's invalid */
    529      1.1     lukem 				ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
    530      1.1     lukem 					op->o_tmpmemctx );
    531      1.1     lukem 				ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
    532      1.1     lukem 			}
    533      1.1     lukem 		}
    534      1.1     lukem 		op->orc_ava->aa_desc = ad;
    535      1.1     lukem 	}
    536      1.1     lukem 
    537      1.1     lukem 	op->o_callback = &roc->cb;
    538      1.1     lukem 
    539      1.1     lukem 	return SLAP_CB_CONTINUE;
    540      1.1     lukem }
    541      1.1     lukem 
    542      1.1     lukem static int
    543      1.1     lukem rwm_op_delete( Operation *op, SlapReply *rs )
    544      1.1     lukem {
    545      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    546      1.1     lukem 	int			rc;
    547      1.1     lukem 
    548  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    549      1.1     lukem 
    550      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
    551      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    552      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    553      1.1     lukem 		send_ldap_error( op, rs, rc, "deleteDN massage error" );
    554      1.1     lukem 		return -1;
    555      1.1     lukem 	}
    556      1.1     lukem 
    557      1.1     lukem 	op->o_callback = &roc->cb;
    558      1.1     lukem 
    559      1.1     lukem 	return SLAP_CB_CONTINUE;
    560      1.1     lukem }
    561      1.1     lukem 
    562      1.1     lukem static int
    563      1.1     lukem rwm_op_modify( Operation *op, SlapReply *rs )
    564      1.1     lukem {
    565      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    566      1.1     lukem 	struct ldaprwmap	*rwmap =
    567      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    568      1.1     lukem 
    569      1.1     lukem 	int			isupdate;
    570      1.1     lukem 	Modifications		**mlp;
    571      1.1     lukem 	int			rc;
    572      1.1     lukem 
    573  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    574      1.1     lukem 
    575      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
    576      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    577      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    578      1.1     lukem 		send_ldap_error( op, rs, rc, "modifyDN massage error" );
    579      1.1     lukem 		return -1;
    580      1.1     lukem 	}
    581      1.1     lukem 
    582      1.1     lukem 	isupdate = be_shadow_update( op );
    583      1.1     lukem 	for ( mlp = &op->orm_modlist; *mlp; ) {
    584      1.1     lukem 		int			is_oc = 0;
    585      1.1     lukem 		Modifications		*ml = *mlp;
    586      1.1     lukem 		struct ldapmapping	*mapping = NULL;
    587      1.1     lukem 
    588      1.1     lukem 		/* ml points to a temporary mod until needs duplication */
    589      1.1     lukem 		if ( ml->sml_desc == slap_schema.si_ad_objectClass
    590      1.1     lukem 				|| ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
    591      1.1     lukem 		{
    592      1.1     lukem 			is_oc = 1;
    593      1.1     lukem 
    594      1.1     lukem 		} else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod  )
    595      1.1     lukem 		{
    596      1.1     lukem 			ml = ch_malloc( sizeof( Modifications ) );
    597      1.1     lukem 			*ml = **mlp;
    598      1.1     lukem 			if ( (*mlp)->sml_values ) {
    599      1.1     lukem 				ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
    600      1.1     lukem 				if ( (*mlp)->sml_nvalues ) {
    601      1.1     lukem 					ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
    602      1.1     lukem 				}
    603      1.1     lukem 			}
    604      1.1     lukem 			*mlp = ml;
    605      1.1     lukem 			goto next_mod;
    606      1.1     lukem 
    607      1.1     lukem 		} else {
    608      1.1     lukem 			int			drop_missing;
    609      1.1     lukem 
    610      1.1     lukem 			drop_missing = rwm_mapping( &rwmap->rwm_at,
    611      1.1     lukem 					&ml->sml_desc->ad_cname,
    612      1.1     lukem 					&mapping, RWM_MAP );
    613      1.1     lukem 			if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
    614      1.1     lukem 			{
    615  1.1.1.4      tron 				goto skip_mod;
    616      1.1     lukem 			}
    617      1.1     lukem 		}
    618      1.1     lukem 
    619      1.1     lukem 		/* duplicate the modlist */
    620      1.1     lukem 		ml = ch_malloc( sizeof( Modifications ));
    621      1.1     lukem 		*ml = **mlp;
    622      1.1     lukem 		*mlp = ml;
    623      1.1     lukem 
    624      1.1     lukem 		if ( ml->sml_values != NULL ) {
    625      1.1     lukem 			int i, num;
    626      1.1     lukem 			struct berval *bva;
    627      1.1     lukem 
    628      1.1     lukem 			for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
    629      1.1     lukem 				/* count values */ ;
    630      1.1     lukem 
    631      1.1     lukem 			bva = ch_malloc( (num+1) * sizeof( struct berval ));
    632      1.1     lukem 			for (i=0; i<num; i++)
    633      1.1     lukem 				ber_dupbv( &bva[i], &ml->sml_values[i] );
    634      1.1     lukem 			BER_BVZERO( &bva[i] );
    635      1.1     lukem 			ml->sml_values = bva;
    636      1.1     lukem 
    637      1.1     lukem 			if ( ml->sml_nvalues ) {
    638      1.1     lukem 				bva = ch_malloc( (num+1) * sizeof( struct berval ));
    639      1.1     lukem 				for (i=0; i<num; i++)
    640      1.1     lukem 					ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
    641      1.1     lukem 				BER_BVZERO( &bva[i] );
    642      1.1     lukem 				ml->sml_nvalues = bva;
    643      1.1     lukem 			}
    644      1.1     lukem 
    645      1.1     lukem 			if ( is_oc ) {
    646      1.1     lukem 				int	last, j;
    647      1.1     lukem 
    648      1.1     lukem 				last = num-1;
    649      1.1     lukem 
    650      1.1     lukem 				for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
    651      1.1     lukem 					struct ldapmapping	*oc_mapping = NULL;
    652      1.1     lukem 
    653      1.1     lukem 					( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
    654      1.1     lukem 							&oc_mapping, RWM_MAP );
    655      1.1     lukem 					if ( oc_mapping == NULL ) {
    656      1.1     lukem 						if ( rwmap->rwm_at.drop_missing ) {
    657      1.1     lukem 							/* FIXME: we allow to remove objectClasses as well;
    658      1.1     lukem 							 * if the resulting entry is inconsistent, that's
    659      1.1     lukem 							 * the relayed database's business...
    660      1.1     lukem 							 */
    661      1.1     lukem 							if ( last > j ) {
    662      1.1     lukem 								ch_free( ml->sml_values[ j ].bv_val );
    663      1.1     lukem 								ml->sml_values[ j ] = ml->sml_values[ last ];
    664      1.1     lukem 							}
    665      1.1     lukem 							BER_BVZERO( &ml->sml_values[ last ] );
    666      1.1     lukem 							last--;
    667      1.1     lukem 							j--;
    668      1.1     lukem 						}
    669      1.1     lukem 
    670      1.1     lukem 					} else {
    671      1.1     lukem 						ch_free( ml->sml_values[ j ].bv_val );
    672      1.1     lukem 						ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
    673      1.1     lukem 					}
    674      1.1     lukem 				}
    675      1.1     lukem 
    676      1.1     lukem 			} else {
    677      1.1     lukem 				if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
    678      1.1     lukem 						|| ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
    679      1.1     lukem 				{
    680      1.1     lukem 					rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
    681      1.1     lukem 							ml->sml_values,
    682      1.1     lukem 							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
    683      1.1     lukem 
    684      1.1     lukem 				} else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
    685      1.1     lukem 					rc = rwm_referral_rewrite( op, rs,
    686      1.1     lukem 							"referralAttrDN",
    687      1.1     lukem 							ml->sml_values,
    688      1.1     lukem 							ml->sml_nvalues ? &ml->sml_nvalues : NULL );
    689      1.1     lukem 					if ( rc != LDAP_SUCCESS ) {
    690      1.1     lukem 						goto cleanup_mod;
    691      1.1     lukem 					}
    692      1.1     lukem 				}
    693      1.1     lukem 
    694      1.1     lukem 				if ( rc != LDAP_SUCCESS ) {
    695      1.1     lukem 					goto cleanup_mod;
    696      1.1     lukem 				}
    697      1.1     lukem 			}
    698      1.1     lukem 		}
    699      1.1     lukem 
    700      1.1     lukem next_mod:;
    701      1.1     lukem 		if ( mapping != NULL ) {
    702      1.1     lukem 			/* use new attribute description */
    703      1.1     lukem 			assert( mapping->m_dst_ad != NULL );
    704      1.1     lukem 			ml->sml_desc = mapping->m_dst_ad;
    705      1.1     lukem 		}
    706      1.1     lukem 
    707      1.1     lukem 		mlp = &ml->sml_next;
    708      1.1     lukem 		continue;
    709      1.1     lukem 
    710  1.1.1.4      tron skip_mod:;
    711  1.1.1.4      tron 		*mlp = (*mlp)->sml_next;
    712  1.1.1.4      tron 		continue;
    713  1.1.1.4      tron 
    714      1.1     lukem cleanup_mod:;
    715      1.1     lukem 		ml = *mlp;
    716      1.1     lukem 		*mlp = (*mlp)->sml_next;
    717      1.1     lukem 		slap_mod_free( &ml->sml_mod, 0 );
    718      1.1     lukem 		free( ml );
    719      1.1     lukem 	}
    720      1.1     lukem 
    721      1.1     lukem 	op->o_callback = &roc->cb;
    722      1.1     lukem 
    723      1.1     lukem 	return SLAP_CB_CONTINUE;
    724      1.1     lukem }
    725      1.1     lukem 
    726      1.1     lukem static int
    727      1.1     lukem rwm_op_modrdn( Operation *op, SlapReply *rs )
    728      1.1     lukem {
    729      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    730      1.1     lukem 	struct ldaprwmap	*rwmap =
    731      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    732      1.1     lukem 
    733      1.1     lukem 	int			rc;
    734  1.1.1.2     lukem 	dncookie		dc;
    735      1.1     lukem 
    736  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    737      1.1     lukem 
    738      1.1     lukem 	if ( op->orr_newSup ) {
    739      1.1     lukem 		struct berval	nnewSup = BER_BVNULL;
    740      1.1     lukem 		struct berval	newSup = BER_BVNULL;
    741      1.1     lukem 
    742      1.1     lukem 		/*
    743      1.1     lukem 		 * Rewrite the new superior, if defined and required
    744      1.1     lukem 	 	 */
    745      1.1     lukem 		dc.rwmap = rwmap;
    746      1.1     lukem 		dc.conn = op->o_conn;
    747      1.1     lukem 		dc.rs = rs;
    748      1.1     lukem 		dc.ctx = "newSuperiorDN";
    749      1.1     lukem 		newSup = *op->orr_newSup;
    750      1.1     lukem 		nnewSup = *op->orr_nnewSup;
    751      1.1     lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
    752      1.1     lukem 		if ( rc != LDAP_SUCCESS ) {
    753      1.1     lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    754      1.1     lukem 			send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
    755      1.1     lukem 			return -1;
    756      1.1     lukem 		}
    757      1.1     lukem 
    758      1.1     lukem 		if ( op->orr_newSup->bv_val != newSup.bv_val ) {
    759      1.1     lukem 			op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
    760      1.1     lukem 				op->o_tmpmemctx );
    761      1.1     lukem 			op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
    762      1.1     lukem 				op->o_tmpmemctx );
    763      1.1     lukem 			*op->orr_newSup = newSup;
    764      1.1     lukem 			*op->orr_nnewSup = nnewSup;
    765      1.1     lukem 		}
    766      1.1     lukem 	}
    767      1.1     lukem 
    768      1.1     lukem 	/*
    769  1.1.1.2     lukem 	 * Rewrite the newRDN, if needed
    770  1.1.1.2     lukem  	 */
    771  1.1.1.2     lukem 	{
    772  1.1.1.2     lukem 		struct berval	newrdn = BER_BVNULL;
    773  1.1.1.2     lukem 		struct berval	nnewrdn = BER_BVNULL;
    774  1.1.1.2     lukem 
    775  1.1.1.2     lukem 		dc.rwmap = rwmap;
    776  1.1.1.2     lukem 		dc.conn = op->o_conn;
    777  1.1.1.2     lukem 		dc.rs = rs;
    778  1.1.1.2     lukem 		dc.ctx = "newRDN";
    779  1.1.1.2     lukem 		newrdn = op->orr_newrdn;
    780  1.1.1.2     lukem 		nnewrdn = op->orr_nnewrdn;
    781  1.1.1.2     lukem 		rc = rwm_dn_massage_pretty_normalize( &dc, &op->orr_newrdn, &newrdn, &nnewrdn );
    782  1.1.1.2     lukem 		if ( rc != LDAP_SUCCESS ) {
    783  1.1.1.2     lukem 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
    784  1.1.1.2     lukem 			send_ldap_error( op, rs, rc, "newRDN massage error" );
    785  1.1.1.2     lukem 			goto err;
    786  1.1.1.2     lukem 		}
    787  1.1.1.2     lukem 
    788  1.1.1.2     lukem 		if ( op->orr_newrdn.bv_val != newrdn.bv_val ) {
    789  1.1.1.2     lukem 			op->orr_newrdn = newrdn;
    790  1.1.1.2     lukem 			op->orr_nnewrdn = nnewrdn;
    791  1.1.1.2     lukem 		}
    792  1.1.1.2     lukem 	}
    793  1.1.1.2     lukem 
    794  1.1.1.2     lukem 	/*
    795      1.1     lukem 	 * Rewrite the dn, if needed
    796      1.1     lukem  	 */
    797      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
    798      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    799      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
    800      1.1     lukem 		send_ldap_error( op, rs, rc, "renameDN massage error" );
    801  1.1.1.2     lukem 		goto err;
    802  1.1.1.2     lukem 	}
    803  1.1.1.2     lukem 
    804  1.1.1.2     lukem 	op->o_callback = &roc->cb;
    805  1.1.1.2     lukem 
    806  1.1.1.2     lukem 	rc = SLAP_CB_CONTINUE;
    807  1.1.1.2     lukem 
    808  1.1.1.2     lukem 	if ( 0 ) {
    809  1.1.1.2     lukem err:;
    810      1.1     lukem 		if ( op->orr_newSup != roc->ros.orr_newSup ) {
    811      1.1     lukem 			ch_free( op->orr_newSup->bv_val );
    812      1.1     lukem 			ch_free( op->orr_nnewSup->bv_val );
    813      1.1     lukem 			op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
    814      1.1     lukem 			op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
    815      1.1     lukem 			op->orr_newSup = roc->ros.orr_newSup;
    816      1.1     lukem 			op->orr_nnewSup = roc->ros.orr_nnewSup;
    817      1.1     lukem 		}
    818      1.1     lukem 
    819  1.1.1.2     lukem 		if ( op->orr_newrdn.bv_val != roc->ros.orr_newrdn.bv_val ) {
    820  1.1.1.2     lukem 			ch_free( op->orr_newrdn.bv_val );
    821  1.1.1.2     lukem 			ch_free( op->orr_nnewrdn.bv_val );
    822  1.1.1.2     lukem 			op->orr_newrdn = roc->ros.orr_newrdn;
    823  1.1.1.2     lukem 			op->orr_nnewrdn = roc->ros.orr_nnewrdn;
    824  1.1.1.2     lukem 		}
    825  1.1.1.2     lukem 	}
    826      1.1     lukem 
    827  1.1.1.2     lukem 	return rc;
    828      1.1     lukem }
    829      1.1     lukem 
    830      1.1     lukem 
    831      1.1     lukem static int
    832      1.1     lukem rwm_swap_attrs( Operation *op, SlapReply *rs )
    833      1.1     lukem {
    834      1.1     lukem 	slap_callback	*cb = op->o_callback;
    835      1.1     lukem 	rwm_op_state *ros = cb->sc_private;
    836      1.1     lukem 
    837      1.1     lukem 	rs->sr_attrs = ros->ors_attrs;
    838      1.1     lukem 
    839      1.1     lukem 	/* other overlays might have touched op->ors_attrs,
    840      1.1     lukem 	 * so we restore the original version here, otherwise
    841      1.1     lukem 	 * attribute-mapping might fail */
    842      1.1     lukem 	op->ors_attrs = ros->mapped_attrs;
    843      1.1     lukem 
    844      1.1     lukem  	return SLAP_CB_CONTINUE;
    845      1.1     lukem }
    846      1.1     lukem 
    847  1.1.1.2     lukem /*
    848  1.1.1.2     lukem  * NOTE: this implementation of get/release entry is probably far from
    849  1.1.1.2     lukem  * optimal.  The rationale consists in intercepting the request directed
    850  1.1.1.2     lukem  * to the underlying database, in order to rewrite/remap the request,
    851  1.1.1.2     lukem  * perform it using the modified data, duplicate the resulting entry
    852  1.1.1.2     lukem  * and finally free it when release is called.
    853  1.1.1.2     lukem  * This implies that subsequent overlays are not called, as the request
    854  1.1.1.2     lukem  * is directly shunted to the underlying database.
    855  1.1.1.2     lukem  */
    856  1.1.1.2     lukem static int
    857  1.1.1.2     lukem rwm_entry_release_rw( Operation *op, Entry *e, int rw )
    858  1.1.1.2     lukem {
    859  1.1.1.2     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    860  1.1.1.2     lukem 
    861  1.1.1.2     lukem 	/* can't be ours */
    862  1.1.1.2     lukem 	if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
    863  1.1.1.2     lukem 		return SLAP_CB_CONTINUE;
    864  1.1.1.2     lukem 	}
    865  1.1.1.2     lukem 
    866  1.1.1.2     lukem 	/* just free entry if (probably) ours */
    867  1.1.1.2     lukem 	if ( e->e_private == NULL && BER_BVISNULL( &e->e_bv ) ) {
    868  1.1.1.2     lukem 		entry_free( e );
    869  1.1.1.2     lukem 		return LDAP_SUCCESS;
    870  1.1.1.2     lukem 	}
    871  1.1.1.2     lukem 
    872  1.1.1.2     lukem 	return SLAP_CB_CONTINUE;
    873  1.1.1.2     lukem }
    874  1.1.1.2     lukem 
    875  1.1.1.2     lukem static int
    876  1.1.1.2     lukem rwm_entry_get_rw( Operation *op, struct berval *ndn,
    877  1.1.1.2     lukem 	ObjectClass *oc, AttributeDescription *at, int rw, Entry **ep )
    878  1.1.1.2     lukem {
    879  1.1.1.2     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    880  1.1.1.2     lukem 	int			rc;
    881  1.1.1.2     lukem 	BackendDB		db;
    882  1.1.1.2     lukem 	Operation		op2;
    883  1.1.1.2     lukem 	SlapReply		rs = { REP_SEARCH };
    884  1.1.1.2     lukem 
    885  1.1.1.2     lukem 	rwm_op_state		ros = { 0 };
    886  1.1.1.2     lukem 	struct berval		mndn = BER_BVNULL;
    887  1.1.1.2     lukem 
    888  1.1.1.2     lukem 	if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
    889  1.1.1.2     lukem 		return SLAP_CB_CONTINUE;
    890  1.1.1.2     lukem 	}
    891  1.1.1.2     lukem 
    892  1.1.1.2     lukem 	/* massage DN */
    893  1.1.1.2     lukem 	op2.o_tag = LDAP_REQ_SEARCH;
    894  1.1.1.2     lukem 	op2 = *op;
    895  1.1.1.2     lukem 	op2.o_req_dn = *ndn;
    896  1.1.1.2     lukem 	op2.o_req_ndn = *ndn;
    897  1.1.1.2     lukem 	rc = rwm_op_dn_massage( &op2, &rs, "searchDN", &ros );
    898  1.1.1.2     lukem 	if ( rc != LDAP_SUCCESS ) {
    899  1.1.1.2     lukem 		return LDAP_OTHER;
    900  1.1.1.2     lukem 	}
    901  1.1.1.2     lukem 
    902  1.1.1.2     lukem 	mndn = BER_BVISNULL( &ros.r_ndn ) ? *ndn : ros.r_ndn;
    903  1.1.1.2     lukem 
    904  1.1.1.2     lukem 	/* map attribute & objectClass */
    905  1.1.1.2     lukem 	if ( at != NULL ) {
    906  1.1.1.2     lukem 	}
    907  1.1.1.2     lukem 
    908  1.1.1.2     lukem 	if ( oc != NULL ) {
    909  1.1.1.2     lukem 	}
    910  1.1.1.2     lukem 
    911  1.1.1.2     lukem 	/* fetch entry */
    912  1.1.1.2     lukem 	db = *op->o_bd;
    913  1.1.1.2     lukem 	op2.o_bd = &db;
    914  1.1.1.2     lukem 	op2.o_bd->bd_info = (BackendInfo *)on->on_info->oi_orig;
    915  1.1.1.2     lukem 	op2.ors_attrs = slap_anlist_all_attributes;
    916  1.1.1.2     lukem 	rc = op2.o_bd->bd_info->bi_entry_get_rw( &op2, &mndn, oc, at, rw, ep );
    917  1.1.1.2     lukem 	if ( rc == LDAP_SUCCESS && *ep != NULL ) {
    918  1.1.1.2     lukem 		/* we assume be_entry_release() needs to be called */
    919  1.1.1.2     lukem 		rs.sr_flags = REP_ENTRY_MUSTRELEASE;
    920  1.1.1.2     lukem 		rs.sr_entry = *ep;
    921  1.1.1.2     lukem 
    922  1.1.1.2     lukem 		/* duplicate & release */
    923  1.1.1.2     lukem 		op2.o_bd->bd_info = (BackendInfo *)on;
    924  1.1.1.2     lukem 		rc = rwm_send_entry( &op2, &rs );
    925  1.1.1.4      tron 		RS_ASSERT( rs.sr_flags & REP_ENTRY_MUSTFLUSH );
    926  1.1.1.2     lukem 		if ( rc == SLAP_CB_CONTINUE ) {
    927  1.1.1.2     lukem 			*ep = rs.sr_entry;
    928  1.1.1.2     lukem 			rc = LDAP_SUCCESS;
    929  1.1.1.4      tron 		} else {
    930  1.1.1.4      tron 			assert( rc != LDAP_SUCCESS && rs.sr_entry == *ep );
    931  1.1.1.4      tron 			*ep = NULL;
    932  1.1.1.4      tron 			op2.o_bd->bd_info = (BackendInfo *)on->on_info;
    933  1.1.1.4      tron 			be_entry_release_r( &op2, rs.sr_entry );
    934  1.1.1.4      tron 			op2.o_bd->bd_info = (BackendInfo *)on;
    935  1.1.1.2     lukem 		}
    936  1.1.1.2     lukem 	}
    937  1.1.1.2     lukem 
    938  1.1.1.2     lukem 	if ( !BER_BVISNULL( &ros.r_ndn) && ros.r_ndn.bv_val != ndn->bv_val ) {
    939  1.1.1.2     lukem 		op->o_tmpfree( ros.r_ndn.bv_val, op->o_tmpmemctx );
    940  1.1.1.2     lukem 	}
    941  1.1.1.2     lukem 
    942  1.1.1.2     lukem 	return rc;
    943  1.1.1.2     lukem }
    944  1.1.1.2     lukem 
    945      1.1     lukem static int
    946      1.1     lukem rwm_op_search( Operation *op, SlapReply *rs )
    947      1.1     lukem {
    948      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
    949      1.1     lukem 	struct ldaprwmap	*rwmap =
    950      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
    951      1.1     lukem 
    952      1.1     lukem 	int			rc;
    953      1.1     lukem 	dncookie		dc;
    954      1.1     lukem 
    955      1.1     lukem 	struct berval		fstr = BER_BVNULL;
    956      1.1     lukem 	Filter			*f = NULL;
    957      1.1     lukem 
    958      1.1     lukem 	AttributeName		*an = NULL;
    959      1.1     lukem 
    960      1.1     lukem 	char			*text = NULL;
    961      1.1     lukem 
    962  1.1.1.4      tron 	rwm_op_cb		*roc = rwm_callback_get( op );
    963      1.1     lukem 
    964      1.1     lukem 	rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
    965      1.1     lukem 		"searchFilter", op->ors_filterstr.bv_val );
    966      1.1     lukem 	if ( rc == LDAP_SUCCESS )
    967      1.1     lukem 		rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
    968      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    969      1.1     lukem 		text = "searchDN massage error";
    970      1.1     lukem 		goto error_return;
    971      1.1     lukem 	}
    972      1.1     lukem 
    973      1.1     lukem 	/*
    974      1.1     lukem 	 * Rewrite the dn if needed
    975      1.1     lukem 	 */
    976      1.1     lukem 	dc.rwmap = rwmap;
    977      1.1     lukem 	dc.conn = op->o_conn;
    978      1.1     lukem 	dc.rs = rs;
    979      1.1     lukem 	dc.ctx = "searchFilterAttrDN";
    980      1.1     lukem 
    981      1.1     lukem 	rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
    982      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
    983      1.1     lukem 		text = "searchFilter/searchFilterAttrDN massage error";
    984      1.1     lukem 		goto error_return;
    985      1.1     lukem 	}
    986      1.1     lukem 
    987      1.1     lukem 	f = str2filter_x( op, fstr.bv_val );
    988      1.1     lukem 
    989      1.1     lukem 	if ( f == NULL ) {
    990      1.1     lukem 		text = "massaged filter parse error";
    991      1.1     lukem 		goto error_return;
    992      1.1     lukem 	}
    993      1.1     lukem 
    994      1.1     lukem 	op->ors_filter = f;
    995      1.1     lukem 	op->ors_filterstr = fstr;
    996      1.1     lukem 
    997  1.1.1.3      adam 	rc = rwm_map_attrnames( op, &rwmap->rwm_at, &rwmap->rwm_oc,
    998      1.1     lukem 			op->ors_attrs, &an, RWM_MAP );
    999      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1000      1.1     lukem 		text = "attribute list mapping error";
   1001      1.1     lukem 		goto error_return;
   1002      1.1     lukem 	}
   1003      1.1     lukem 
   1004      1.1     lukem 	op->ors_attrs = an;
   1005      1.1     lukem 	/* store the mapped Attributes for later usage, in
   1006      1.1     lukem 	 * the case that other overlays change op->ors_attrs */
   1007      1.1     lukem 	roc->ros.mapped_attrs = an;
   1008      1.1     lukem 	roc->cb.sc_response = rwm_swap_attrs;
   1009      1.1     lukem 
   1010      1.1     lukem 	op->o_callback = &roc->cb;
   1011      1.1     lukem 
   1012      1.1     lukem 	return SLAP_CB_CONTINUE;
   1013      1.1     lukem 
   1014      1.1     lukem error_return:;
   1015      1.1     lukem 	if ( an != NULL ) {
   1016      1.1     lukem 		ch_free( an );
   1017      1.1     lukem 	}
   1018      1.1     lukem 
   1019      1.1     lukem 	if ( f != NULL ) {
   1020  1.1.1.2     lukem 		filter_free_x( op, f, 1 );
   1021      1.1     lukem 	}
   1022      1.1     lukem 
   1023      1.1     lukem 	if ( !BER_BVISNULL( &fstr ) ) {
   1024  1.1.1.3      adam 		op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
   1025      1.1     lukem 	}
   1026      1.1     lukem 
   1027  1.1.1.2     lukem 	rwm_op_rollback( op, rs, &roc->ros );
   1028      1.1     lukem 	op->oq_search = roc->ros.oq_search;
   1029  1.1.1.2     lukem 	op->o_tmpfree( roc, op->o_tmpmemctx );
   1030      1.1     lukem 
   1031      1.1     lukem 	op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1032      1.1     lukem 	send_ldap_error( op, rs, rc, text );
   1033      1.1     lukem 
   1034      1.1     lukem 	return -1;
   1035      1.1     lukem 
   1036      1.1     lukem }
   1037      1.1     lukem 
   1038      1.1     lukem static int
   1039      1.1     lukem rwm_exop_passwd( Operation *op, SlapReply *rs )
   1040      1.1     lukem {
   1041      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1042      1.1     lukem 	int			rc;
   1043      1.1     lukem 	rwm_op_cb *roc;
   1044      1.1     lukem 
   1045      1.1     lukem 	struct berval	id = BER_BVNULL,
   1046      1.1     lukem 			pwold = BER_BVNULL,
   1047      1.1     lukem 			pwnew = BER_BVNULL;
   1048      1.1     lukem 	BerElement *ber = NULL;
   1049      1.1     lukem 
   1050      1.1     lukem 	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
   1051      1.1     lukem 		return LDAP_SUCCESS;
   1052      1.1     lukem 	}
   1053      1.1     lukem 
   1054      1.1     lukem 	if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
   1055      1.1     lukem 		rs->sr_err = LDAP_OTHER;
   1056      1.1     lukem 		return rs->sr_err;
   1057      1.1     lukem 	}
   1058      1.1     lukem 
   1059      1.1     lukem 	rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
   1060      1.1     lukem 		&pwold, &pwnew, &rs->sr_text );
   1061      1.1     lukem 	if ( rs->sr_err != LDAP_SUCCESS ) {
   1062      1.1     lukem 		return rs->sr_err;
   1063      1.1     lukem 	}
   1064      1.1     lukem 
   1065      1.1     lukem 	if ( !BER_BVISNULL( &id ) ) {
   1066      1.1     lukem 		char idNul = id.bv_val[id.bv_len];
   1067      1.1     lukem 		id.bv_val[id.bv_len] = '\0';
   1068      1.1     lukem 		rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
   1069      1.1     lukem 				&op->o_req_ndn, op->o_tmpmemctx );
   1070      1.1     lukem 		id.bv_val[id.bv_len] = idNul;
   1071      1.1     lukem 		if ( rs->sr_err != LDAP_SUCCESS ) {
   1072      1.1     lukem 			rs->sr_text = "Invalid DN";
   1073      1.1     lukem 			return rs->sr_err;
   1074      1.1     lukem 		}
   1075      1.1     lukem 
   1076      1.1     lukem 	} else {
   1077      1.1     lukem 		ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
   1078      1.1     lukem 		ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
   1079      1.1     lukem 	}
   1080      1.1     lukem 
   1081  1.1.1.4      tron 	roc = rwm_callback_get( op );
   1082      1.1     lukem 
   1083      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
   1084      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1085      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1086      1.1     lukem 		send_ldap_error( op, rs, rc, "extendedDN massage error" );
   1087      1.1     lukem 		return -1;
   1088      1.1     lukem 	}
   1089      1.1     lukem 
   1090      1.1     lukem 	ber = ber_alloc_t( LBER_USE_DER );
   1091      1.1     lukem 	if ( !ber ) {
   1092      1.1     lukem 		rs->sr_err = LDAP_OTHER;
   1093      1.1     lukem 		rs->sr_text = "No memory";
   1094      1.1     lukem 		return rs->sr_err;
   1095      1.1     lukem 	}
   1096      1.1     lukem 	ber_printf( ber, "{" );
   1097      1.1     lukem 	if ( !BER_BVISNULL( &id )) {
   1098      1.1     lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
   1099      1.1     lukem 			&op->o_req_dn );
   1100      1.1     lukem 	}
   1101      1.1     lukem 	if ( !BER_BVISNULL( &pwold )) {
   1102      1.1     lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
   1103      1.1     lukem 	}
   1104      1.1     lukem 	if ( !BER_BVISNULL( &pwnew )) {
   1105      1.1     lukem 		ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
   1106      1.1     lukem 	}
   1107      1.1     lukem 	ber_printf( ber, "N}" );
   1108      1.1     lukem 	ber_flatten( ber, &op->ore_reqdata );
   1109      1.1     lukem 	ber_free( ber, 1 );
   1110      1.1     lukem 
   1111      1.1     lukem 	op->o_callback = &roc->cb;
   1112      1.1     lukem 
   1113      1.1     lukem 	return SLAP_CB_CONTINUE;
   1114      1.1     lukem }
   1115      1.1     lukem 
   1116      1.1     lukem static struct exop {
   1117      1.1     lukem 	struct berval	oid;
   1118      1.1     lukem 	BI_op_extended	*extended;
   1119      1.1     lukem } exop_table[] = {
   1120      1.1     lukem 	{ BER_BVC(LDAP_EXOP_MODIFY_PASSWD),	rwm_exop_passwd },
   1121      1.1     lukem 	{ BER_BVNULL, NULL }
   1122      1.1     lukem };
   1123      1.1     lukem 
   1124      1.1     lukem static int
   1125      1.1     lukem rwm_extended( Operation *op, SlapReply *rs )
   1126      1.1     lukem {
   1127      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1128      1.1     lukem 	int			rc;
   1129      1.1     lukem 	rwm_op_cb *roc;
   1130      1.1     lukem 
   1131      1.1     lukem 	int	i;
   1132      1.1     lukem 
   1133      1.1     lukem 	for ( i = 0; exop_table[i].extended != NULL; i++ ) {
   1134      1.1     lukem 		if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
   1135      1.1     lukem 		{
   1136      1.1     lukem 			rc = exop_table[i].extended( op, rs );
   1137      1.1     lukem 			switch ( rc ) {
   1138      1.1     lukem 			case LDAP_SUCCESS:
   1139      1.1     lukem 				break;
   1140      1.1     lukem 
   1141      1.1     lukem 			case SLAP_CB_CONTINUE:
   1142      1.1     lukem 			case SLAPD_ABANDON:
   1143      1.1     lukem 				return rc;
   1144      1.1     lukem 
   1145      1.1     lukem 			default:
   1146      1.1     lukem 				send_ldap_result( op, rs );
   1147      1.1     lukem 				return rc;
   1148      1.1     lukem 			}
   1149      1.1     lukem 			break;
   1150      1.1     lukem 		}
   1151      1.1     lukem 	}
   1152      1.1     lukem 
   1153  1.1.1.4      tron 	roc = rwm_callback_get( op );
   1154      1.1     lukem 
   1155      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
   1156      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1157      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1158      1.1     lukem 		send_ldap_error( op, rs, rc, "extendedDN massage error" );
   1159      1.1     lukem 		return -1;
   1160      1.1     lukem 	}
   1161      1.1     lukem 
   1162      1.1     lukem 	/* TODO: rewrite/map extended data ? ... */
   1163      1.1     lukem 	op->o_callback = &roc->cb;
   1164      1.1     lukem 
   1165      1.1     lukem 	return SLAP_CB_CONTINUE;
   1166      1.1     lukem }
   1167      1.1     lukem 
   1168  1.1.1.4      tron static void
   1169      1.1     lukem rwm_matched( Operation *op, SlapReply *rs )
   1170      1.1     lukem {
   1171      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1172      1.1     lukem 	struct ldaprwmap	*rwmap =
   1173      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1174      1.1     lukem 
   1175      1.1     lukem 	struct berval		dn, mdn;
   1176      1.1     lukem 	dncookie		dc;
   1177      1.1     lukem 	int			rc;
   1178      1.1     lukem 
   1179      1.1     lukem 	if ( rs->sr_matched == NULL ) {
   1180  1.1.1.4      tron 		return;
   1181      1.1     lukem 	}
   1182      1.1     lukem 
   1183      1.1     lukem 	dc.rwmap = rwmap;
   1184      1.1     lukem 	dc.conn = op->o_conn;
   1185      1.1     lukem 	dc.rs = rs;
   1186      1.1     lukem 	dc.ctx = "matchedDN";
   1187      1.1     lukem 	ber_str2bv( rs->sr_matched, 0, 0, &dn );
   1188      1.1     lukem 	mdn = dn;
   1189      1.1     lukem 	rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
   1190      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1191      1.1     lukem 		rs->sr_err = rc;
   1192      1.1     lukem 		rs->sr_text = "Rewrite error";
   1193      1.1     lukem 
   1194  1.1.1.4      tron 	} else if ( mdn.bv_val != dn.bv_val ) {
   1195      1.1     lukem 		if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
   1196      1.1     lukem 			ch_free( (void *)rs->sr_matched );
   1197      1.1     lukem 
   1198      1.1     lukem 		} else {
   1199      1.1     lukem 			rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
   1200      1.1     lukem 		}
   1201      1.1     lukem 		rs->sr_matched = mdn.bv_val;
   1202      1.1     lukem 	}
   1203      1.1     lukem }
   1204      1.1     lukem 
   1205      1.1     lukem static int
   1206      1.1     lukem rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
   1207      1.1     lukem {
   1208      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1209      1.1     lukem 	struct ldaprwmap	*rwmap =
   1210      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1211      1.1     lukem 
   1212      1.1     lukem 	dncookie		dc;
   1213      1.1     lukem 	int			rc;
   1214      1.1     lukem 	Attribute		**ap;
   1215      1.1     lukem 	int			isupdate;
   1216      1.1     lukem 	int			check_duplicate_attrs = 0;
   1217      1.1     lukem 
   1218      1.1     lukem 	/*
   1219      1.1     lukem 	 * Rewrite the dn attrs, if needed
   1220      1.1     lukem 	 */
   1221      1.1     lukem 	dc.rwmap = rwmap;
   1222      1.1     lukem 	dc.conn = op->o_conn;
   1223      1.1     lukem 	dc.rs = NULL;
   1224      1.1     lukem 
   1225      1.1     lukem 	/* FIXME: the entries are in the remote mapping form;
   1226      1.1     lukem 	 * so we need to select those attributes we are willing
   1227      1.1     lukem 	 * to return, and remap them accordingly */
   1228      1.1     lukem 
   1229      1.1     lukem 	/* FIXME: in principle, one could map an attribute
   1230      1.1     lukem 	 * on top of another, which already exists.
   1231      1.1     lukem 	 * As such, in the end there might exist more than
   1232      1.1     lukem 	 * one instance of an attribute.
   1233      1.1     lukem 	 * We should at least check if this occurs, and issue
   1234      1.1     lukem 	 * an error (because multiple instances of attrs in
   1235      1.1     lukem 	 * response are not valid), or merge the values (what
   1236      1.1     lukem 	 * about duplicate values?) */
   1237      1.1     lukem 	isupdate = be_shadow_update( op );
   1238      1.1     lukem 	for ( ap = a_first; *ap; ) {
   1239      1.1     lukem 		struct ldapmapping	*mapping = NULL;
   1240      1.1     lukem 		int			drop_missing;
   1241      1.1     lukem 		int			last = -1;
   1242      1.1     lukem 		Attribute		*a;
   1243      1.1     lukem 
   1244  1.1.1.2     lukem 		if ( ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS ) &&
   1245  1.1.1.2     lukem 				op->ors_attrs != NULL &&
   1246  1.1.1.2     lukem 				!SLAP_USERATTRS( rs->sr_attr_flags ) &&
   1247  1.1.1.2     lukem 				!ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
   1248      1.1     lukem 		{
   1249  1.1.1.2     lukem 			goto cleanup_attr;
   1250  1.1.1.2     lukem 		}
   1251      1.1     lukem 
   1252  1.1.1.2     lukem 		drop_missing = rwm_mapping( &rwmap->rwm_at,
   1253  1.1.1.2     lukem 				&(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
   1254  1.1.1.2     lukem 		if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
   1255  1.1.1.2     lukem 		{
   1256  1.1.1.2     lukem 			goto cleanup_attr;
   1257  1.1.1.2     lukem 		}
   1258  1.1.1.2     lukem 		if ( mapping != NULL ) {
   1259  1.1.1.2     lukem 			assert( mapping->m_dst_ad != NULL );
   1260      1.1     lukem 
   1261  1.1.1.2     lukem 			/* try to normalize mapped Attributes if the original
   1262  1.1.1.2     lukem 			 * AttributeType was not normalized */
   1263  1.1.1.2     lukem 			if ( (!(*ap)->a_desc->ad_type->sat_equality ||
   1264  1.1.1.2     lukem 				!(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
   1265  1.1.1.2     lukem 				mapping->m_dst_ad->ad_type->sat_equality &&
   1266  1.1.1.2     lukem 				mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
   1267  1.1.1.2     lukem 			{
   1268  1.1.1.2     lukem 				if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS))
   1269      1.1     lukem 				{
   1270      1.1     lukem 					int i = 0;
   1271      1.1     lukem 
   1272      1.1     lukem 					last = (*ap)->a_numvals;
   1273      1.1     lukem 					if ( last )
   1274      1.1     lukem 					{
   1275      1.1     lukem 						(*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
   1276      1.1     lukem 
   1277      1.1     lukem 						for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
   1278      1.1     lukem 							int		rc;
   1279      1.1     lukem 							/*
   1280      1.1     lukem 							 * check that each value is valid per syntax
   1281      1.1     lukem 							 * and pretty if appropriate
   1282      1.1     lukem 							 */
   1283      1.1     lukem 							rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
   1284      1.1     lukem 								SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
   1285      1.1     lukem 								mapping->m_dst_ad->ad_type->sat_syntax,
   1286      1.1     lukem 								mapping->m_dst_ad->ad_type->sat_equality,
   1287      1.1     lukem 								&(*ap)->a_vals[i], &(*ap)->a_nvals[i],
   1288      1.1     lukem 								NULL );
   1289      1.1     lukem 
   1290      1.1     lukem 							if ( rc != LDAP_SUCCESS ) {
   1291  1.1.1.4      tron 								/* FIXME: this is wrong, putting a non-normalized value
   1292  1.1.1.4      tron 								 * into nvals. But when a proxy sends us bogus data,
   1293  1.1.1.4      tron 								 * we still need to give it to the client, even if it
   1294  1.1.1.4      tron 								 * violates the syntax. I.e., we don't want to silently
   1295  1.1.1.4      tron 								 * drop things and trigger an apparent data loss.
   1296  1.1.1.4      tron 								 */
   1297  1.1.1.4      tron 								ber_dupbv( &(*ap)->a_nvals[i], &(*ap)->a_vals[i] );
   1298      1.1     lukem 							}
   1299      1.1     lukem 						}
   1300      1.1     lukem 						BER_BVZERO( &(*ap)->a_nvals[i] );
   1301      1.1     lukem 					}
   1302  1.1.1.2     lukem 
   1303  1.1.1.2     lukem 				} else {
   1304  1.1.1.2     lukem 					assert( (*ap)->a_nvals == (*ap)->a_vals );
   1305  1.1.1.2     lukem 					(*ap)->a_nvals = NULL;
   1306  1.1.1.2     lukem 					ber_bvarray_dup_x( &(*ap)->a_nvals, (*ap)->a_vals, NULL );
   1307      1.1     lukem 				}
   1308  1.1.1.2     lukem 			}
   1309      1.1     lukem 
   1310  1.1.1.2     lukem 			/* rewrite the attribute description */
   1311  1.1.1.2     lukem 			(*ap)->a_desc = mapping->m_dst_ad;
   1312      1.1     lukem 
   1313  1.1.1.2     lukem 			/* will need to check for duplicate attrs */
   1314  1.1.1.2     lukem 			check_duplicate_attrs++;
   1315      1.1     lukem 		}
   1316      1.1     lukem 
   1317      1.1     lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
   1318      1.1     lukem 			if ( stripEntryDN ) {
   1319      1.1     lukem 				/* will be generated by frontend */
   1320      1.1     lukem 				goto cleanup_attr;
   1321      1.1     lukem 			}
   1322      1.1     lukem 
   1323      1.1     lukem 		} else if ( !isupdate
   1324      1.1     lukem 			&& !get_relax( op )
   1325      1.1     lukem 			&& (*ap)->a_desc->ad_type->sat_no_user_mod
   1326      1.1     lukem 			&& (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
   1327      1.1     lukem 		{
   1328      1.1     lukem 			goto next_attr;
   1329      1.1     lukem 		}
   1330      1.1     lukem 
   1331      1.1     lukem 		if ( last == -1 ) { /* not yet counted */
   1332      1.1     lukem 			last = (*ap)->a_numvals;
   1333      1.1     lukem 		}
   1334      1.1     lukem 
   1335      1.1     lukem 		if ( last == 0 ) {
   1336      1.1     lukem 			/* empty? leave it in place because of attrsonly and vlv */
   1337      1.1     lukem 			goto next_attr;
   1338      1.1     lukem 		}
   1339      1.1     lukem 		last--;
   1340      1.1     lukem 
   1341      1.1     lukem 		if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
   1342      1.1     lukem 				|| (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
   1343      1.1     lukem 		{
   1344      1.1     lukem 			struct berval	*bv;
   1345      1.1     lukem 
   1346      1.1     lukem 			for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
   1347      1.1     lukem 				struct berval	mapped;
   1348      1.1     lukem 
   1349      1.1     lukem 				rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
   1350      1.1     lukem 				if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
   1351      1.1     lukem remove_oc:;
   1352      1.1     lukem 					ch_free( bv[0].bv_val );
   1353      1.1     lukem 					BER_BVZERO( &bv[0] );
   1354      1.1     lukem 					if ( &(*ap)->a_vals[last] > &bv[0] ) {
   1355      1.1     lukem 						bv[0] = (*ap)->a_vals[last];
   1356      1.1     lukem 						BER_BVZERO( &(*ap)->a_vals[last] );
   1357      1.1     lukem 					}
   1358      1.1     lukem 					last--;
   1359      1.1     lukem 					bv--;
   1360      1.1     lukem 
   1361  1.1.1.2     lukem 				} else if ( mapped.bv_val != bv[0].bv_val
   1362  1.1.1.2     lukem 					&& ber_bvstrcasecmp( &mapped, &bv[0] ) != 0 )
   1363  1.1.1.2     lukem 				{
   1364      1.1     lukem 					int	i;
   1365      1.1     lukem 
   1366      1.1     lukem 					for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
   1367      1.1     lukem 						if ( &(*ap)->a_vals[ i ] == bv ) {
   1368      1.1     lukem 							continue;
   1369      1.1     lukem 						}
   1370      1.1     lukem 
   1371      1.1     lukem 						if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
   1372      1.1     lukem 							break;
   1373      1.1     lukem 						}
   1374      1.1     lukem 					}
   1375      1.1     lukem 
   1376      1.1     lukem 					if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
   1377      1.1     lukem 						goto remove_oc;
   1378      1.1     lukem 					}
   1379      1.1     lukem 
   1380      1.1     lukem 					/*
   1381      1.1     lukem 					 * FIXME: after LBER_FREEing
   1382      1.1     lukem 					 * the value is replaced by
   1383      1.1     lukem 					 * ch_alloc'ed memory
   1384      1.1     lukem 					 */
   1385      1.1     lukem 					ber_bvreplace( &bv[0], &mapped );
   1386      1.1     lukem 
   1387      1.1     lukem 					/* FIXME: will need to check
   1388      1.1     lukem 					 * if the structuralObjectClass
   1389      1.1     lukem 					 * changed */
   1390      1.1     lukem 				}
   1391      1.1     lukem 			}
   1392      1.1     lukem 
   1393      1.1     lukem 		/*
   1394      1.1     lukem 		 * It is necessary to try to rewrite attributes with
   1395      1.1     lukem 		 * dn syntax because they might be used in ACLs as
   1396      1.1     lukem 		 * members of groups; since ACLs are applied to the
   1397      1.1     lukem 		 * rewritten stuff, no dn-based subject clause could
   1398      1.1     lukem 		 * be used at the ldap backend side (see
   1399      1.1     lukem 		 * http://www.OpenLDAP.org/faq/data/cache/452.html)
   1400      1.1     lukem 		 * The problem can be overcome by moving the dn-based
   1401      1.1     lukem 		 * ACLs to the target directory server, and letting
   1402      1.1     lukem 		 * everything pass thru the ldap backend. */
   1403      1.1     lukem 		/* FIXME: handle distinguishedName-like syntaxes, like
   1404      1.1     lukem 		 * nameAndOptionalUID */
   1405      1.1     lukem 		} else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
   1406      1.1     lukem 				|| ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
   1407      1.1     lukem 		{
   1408      1.1     lukem 			dc.ctx = "searchAttrDN";
   1409  1.1.1.2     lukem 			rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals, (*ap)->a_nvals );
   1410      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
   1411      1.1     lukem 				goto cleanup_attr;
   1412      1.1     lukem 			}
   1413      1.1     lukem 
   1414      1.1     lukem 		} else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
   1415      1.1     lukem 			dc.ctx = "searchAttrDN";
   1416      1.1     lukem 			rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
   1417      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
   1418      1.1     lukem 				goto cleanup_attr;
   1419      1.1     lukem 			}
   1420      1.1     lukem 		}
   1421      1.1     lukem 
   1422      1.1     lukem 
   1423      1.1     lukem next_attr:;
   1424      1.1     lukem 		ap = &(*ap)->a_next;
   1425      1.1     lukem 		continue;
   1426      1.1     lukem 
   1427      1.1     lukem cleanup_attr:;
   1428      1.1     lukem 		a = *ap;
   1429      1.1     lukem 		*ap = (*ap)->a_next;
   1430      1.1     lukem 
   1431      1.1     lukem 		attr_free( a );
   1432      1.1     lukem 	}
   1433      1.1     lukem 
   1434      1.1     lukem 	/* only check if some mapping occurred */
   1435      1.1     lukem 	if ( check_duplicate_attrs ) {
   1436      1.1     lukem 		for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
   1437      1.1     lukem 			Attribute	**tap;
   1438      1.1     lukem 
   1439      1.1     lukem 			for ( tap = &(*ap)->a_next; *tap != NULL; ) {
   1440      1.1     lukem 				if ( (*tap)->a_desc == (*ap)->a_desc ) {
   1441      1.1     lukem 					Entry		e = { 0 };
   1442      1.1     lukem 					Modification	mod = { 0 };
   1443      1.1     lukem 					const char	*text = NULL;
   1444      1.1     lukem 					char		textbuf[ SLAP_TEXT_BUFLEN ];
   1445      1.1     lukem 					Attribute	*next = (*tap)->a_next;
   1446      1.1     lukem 
   1447      1.1     lukem 					BER_BVSTR( &e.e_name, "" );
   1448      1.1     lukem 					BER_BVSTR( &e.e_nname, "" );
   1449      1.1     lukem 					e.e_attrs = *ap;
   1450      1.1     lukem 					mod.sm_op = LDAP_MOD_ADD;
   1451      1.1     lukem 					mod.sm_desc = (*ap)->a_desc;
   1452      1.1     lukem 					mod.sm_type = mod.sm_desc->ad_cname;
   1453      1.1     lukem 					mod.sm_numvals = (*tap)->a_numvals;
   1454      1.1     lukem 					mod.sm_values = (*tap)->a_vals;
   1455      1.1     lukem 					if ( (*tap)->a_nvals != (*tap)->a_vals ) {
   1456      1.1     lukem 						mod.sm_nvalues = (*tap)->a_nvals;
   1457      1.1     lukem 					}
   1458      1.1     lukem 
   1459      1.1     lukem 					(void)modify_add_values( &e, &mod,
   1460      1.1     lukem 						/* permissive */ 1,
   1461      1.1     lukem 						&text, textbuf, sizeof( textbuf ) );
   1462      1.1     lukem 
   1463      1.1     lukem 					/* should not insert new attrs! */
   1464      1.1     lukem 					assert( e.e_attrs == *ap );
   1465      1.1     lukem 
   1466      1.1     lukem 					attr_free( *tap );
   1467      1.1     lukem 					*tap = next;
   1468      1.1     lukem 
   1469      1.1     lukem 				} else {
   1470      1.1     lukem 					tap = &(*tap)->a_next;
   1471      1.1     lukem 				}
   1472      1.1     lukem 			}
   1473      1.1     lukem 		}
   1474      1.1     lukem 	}
   1475      1.1     lukem 
   1476      1.1     lukem 	return 0;
   1477      1.1     lukem }
   1478      1.1     lukem 
   1479  1.1.1.4      tron /* Should return SLAP_CB_CONTINUE or failure, never LDAP_SUCCESS. */
   1480      1.1     lukem static int
   1481      1.1     lukem rwm_send_entry( Operation *op, SlapReply *rs )
   1482      1.1     lukem {
   1483      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1484      1.1     lukem 	struct ldaprwmap	*rwmap =
   1485      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1486      1.1     lukem 
   1487      1.1     lukem 	Entry			*e = NULL;
   1488      1.1     lukem 	struct berval		dn = BER_BVNULL,
   1489      1.1     lukem 				ndn = BER_BVNULL;
   1490      1.1     lukem 	dncookie		dc;
   1491      1.1     lukem 	int			rc;
   1492      1.1     lukem 
   1493      1.1     lukem 	assert( rs->sr_entry != NULL );
   1494      1.1     lukem 
   1495      1.1     lukem 	/*
   1496      1.1     lukem 	 * Rewrite the dn of the result, if needed
   1497      1.1     lukem 	 */
   1498      1.1     lukem 	dc.rwmap = rwmap;
   1499      1.1     lukem 	dc.conn = op->o_conn;
   1500      1.1     lukem 	dc.rs = NULL;
   1501      1.1     lukem 	dc.ctx = "searchEntryDN";
   1502      1.1     lukem 
   1503      1.1     lukem 	e = rs->sr_entry;
   1504      1.1     lukem 	if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
   1505      1.1     lukem 		/* FIXME: all we need to duplicate are:
   1506      1.1     lukem 		 * - dn
   1507      1.1     lukem 		 * - ndn
   1508      1.1     lukem 		 * - attributes that are requested
   1509      1.1     lukem 		 * - no values if attrsonly is set
   1510      1.1     lukem 		 */
   1511      1.1     lukem 		e = entry_dup( e );
   1512      1.1     lukem 		if ( e == NULL ) {
   1513      1.1     lukem 			rc = LDAP_NO_MEMORY;
   1514      1.1     lukem 			goto fail;
   1515      1.1     lukem 		}
   1516  1.1.1.4      tron 	} else if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
   1517  1.1.1.4      tron 		/* ITS#6423: REP_ENTRY_MUSTRELEASE incompatible
   1518  1.1.1.4      tron 		 * with REP_ENTRY_MODIFIABLE */
   1519  1.1.1.4      tron 		RS_ASSERT( 0 );
   1520  1.1.1.4      tron 		rc = 1;
   1521  1.1.1.4      tron 		goto fail;
   1522      1.1     lukem 	}
   1523      1.1     lukem 
   1524      1.1     lukem 	/*
   1525      1.1     lukem 	 * Note: this may fail if the target host(s) schema differs
   1526      1.1     lukem 	 * from the one known to the meta, and a DN with unknown
   1527      1.1     lukem 	 * attributes is returned.
   1528      1.1     lukem 	 */
   1529      1.1     lukem 	dn = e->e_name;
   1530      1.1     lukem 	ndn = e->e_nname;
   1531      1.1     lukem 	rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
   1532      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1533      1.1     lukem 		rc = 1;
   1534      1.1     lukem 		goto fail;
   1535      1.1     lukem 	}
   1536      1.1     lukem 
   1537      1.1     lukem 	if ( e->e_name.bv_val != dn.bv_val ) {
   1538      1.1     lukem 		ch_free( e->e_name.bv_val );
   1539      1.1     lukem 		ch_free( e->e_nname.bv_val );
   1540      1.1     lukem 
   1541      1.1     lukem 		e->e_name = dn;
   1542      1.1     lukem 		e->e_nname = ndn;
   1543      1.1     lukem 	}
   1544      1.1     lukem 
   1545      1.1     lukem 	/* TODO: map entry attribute types, objectclasses
   1546      1.1     lukem 	 * and dn-valued attribute values */
   1547      1.1     lukem 
   1548      1.1     lukem 	/* FIXME: the entries are in the remote mapping form;
   1549      1.1     lukem 	 * so we need to select those attributes we are willing
   1550      1.1     lukem 	 * to return, and remap them accordingly */
   1551      1.1     lukem 	(void)rwm_attrs( op, rs, &e->e_attrs, 1 );
   1552      1.1     lukem 
   1553  1.1.1.4      tron 	if ( e != rs->sr_entry ) {
   1554  1.1.1.4      tron 		/* Reimplementing rs_replace_entry(), I suppose to
   1555  1.1.1.4      tron 		 * bypass our own dubious rwm_entry_release_rw() */
   1556  1.1.1.4      tron 		if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
   1557  1.1.1.4      tron 			rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
   1558  1.1.1.4      tron 			op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1559  1.1.1.4      tron 			be_entry_release_r( op, rs->sr_entry );
   1560  1.1.1.4      tron 			op->o_bd->bd_info = (BackendInfo *)on;
   1561  1.1.1.4      tron 		} else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
   1562  1.1.1.4      tron 			entry_free( rs->sr_entry );
   1563  1.1.1.3      adam 		}
   1564  1.1.1.4      tron 		rs->sr_entry = e;
   1565  1.1.1.4      tron 		rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
   1566      1.1     lukem 	}
   1567      1.1     lukem 
   1568      1.1     lukem 	return SLAP_CB_CONTINUE;
   1569      1.1     lukem 
   1570      1.1     lukem fail:;
   1571      1.1     lukem 	if ( e != NULL && e != rs->sr_entry ) {
   1572      1.1     lukem 		if ( e->e_name.bv_val == dn.bv_val ) {
   1573      1.1     lukem 			BER_BVZERO( &e->e_name );
   1574      1.1     lukem 		}
   1575      1.1     lukem 
   1576      1.1     lukem 		if ( e->e_nname.bv_val == ndn.bv_val ) {
   1577      1.1     lukem 			BER_BVZERO( &e->e_nname );
   1578      1.1     lukem 		}
   1579      1.1     lukem 
   1580      1.1     lukem 		entry_free( e );
   1581      1.1     lukem 	}
   1582      1.1     lukem 
   1583      1.1     lukem 	if ( !BER_BVISNULL( &dn ) ) {
   1584      1.1     lukem 		ch_free( dn.bv_val );
   1585      1.1     lukem 	}
   1586      1.1     lukem 
   1587      1.1     lukem 	if ( !BER_BVISNULL( &ndn ) ) {
   1588      1.1     lukem 		ch_free( ndn.bv_val );
   1589      1.1     lukem 	}
   1590      1.1     lukem 
   1591      1.1     lukem 	return rc;
   1592      1.1     lukem }
   1593      1.1     lukem 
   1594      1.1     lukem static int
   1595      1.1     lukem rwm_operational( Operation *op, SlapReply *rs )
   1596      1.1     lukem {
   1597      1.1     lukem 	/* FIXME: the entries are in the remote mapping form;
   1598      1.1     lukem 	 * so we need to select those attributes we are willing
   1599      1.1     lukem 	 * to return, and remap them accordingly */
   1600      1.1     lukem 	if ( rs->sr_operational_attrs ) {
   1601      1.1     lukem 		rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
   1602      1.1     lukem 	}
   1603      1.1     lukem 
   1604      1.1     lukem 	return SLAP_CB_CONTINUE;
   1605      1.1     lukem }
   1606      1.1     lukem 
   1607      1.1     lukem #if 0
   1608      1.1     lukem /* don't use this; it cannot be reverted, and leaves op->o_req_dn
   1609      1.1     lukem  * rewritten for subsequent operations; fine for plain suffixmassage,
   1610      1.1     lukem  * but destroys everything else */
   1611      1.1     lukem static int
   1612      1.1     lukem rwm_chk_referrals( Operation *op, SlapReply *rs )
   1613      1.1     lukem {
   1614      1.1     lukem 	slap_overinst		*on = (slap_overinst *) op->o_bd->bd_info;
   1615      1.1     lukem 	int			rc;
   1616      1.1     lukem 
   1617      1.1     lukem 	rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
   1618      1.1     lukem 	if ( rc != LDAP_SUCCESS ) {
   1619      1.1     lukem 		op->o_bd->bd_info = (BackendInfo *)on->on_info;
   1620      1.1     lukem 		send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
   1621      1.1     lukem 		return -1;
   1622      1.1     lukem 	}
   1623      1.1     lukem 
   1624      1.1     lukem 	return SLAP_CB_CONTINUE;
   1625      1.1     lukem }
   1626      1.1     lukem #endif
   1627      1.1     lukem 
   1628      1.1     lukem static int
   1629      1.1     lukem rwm_rw_config(
   1630      1.1     lukem 	BackendDB	*be,
   1631      1.1     lukem 	const char	*fname,
   1632      1.1     lukem 	int		lineno,
   1633      1.1     lukem 	int		argc,
   1634      1.1     lukem 	char		**argv )
   1635      1.1     lukem {
   1636      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1637      1.1     lukem 	struct ldaprwmap	*rwmap =
   1638      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1639      1.1     lukem 
   1640      1.1     lukem 	return rewrite_parse( rwmap->rwm_rw,
   1641      1.1     lukem 				fname, lineno, argc, argv );
   1642      1.1     lukem 
   1643      1.1     lukem 	return 0;
   1644      1.1     lukem }
   1645      1.1     lukem 
   1646      1.1     lukem static int
   1647      1.1     lukem rwm_suffixmassage_config(
   1648      1.1     lukem 	BackendDB	*be,
   1649      1.1     lukem 	const char	*fname,
   1650      1.1     lukem 	int		lineno,
   1651      1.1     lukem 	int		argc,
   1652      1.1     lukem 	char		**argv )
   1653      1.1     lukem {
   1654      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1655      1.1     lukem 	struct ldaprwmap	*rwmap =
   1656      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1657      1.1     lukem 
   1658      1.1     lukem 	struct berval		bvnc, nvnc, pvnc, brnc, nrnc, prnc;
   1659      1.1     lukem 	int			massaged;
   1660      1.1     lukem 	int			rc;
   1661      1.1     lukem 
   1662      1.1     lukem 	/*
   1663      1.1     lukem 	 * syntax:
   1664      1.1     lukem 	 *
   1665      1.1     lukem 	 * 	suffixmassage [<suffix>] <massaged suffix>
   1666      1.1     lukem 	 *
   1667      1.1     lukem 	 * the [<suffix>] field must be defined as a valid suffix
   1668      1.1     lukem 	 * for the current database;
   1669      1.1     lukem 	 * the <massaged suffix> shouldn't have already been
   1670      1.1     lukem 	 * defined as a valid suffix for the current server
   1671      1.1     lukem 	 */
   1672      1.1     lukem 	if ( argc == 2 ) {
   1673      1.1     lukem 		if ( be->be_suffix == NULL ) {
   1674  1.1.1.3      adam  			Debug( LDAP_DEBUG_ANY, "%s: line %d: "
   1675      1.1     lukem 				       " \"suffixMassage [<suffix>]"
   1676      1.1     lukem 				       " <massaged suffix>\" without "
   1677      1.1     lukem 				       "<suffix> part requires database "
   1678      1.1     lukem 				       "suffix be defined first.\n",
   1679  1.1.1.3      adam 				fname, lineno, 0 );
   1680      1.1     lukem 			return 1;
   1681      1.1     lukem 		}
   1682      1.1     lukem 		bvnc = be->be_suffix[ 0 ];
   1683      1.1     lukem 		massaged = 1;
   1684      1.1     lukem 
   1685      1.1     lukem 	} else if ( argc == 3 ) {
   1686      1.1     lukem 		ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
   1687      1.1     lukem 		massaged = 2;
   1688      1.1     lukem 
   1689      1.1     lukem 	} else  {
   1690  1.1.1.3      adam  		Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is"
   1691      1.1     lukem 			       " \"suffixMassage [<suffix>]"
   1692      1.1     lukem 			       " <massaged suffix>\"\n",
   1693  1.1.1.3      adam 			fname, lineno, 0 );
   1694      1.1     lukem 		return 1;
   1695      1.1     lukem 	}
   1696      1.1     lukem 
   1697      1.1     lukem 	if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
   1698  1.1.1.3      adam 		Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
   1699      1.1     lukem 			fname, lineno, bvnc.bv_val );
   1700      1.1     lukem 		return 1;
   1701      1.1     lukem 	}
   1702      1.1     lukem 
   1703      1.1     lukem 	ber_str2bv( argv[ massaged ], 0, 0, &brnc );
   1704      1.1     lukem 	if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
   1705  1.1.1.3      adam 		Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
   1706      1.1     lukem 				fname, lineno, brnc.bv_val );
   1707      1.1     lukem 		free( nvnc.bv_val );
   1708      1.1     lukem 		free( pvnc.bv_val );
   1709      1.1     lukem 		return 1;
   1710      1.1     lukem 	}
   1711      1.1     lukem 
   1712      1.1     lukem 	/*
   1713      1.1     lukem 	 * The suffix massaging is emulated
   1714      1.1     lukem 	 * by means of the rewrite capabilities
   1715      1.1     lukem 	 */
   1716      1.1     lukem  	rc = rwm_suffix_massage_config( rwmap->rwm_rw,
   1717      1.1     lukem 			&pvnc, &nvnc, &prnc, &nrnc );
   1718      1.1     lukem 	free( nvnc.bv_val );
   1719      1.1     lukem 	free( pvnc.bv_val );
   1720      1.1     lukem 	free( nrnc.bv_val );
   1721      1.1     lukem 	free( prnc.bv_val );
   1722      1.1     lukem 
   1723      1.1     lukem 	return rc;
   1724      1.1     lukem }
   1725      1.1     lukem 
   1726      1.1     lukem static int
   1727      1.1     lukem rwm_m_config(
   1728      1.1     lukem 	BackendDB	*be,
   1729      1.1     lukem 	const char	*fname,
   1730      1.1     lukem 	int		lineno,
   1731      1.1     lukem 	int		argc,
   1732      1.1     lukem 	char		**argv )
   1733      1.1     lukem {
   1734      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1735      1.1     lukem 	struct ldaprwmap	*rwmap =
   1736      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1737      1.1     lukem 
   1738      1.1     lukem 	/* objectclass/attribute mapping */
   1739      1.1     lukem 	return rwm_map_config( &rwmap->rwm_oc,
   1740      1.1     lukem 			&rwmap->rwm_at,
   1741      1.1     lukem 			fname, lineno, argc, argv );
   1742      1.1     lukem }
   1743      1.1     lukem 
   1744      1.1     lukem static int
   1745      1.1     lukem rwm_response( Operation *op, SlapReply *rs )
   1746      1.1     lukem {
   1747      1.1     lukem 	slap_overinst		*on = (slap_overinst *)op->o_bd->bd_info;
   1748      1.1     lukem 	struct ldaprwmap	*rwmap =
   1749      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1750      1.1     lukem 
   1751      1.1     lukem 	int		rc;
   1752      1.1     lukem 
   1753      1.1     lukem 	if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
   1754      1.1     lukem 		return rwm_send_entry( op, rs );
   1755      1.1     lukem 	}
   1756      1.1     lukem 
   1757      1.1     lukem 	switch( op->o_tag ) {
   1758      1.1     lukem 	case LDAP_REQ_SEARCH:
   1759      1.1     lukem 	case LDAP_REQ_BIND:
   1760      1.1     lukem 	case LDAP_REQ_ADD:
   1761      1.1     lukem 	case LDAP_REQ_DELETE:
   1762      1.1     lukem 	case LDAP_REQ_MODRDN:
   1763      1.1     lukem 	case LDAP_REQ_MODIFY:
   1764      1.1     lukem 	case LDAP_REQ_COMPARE:
   1765      1.1     lukem 	case LDAP_REQ_EXTENDED:
   1766      1.1     lukem 		if ( rs->sr_ref ) {
   1767      1.1     lukem 			dncookie		dc;
   1768      1.1     lukem 
   1769      1.1     lukem 			/*
   1770      1.1     lukem 			 * Rewrite the dn of the referrals, if needed
   1771      1.1     lukem 			 */
   1772      1.1     lukem 			dc.rwmap = rwmap;
   1773      1.1     lukem 			dc.conn = op->o_conn;
   1774      1.1     lukem 			dc.rs = NULL;
   1775      1.1     lukem 			dc.ctx = "referralDN";
   1776      1.1     lukem 			rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
   1777  1.1.1.4      tron 			/* FIXME: impossible, so far */
   1778      1.1     lukem 			if ( rc != LDAP_SUCCESS ) {
   1779  1.1.1.4      tron 				rs->sr_err = rc;
   1780      1.1     lukem 				break;
   1781      1.1     lukem 			}
   1782      1.1     lukem 		}
   1783      1.1     lukem 
   1784  1.1.1.4      tron 		rwm_matched( op, rs );
   1785      1.1     lukem 		break;
   1786      1.1     lukem 	}
   1787      1.1     lukem 
   1788  1.1.1.4      tron 	return SLAP_CB_CONTINUE;
   1789      1.1     lukem }
   1790      1.1     lukem 
   1791      1.1     lukem static int
   1792      1.1     lukem rwm_db_config(
   1793      1.1     lukem 	BackendDB	*be,
   1794      1.1     lukem 	const char	*fname,
   1795      1.1     lukem 	int		lineno,
   1796      1.1     lukem 	int		argc,
   1797      1.1     lukem 	char		**argv )
   1798      1.1     lukem {
   1799      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   1800      1.1     lukem 	struct ldaprwmap	*rwmap =
   1801      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   1802      1.1     lukem 
   1803      1.1     lukem 	int		rc = 0;
   1804      1.1     lukem 	char		*argv0 = NULL;
   1805      1.1     lukem 
   1806      1.1     lukem 	if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
   1807      1.1     lukem 		argv0 = argv[ 0 ];
   1808      1.1     lukem 		argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
   1809      1.1     lukem 	}
   1810      1.1     lukem 
   1811      1.1     lukem 	if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
   1812      1.1     lukem 		rc = rwm_rw_config( be, fname, lineno, argc, argv );
   1813      1.1     lukem 
   1814      1.1     lukem 	} else if ( strcasecmp( argv[0], "map" ) == 0 ) {
   1815      1.1     lukem 		rc = rwm_m_config( be, fname, lineno, argc, argv );
   1816      1.1     lukem 
   1817      1.1     lukem 	} else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
   1818      1.1     lukem 		rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
   1819      1.1     lukem 
   1820      1.1     lukem 	} else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
   1821      1.1     lukem 		if ( argc != 2 ) {
   1822  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1823      1.1     lukem 		"%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
   1824  1.1.1.3      adam 					fname, lineno, 0 );
   1825      1.1     lukem 			return( 1 );
   1826      1.1     lukem 		}
   1827      1.1     lukem 
   1828      1.1     lukem 		if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
   1829      1.1     lukem 			rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
   1830      1.1     lukem 
   1831      1.1     lukem 		} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
   1832      1.1     lukem 			rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
   1833      1.1     lukem 
   1834      1.1     lukem 		/* TODO: not implemented yet */
   1835      1.1     lukem 		} else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
   1836  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1837      1.1     lukem 		"%s: line %d: \"discover\" not supported yet "
   1838      1.1     lukem 		"in \"t-f-support {no|yes|discover}\".\n",
   1839  1.1.1.3      adam 					fname, lineno, 0 );
   1840      1.1     lukem 			return( 1 );
   1841      1.1     lukem #if 0
   1842      1.1     lukem 			rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
   1843      1.1     lukem #endif
   1844      1.1     lukem 
   1845      1.1     lukem 		} else {
   1846  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1847      1.1     lukem 	"%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
   1848      1.1     lukem 				fname, lineno, argv[ 1 ] );
   1849      1.1     lukem 			return 1;
   1850      1.1     lukem 		}
   1851      1.1     lukem 
   1852      1.1     lukem 	} else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) ==  0 ) {
   1853      1.1     lukem 		if ( argc !=2 ) {
   1854  1.1.1.3      adam 			Debug( LDAP_DEBUG_ANY,
   1855      1.1     lukem 		"%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
   1856  1.1.1.3      adam 					fname, lineno, 0 );
   1857      1.1     lukem 			return( 1 );
   1858      1.1     lukem 		}
   1859      1.1     lukem 
   1860      1.1     lukem 		if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
   1861      1.1     lukem 			rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
   1862      1.1     lukem 
   1863      1.1     lukem 		} else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
   1864      1.1     lukem 			rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
   1865      1.1     lukem 		}
   1866      1.1     lukem 
   1867      1.1     lukem 	} else {
   1868      1.1     lukem 		rc = SLAP_CONF_UNKNOWN;
   1869      1.1     lukem 	}
   1870      1.1     lukem 
   1871      1.1     lukem 	if ( argv0 ) {
   1872      1.1     lukem 		argv[ 0 ] = argv0;
   1873      1.1     lukem 	}
   1874      1.1     lukem 
   1875      1.1     lukem 	return rc;
   1876      1.1     lukem }
   1877      1.1     lukem 
   1878      1.1     lukem /*
   1879      1.1     lukem  * dynamic configuration...
   1880      1.1     lukem  */
   1881      1.1     lukem 
   1882      1.1     lukem enum {
   1883      1.1     lukem 	/* rewrite */
   1884      1.1     lukem 	RWM_CF_REWRITE = 1,
   1885      1.1     lukem 
   1886      1.1     lukem 	/* map */
   1887      1.1     lukem 	RWM_CF_MAP,
   1888      1.1     lukem 	RWM_CF_T_F_SUPPORT,
   1889      1.1     lukem 	RWM_CF_NORMALIZE_MAPPED,
   1890  1.1.1.2     lukem 	RWM_CF_DROP_UNREQUESTED,
   1891      1.1     lukem 
   1892      1.1     lukem 	RWM_CF_LAST
   1893      1.1     lukem };
   1894      1.1     lukem 
   1895      1.1     lukem static slap_verbmasks t_f_mode[] = {
   1896  1.1.1.2     lukem 	{ BER_BVC( "true" ),		RWM_F_SUPPORT_T_F },
   1897      1.1     lukem 	{ BER_BVC( "yes" ),		RWM_F_SUPPORT_T_F },
   1898      1.1     lukem 	{ BER_BVC( "discover" ),	RWM_F_SUPPORT_T_F_DISCOVER },
   1899  1.1.1.2     lukem 	{ BER_BVC( "false" ),		RWM_F_NONE },
   1900      1.1     lukem 	{ BER_BVC( "no" ),		RWM_F_NONE },
   1901      1.1     lukem 	{ BER_BVNULL,			0 }
   1902      1.1     lukem };
   1903      1.1     lukem 
   1904      1.1     lukem static ConfigDriver rwm_cf_gen;
   1905      1.1     lukem 
   1906      1.1     lukem static ConfigTable rwmcfg[] = {
   1907      1.1     lukem 	{ "rwm-rewrite", "rewrite",
   1908      1.1     lukem 		2, 0, STRLENOF("rwm-rewrite"),
   1909  1.1.1.2     lukem 		ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
   1910      1.1     lukem 		"( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
   1911      1.1     lukem 			"DESC 'Rewrites strings' "
   1912      1.1     lukem 			"EQUALITY caseIgnoreMatch "
   1913      1.1     lukem 			"SYNTAX OMsDirectoryString "
   1914      1.1     lukem 			"X-ORDERED 'VALUES' )",
   1915      1.1     lukem 		NULL, NULL },
   1916      1.1     lukem 
   1917      1.1     lukem 	{ "rwm-suffixmassage", "[virtual]> <real",
   1918  1.1.1.2     lukem 		2, 3, 0, ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
   1919      1.1     lukem 		NULL, NULL, NULL },
   1920      1.1     lukem 
   1921      1.1     lukem 	{ "rwm-t-f-support", "true|false|discover",
   1922      1.1     lukem 		2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
   1923      1.1     lukem 		"( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
   1924      1.1     lukem 			"DESC 'Absolute filters support' "
   1925      1.1     lukem 			"SYNTAX OMsDirectoryString "
   1926      1.1     lukem 			"SINGLE-VALUE )",
   1927      1.1     lukem 		NULL, NULL },
   1928      1.1     lukem 
   1929      1.1     lukem 	{ "rwm-map", "{objectClass|attribute}",
   1930      1.1     lukem 		2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
   1931      1.1     lukem 		"( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
   1932      1.1     lukem 			"DESC 'maps attributes/objectClasses' "
   1933  1.1.1.3      adam 			"EQUALITY caseIgnoreMatch "
   1934      1.1     lukem 			"SYNTAX OMsDirectoryString "
   1935      1.1     lukem 			"X-ORDERED 'VALUES' )",
   1936      1.1     lukem 		NULL, NULL },
   1937      1.1     lukem 
   1938      1.1     lukem 	{ "rwm-normalize-mapped-attrs", "true|false",
   1939      1.1     lukem 		2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
   1940      1.1     lukem 		"( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
   1941      1.1     lukem 			"DESC 'Normalize mapped attributes/objectClasses' "
   1942      1.1     lukem 			"SYNTAX OMsBoolean "
   1943      1.1     lukem 			"SINGLE-VALUE )",
   1944      1.1     lukem 		NULL, NULL },
   1945      1.1     lukem 
   1946  1.1.1.2     lukem 	{ "rwm-drop-unrequested-attrs", "true|false",
   1947  1.1.1.2     lukem 		2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_DROP_UNREQUESTED, rwm_cf_gen,
   1948  1.1.1.2     lukem 		"( OLcfgOvAt:16.5 NAME 'olcRwmDropUnrequested' "
   1949  1.1.1.2     lukem 			"DESC 'Drop unrequested attributes' "
   1950  1.1.1.2     lukem 			"SYNTAX OMsBoolean "
   1951  1.1.1.2     lukem 			"SINGLE-VALUE )",
   1952  1.1.1.2     lukem 		NULL, NULL },
   1953  1.1.1.2     lukem 
   1954      1.1     lukem 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
   1955      1.1     lukem };
   1956      1.1     lukem 
   1957      1.1     lukem static ConfigOCs rwmocs[] = {
   1958      1.1     lukem 	{ "( OLcfgOvOc:16.1 "
   1959      1.1     lukem 		"NAME 'olcRwmConfig' "
   1960      1.1     lukem 		"DESC 'Rewrite/remap configuration' "
   1961      1.1     lukem 		"SUP olcOverlayConfig "
   1962      1.1     lukem 		"MAY ( "
   1963      1.1     lukem 			"olcRwmRewrite $ "
   1964      1.1     lukem 			"olcRwmTFSupport $ "
   1965      1.1     lukem 			"olcRwmMap $ "
   1966  1.1.1.5  christos 			"olcRwmNormalizeMapped $ "
   1967  1.1.1.5  christos 			"olcRwmDropUnrequested"
   1968      1.1     lukem 			") )",
   1969      1.1     lukem 		Cft_Overlay, rwmcfg, NULL, NULL },
   1970      1.1     lukem 	{ NULL, 0, NULL }
   1971      1.1     lukem };
   1972      1.1     lukem 
   1973      1.1     lukem static void
   1974  1.1.1.3      adam slap_bv_x_ordered_unparse( BerVarray in, BerVarray *out )
   1975      1.1     lukem {
   1976      1.1     lukem 	int		i;
   1977      1.1     lukem 	BerVarray	bva = NULL;
   1978      1.1     lukem 	char		ibuf[32], *ptr;
   1979      1.1     lukem 	struct berval	idx;
   1980      1.1     lukem 
   1981      1.1     lukem 	assert( in != NULL );
   1982      1.1     lukem 
   1983      1.1     lukem 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
   1984      1.1     lukem 		/* count'em */ ;
   1985      1.1     lukem 
   1986      1.1     lukem 	if ( i == 0 ) {
   1987      1.1     lukem 		return;
   1988      1.1     lukem 	}
   1989      1.1     lukem 
   1990      1.1     lukem 	idx.bv_val = ibuf;
   1991      1.1     lukem 
   1992      1.1     lukem 	bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
   1993      1.1     lukem 	BER_BVZERO( &bva[ 0 ] );
   1994      1.1     lukem 
   1995      1.1     lukem 	for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
   1996      1.1     lukem 		idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
   1997      1.1     lukem 		if ( idx.bv_len >= sizeof( ibuf ) ) {
   1998      1.1     lukem 			ber_bvarray_free( bva );
   1999      1.1     lukem 			return;
   2000      1.1     lukem 		}
   2001      1.1     lukem 
   2002      1.1     lukem 		bva[i].bv_len = idx.bv_len + in[i].bv_len;
   2003      1.1     lukem 		bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
   2004      1.1     lukem 		ptr = lutil_strcopy( bva[i].bv_val, ibuf );
   2005      1.1     lukem 		ptr = lutil_strcopy( ptr, in[i].bv_val );
   2006      1.1     lukem 		*ptr = '\0';
   2007      1.1     lukem 		BER_BVZERO( &bva[ i + 1 ] );
   2008      1.1     lukem 	}
   2009      1.1     lukem 
   2010      1.1     lukem 	*out = bva;
   2011      1.1     lukem }
   2012      1.1     lukem 
   2013      1.1     lukem static int
   2014  1.1.1.3      adam rwm_bva_add(
   2015  1.1.1.3      adam 	BerVarray		*bva,
   2016  1.1.1.2     lukem 	int			idx,
   2017  1.1.1.2     lukem 	char			**argv )
   2018  1.1.1.2     lukem {
   2019  1.1.1.2     lukem 	char		*line;
   2020  1.1.1.2     lukem 	struct berval	bv;
   2021  1.1.1.2     lukem 
   2022  1.1.1.2     lukem 	line = ldap_charray2str( argv, "\" \"" );
   2023  1.1.1.2     lukem 	if ( line != NULL ) {
   2024  1.1.1.2     lukem 		int	len = strlen( argv[ 0 ] );
   2025  1.1.1.2     lukem 
   2026  1.1.1.2     lukem 		ber_str2bv( line, 0, 0, &bv );
   2027  1.1.1.2     lukem 		AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
   2028  1.1.1.2     lukem 			bv.bv_len - ( len + 1 ) );
   2029  1.1.1.2     lukem 		bv.bv_val[ bv.bv_len - 1 ] = '"';
   2030  1.1.1.2     lukem 
   2031  1.1.1.2     lukem 		if ( idx == -1 ) {
   2032  1.1.1.3      adam 			ber_bvarray_add( bva, &bv );
   2033  1.1.1.2     lukem 
   2034  1.1.1.2     lukem 		} else {
   2035  1.1.1.3      adam 			(*bva)[ idx ] = bv;
   2036  1.1.1.2     lukem 		}
   2037  1.1.1.3      adam 
   2038  1.1.1.3      adam 		return 0;
   2039  1.1.1.2     lukem 	}
   2040  1.1.1.2     lukem 
   2041  1.1.1.3      adam 	return -1;
   2042  1.1.1.3      adam }
   2043  1.1.1.3      adam 
   2044  1.1.1.3      adam static int
   2045  1.1.1.3      adam rwm_bva_rewrite_add(
   2046  1.1.1.3      adam 	struct ldaprwmap	*rwmap,
   2047  1.1.1.3      adam 	int			idx,
   2048  1.1.1.3      adam 	char			**argv )
   2049  1.1.1.3      adam {
   2050  1.1.1.3      adam 	return rwm_bva_add( &rwmap->rwm_bva_rewrite, idx, argv );
   2051  1.1.1.3      adam }
   2052  1.1.1.3      adam 
   2053  1.1.1.4      tron #ifdef unused
   2054  1.1.1.3      adam static int
   2055  1.1.1.3      adam rwm_bva_map_add(
   2056  1.1.1.3      adam 	struct ldaprwmap	*rwmap,
   2057  1.1.1.3      adam 	int			idx,
   2058  1.1.1.3      adam 	char			**argv )
   2059  1.1.1.3      adam {
   2060  1.1.1.3      adam 	return rwm_bva_add( &rwmap->rwm_bva_map, idx, argv );
   2061  1.1.1.2     lukem }
   2062  1.1.1.4      tron #endif /* unused */
   2063  1.1.1.2     lukem 
   2064  1.1.1.2     lukem static int
   2065  1.1.1.2     lukem rwm_info_init( struct rewrite_info ** rwm_rw )
   2066  1.1.1.2     lukem {
   2067  1.1.1.2     lukem 	char			*rargv[ 3 ];
   2068  1.1.1.2     lukem 
   2069  1.1.1.2     lukem  	*rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
   2070  1.1.1.2     lukem 	if ( *rwm_rw == NULL ) {
   2071  1.1.1.2     lukem  		return -1;
   2072  1.1.1.2     lukem  	}
   2073  1.1.1.2     lukem 
   2074  1.1.1.2     lukem 	/* this rewriteContext by default must be null;
   2075  1.1.1.2     lukem 	 * rules can be added if required */
   2076  1.1.1.2     lukem 	rargv[ 0 ] = "rewriteContext";
   2077  1.1.1.2     lukem 	rargv[ 1 ] = "searchFilter";
   2078  1.1.1.2     lukem 	rargv[ 2 ] = NULL;
   2079  1.1.1.2     lukem 	rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
   2080  1.1.1.2     lukem 
   2081  1.1.1.2     lukem 	rargv[ 0 ] = "rewriteContext";
   2082  1.1.1.2     lukem 	rargv[ 1 ] = "default";
   2083  1.1.1.2     lukem 	rargv[ 2 ] = NULL;
   2084  1.1.1.2     lukem 	rewrite_parse( *rwm_rw, "<suffix massage>", 2, 2, rargv );
   2085  1.1.1.2     lukem 
   2086  1.1.1.2     lukem 	return 0;
   2087  1.1.1.2     lukem }
   2088  1.1.1.2     lukem 
   2089  1.1.1.2     lukem static int
   2090      1.1     lukem rwm_cf_gen( ConfigArgs *c )
   2091      1.1     lukem {
   2092      1.1     lukem 	slap_overinst		*on = (slap_overinst *)c->bi;
   2093      1.1     lukem 	struct ldaprwmap	*rwmap =
   2094      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   2095      1.1     lukem 
   2096      1.1     lukem 	BackendDB		db;
   2097      1.1     lukem 	char			*argv0;
   2098  1.1.1.2     lukem 	int			idx0 = 0;
   2099      1.1     lukem 	int			rc = 0;
   2100      1.1     lukem 
   2101      1.1     lukem 	db = *c->be;
   2102      1.1     lukem 	db.bd_info = c->bi;
   2103      1.1     lukem 
   2104      1.1     lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
   2105      1.1     lukem 		struct berval	bv = BER_BVNULL;
   2106      1.1     lukem 
   2107      1.1     lukem 		switch ( c->type ) {
   2108      1.1     lukem 		case RWM_CF_REWRITE:
   2109      1.1     lukem 			if ( rwmap->rwm_bva_rewrite == NULL ) {
   2110      1.1     lukem 				rc = 1;
   2111      1.1     lukem 
   2112      1.1     lukem 			} else {
   2113  1.1.1.3      adam 				slap_bv_x_ordered_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
   2114      1.1     lukem 				if ( !c->rvalue_vals ) {
   2115      1.1     lukem 					rc = 1;
   2116      1.1     lukem 				}
   2117      1.1     lukem 			}
   2118      1.1     lukem 			break;
   2119      1.1     lukem 
   2120      1.1     lukem 		case RWM_CF_T_F_SUPPORT:
   2121      1.1     lukem 			enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
   2122      1.1     lukem 			if ( BER_BVISNULL( &bv ) ) {
   2123      1.1     lukem 				/* there's something wrong... */
   2124      1.1     lukem 				assert( 0 );
   2125      1.1     lukem 				rc = 1;
   2126      1.1     lukem 
   2127      1.1     lukem 			} else {
   2128      1.1     lukem 				value_add_one( &c->rvalue_vals, &bv );
   2129      1.1     lukem 			}
   2130      1.1     lukem 			break;
   2131      1.1     lukem 
   2132      1.1     lukem 		case RWM_CF_MAP:
   2133      1.1     lukem 			if ( rwmap->rwm_bva_map == NULL ) {
   2134      1.1     lukem 				rc = 1;
   2135      1.1     lukem 
   2136      1.1     lukem 			} else {
   2137  1.1.1.3      adam 				slap_bv_x_ordered_unparse( rwmap->rwm_bva_map, &c->rvalue_vals );
   2138  1.1.1.3      adam 				if ( !c->rvalue_vals ) {
   2139  1.1.1.3      adam 					rc = 1;
   2140  1.1.1.3      adam 				}
   2141      1.1     lukem 			}
   2142      1.1     lukem 			break;
   2143      1.1     lukem 
   2144      1.1     lukem 		case RWM_CF_NORMALIZE_MAPPED:
   2145      1.1     lukem 			c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
   2146      1.1     lukem 			break;
   2147      1.1     lukem 
   2148  1.1.1.2     lukem 		case RWM_CF_DROP_UNREQUESTED:
   2149  1.1.1.2     lukem 			c->value_int = ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS );
   2150  1.1.1.2     lukem 			break;
   2151  1.1.1.2     lukem 
   2152      1.1     lukem 		default:
   2153      1.1     lukem 			assert( 0 );
   2154      1.1     lukem 			rc = 1;
   2155      1.1     lukem 		}
   2156      1.1     lukem 
   2157      1.1     lukem 		return rc;
   2158      1.1     lukem 
   2159      1.1     lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
   2160      1.1     lukem 		switch ( c->type ) {
   2161      1.1     lukem 		case RWM_CF_REWRITE:
   2162      1.1     lukem 			if ( c->valx >= 0 ) {
   2163  1.1.1.2     lukem 				int i;
   2164  1.1.1.2     lukem 
   2165  1.1.1.2     lukem 				for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
   2166  1.1.1.2     lukem 					/* count'em */ ;
   2167  1.1.1.2     lukem 
   2168  1.1.1.3      adam 				if ( c->valx >= i ) {
   2169  1.1.1.2     lukem 					rc = 1;
   2170  1.1.1.2     lukem 					break;
   2171  1.1.1.2     lukem 				}
   2172  1.1.1.2     lukem 
   2173  1.1.1.2     lukem 				ber_memfree( rwmap->rwm_bva_rewrite[ c->valx ].bv_val );
   2174  1.1.1.2     lukem 				for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i + 1 ] ); i++ )
   2175  1.1.1.2     lukem 				{
   2176  1.1.1.2     lukem 					rwmap->rwm_bva_rewrite[ i ] = rwmap->rwm_bva_rewrite[ i + 1 ];
   2177  1.1.1.2     lukem 				}
   2178  1.1.1.2     lukem 				BER_BVZERO( &rwmap->rwm_bva_rewrite[ i ] );
   2179  1.1.1.2     lukem 
   2180  1.1.1.2     lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   2181  1.1.1.2     lukem 				assert( rwmap->rwm_rw == NULL );
   2182  1.1.1.2     lukem 
   2183  1.1.1.2     lukem 				rc = rwm_info_init( &rwmap->rwm_rw );
   2184  1.1.1.2     lukem 
   2185  1.1.1.2     lukem 				for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
   2186  1.1.1.2     lukem 				{
   2187  1.1.1.3      adam 					ConfigArgs ca = { 0 };
   2188  1.1.1.3      adam 
   2189  1.1.1.2     lukem 					ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
   2190  1.1.1.2     lukem 					ca.argc = 0;
   2191  1.1.1.5  christos 					init_config_argv( &ca );
   2192  1.1.1.5  christos 					config_parse_ldif( &ca );
   2193  1.1.1.5  christos 
   2194  1.1.1.5  christos 					argv0 = ca.argv[ 0 ];
   2195  1.1.1.5  christos 					ca.argv[ 0 ] += STRLENOF( "rwm-" );
   2196  1.1.1.5  christos 
   2197  1.1.1.2     lukem 					if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
   2198  1.1.1.2     lukem 						rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2199  1.1.1.2     lukem 							ca.argc, ca.argv );
   2200  1.1.1.2     lukem 
   2201  1.1.1.2     lukem 					} else {
   2202  1.1.1.2     lukem 						rc = rwm_rw_config( &db, c->fname, c->lineno,
   2203  1.1.1.2     lukem 							ca.argc, ca.argv );
   2204  1.1.1.2     lukem 					}
   2205  1.1.1.2     lukem 
   2206  1.1.1.5  christos 					ca.argv[ 0 ] = argv0;
   2207  1.1.1.5  christos 
   2208  1.1.1.2     lukem 					ch_free( ca.tline );
   2209  1.1.1.3      adam 					ch_free( ca.argv );
   2210  1.1.1.2     lukem 
   2211  1.1.1.2     lukem 					assert( rc == 0 );
   2212  1.1.1.2     lukem 				}
   2213      1.1     lukem 
   2214      1.1     lukem 			} else if ( rwmap->rwm_rw != NULL ) {
   2215      1.1     lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   2216      1.1     lukem 				assert( rwmap->rwm_rw == NULL );
   2217      1.1     lukem 
   2218      1.1     lukem 				ber_bvarray_free( rwmap->rwm_bva_rewrite );
   2219      1.1     lukem 				rwmap->rwm_bva_rewrite = NULL;
   2220  1.1.1.2     lukem 
   2221  1.1.1.2     lukem 				rc = rwm_info_init( &rwmap->rwm_rw );
   2222      1.1     lukem 			}
   2223      1.1     lukem 			break;
   2224      1.1     lukem 
   2225      1.1     lukem 		case RWM_CF_T_F_SUPPORT:
   2226      1.1     lukem 			rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
   2227      1.1     lukem 			break;
   2228      1.1     lukem 
   2229      1.1     lukem 		case RWM_CF_MAP:
   2230      1.1     lukem 			if ( c->valx >= 0 ) {
   2231  1.1.1.3      adam 				struct ldapmap rwm_oc = rwmap->rwm_oc;
   2232  1.1.1.3      adam 				struct ldapmap rwm_at = rwmap->rwm_at;
   2233  1.1.1.3      adam 				char *argv[5];
   2234  1.1.1.3      adam 				int cnt = 0;
   2235  1.1.1.3      adam 
   2236  1.1.1.3      adam 				if ( rwmap->rwm_bva_map ) {
   2237  1.1.1.3      adam 					for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
   2238  1.1.1.3      adam 						/* count */ ;
   2239  1.1.1.3      adam 				}
   2240  1.1.1.3      adam 
   2241  1.1.1.3      adam 				if ( c->valx >= cnt ) {
   2242  1.1.1.3      adam 					rc = 1;
   2243  1.1.1.3      adam 					break;
   2244  1.1.1.3      adam 				}
   2245  1.1.1.3      adam 
   2246  1.1.1.3      adam 				memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
   2247  1.1.1.3      adam 				memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
   2248  1.1.1.3      adam 
   2249  1.1.1.3      adam 				/* re-parse all mappings except the one
   2250  1.1.1.3      adam 				 * that needs to be eliminated */
   2251  1.1.1.3      adam 				argv[0] = "map";
   2252  1.1.1.3      adam 				for ( cnt = 0; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
   2253  1.1.1.3      adam 					ConfigArgs ca = { 0 };
   2254  1.1.1.3      adam 
   2255  1.1.1.3      adam 					if ( cnt == c->valx ) {
   2256  1.1.1.3      adam 						continue;
   2257  1.1.1.3      adam 					}
   2258  1.1.1.3      adam 
   2259  1.1.1.3      adam 					ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
   2260  1.1.1.3      adam 					ca.argc = 0;
   2261  1.1.1.5  christos 					init_config_argv( &ca );
   2262  1.1.1.5  christos 					config_parse_ldif( &ca );
   2263  1.1.1.3      adam 
   2264  1.1.1.3      adam 					argv[1] = ca.argv[0];
   2265  1.1.1.3      adam 					argv[2] = ca.argv[1];
   2266  1.1.1.3      adam 					argv[3] = ca.argv[2];
   2267  1.1.1.3      adam 					argv[4] = ca.argv[3];
   2268  1.1.1.3      adam 
   2269  1.1.1.3      adam 					rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
   2270  1.1.1.3      adam 
   2271  1.1.1.3      adam 					ch_free( ca.tline );
   2272  1.1.1.3      adam 					ch_free( ca.argv );
   2273  1.1.1.3      adam 
   2274  1.1.1.3      adam 					/* in case of failure, restore
   2275  1.1.1.3      adam 					 * the existing mapping */
   2276  1.1.1.3      adam 					if ( rc ) {
   2277  1.1.1.3      adam 						avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2278  1.1.1.3      adam 						avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2279  1.1.1.3      adam 						avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2280  1.1.1.3      adam 						avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2281  1.1.1.3      adam 						rwmap->rwm_oc = rwm_oc;
   2282  1.1.1.3      adam 						rwmap->rwm_at = rwm_at;
   2283  1.1.1.3      adam 						break;
   2284  1.1.1.3      adam 					}
   2285  1.1.1.3      adam 				}
   2286  1.1.1.3      adam 
   2287  1.1.1.3      adam 				/* in case of success, destroy the old mapping
   2288  1.1.1.3      adam 				 * and eliminate the deleted one */
   2289  1.1.1.3      adam 				if ( rc == 0 ) {
   2290  1.1.1.3      adam 					avl_free( rwm_oc.remap, rwm_mapping_dst_free );
   2291  1.1.1.3      adam 					avl_free( rwm_oc.map, rwm_mapping_free );
   2292  1.1.1.3      adam 					avl_free( rwm_at.remap, rwm_mapping_dst_free );
   2293  1.1.1.3      adam 					avl_free( rwm_at.map, rwm_mapping_free );
   2294  1.1.1.3      adam 
   2295  1.1.1.3      adam 					ber_memfree( rwmap->rwm_bva_map[ c->valx ].bv_val );
   2296  1.1.1.3      adam 					for ( cnt = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
   2297  1.1.1.3      adam 						rwmap->rwm_bva_map[ cnt ] = rwmap->rwm_bva_map[ cnt + 1 ];
   2298  1.1.1.3      adam 					}
   2299  1.1.1.3      adam 				}
   2300      1.1     lukem 
   2301      1.1     lukem 			} else {
   2302      1.1     lukem 				avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2303      1.1     lukem 				avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2304      1.1     lukem 				avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2305      1.1     lukem 				avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2306      1.1     lukem 
   2307      1.1     lukem 				rwmap->rwm_oc.remap = NULL;
   2308      1.1     lukem 				rwmap->rwm_oc.map = NULL;
   2309      1.1     lukem 				rwmap->rwm_at.remap = NULL;
   2310      1.1     lukem 				rwmap->rwm_at.map = NULL;
   2311      1.1     lukem 
   2312      1.1     lukem 				ber_bvarray_free( rwmap->rwm_bva_map );
   2313      1.1     lukem 				rwmap->rwm_bva_map = NULL;
   2314      1.1     lukem 			}
   2315      1.1     lukem 			break;
   2316      1.1     lukem 
   2317      1.1     lukem 		case RWM_CF_NORMALIZE_MAPPED:
   2318      1.1     lukem 			rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
   2319      1.1     lukem 			break;
   2320      1.1     lukem 
   2321  1.1.1.2     lukem 		case RWM_CF_DROP_UNREQUESTED:
   2322  1.1.1.2     lukem 			rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
   2323  1.1.1.2     lukem 			break;
   2324  1.1.1.2     lukem 
   2325      1.1     lukem 		default:
   2326      1.1     lukem 			return 1;
   2327      1.1     lukem 		}
   2328      1.1     lukem 		return rc;
   2329      1.1     lukem 	}
   2330      1.1     lukem 
   2331  1.1.1.2     lukem 	if ( strncasecmp( c->argv[ 0 ], "olcRwm", STRLENOF( "olcRwm" ) ) == 0 ) {
   2332  1.1.1.2     lukem 		idx0 = 1;
   2333  1.1.1.2     lukem 	}
   2334  1.1.1.2     lukem 
   2335      1.1     lukem 	switch ( c->type ) {
   2336      1.1     lukem 	case RWM_CF_REWRITE:
   2337  1.1.1.2     lukem 		if ( c->valx >= 0 ) {
   2338  1.1.1.2     lukem 			struct rewrite_info *rwm_rw = rwmap->rwm_rw;
   2339  1.1.1.2     lukem 			int i, last;
   2340  1.1.1.2     lukem 
   2341  1.1.1.2     lukem 			for ( last = 0; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ last ] ); last++ )
   2342  1.1.1.2     lukem 				/* count'em */ ;
   2343  1.1.1.2     lukem 
   2344  1.1.1.2     lukem 			if ( c->valx > last ) {
   2345  1.1.1.2     lukem 				c->valx = last;
   2346  1.1.1.2     lukem 			}
   2347  1.1.1.2     lukem 
   2348  1.1.1.2     lukem 			rwmap->rwm_rw = NULL;
   2349  1.1.1.2     lukem 			rc = rwm_info_init( &rwmap->rwm_rw );
   2350  1.1.1.2     lukem 
   2351  1.1.1.2     lukem 			for ( i = 0; i < c->valx; i++ ) {
   2352  1.1.1.3      adam 				ConfigArgs ca = { 0 };
   2353  1.1.1.3      adam 
   2354  1.1.1.2     lukem 				ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
   2355  1.1.1.2     lukem 				ca.argc = 0;
   2356  1.1.1.5  christos 				init_config_argv( &ca );
   2357  1.1.1.5  christos 				config_parse_ldif( &ca );
   2358  1.1.1.2     lukem 
   2359  1.1.1.2     lukem 				argv0 = ca.argv[ 0 ];
   2360  1.1.1.2     lukem 				ca.argv[ 0 ] += STRLENOF( "rwm-" );
   2361  1.1.1.2     lukem 
   2362  1.1.1.2     lukem 				if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
   2363  1.1.1.2     lukem 					rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2364  1.1.1.2     lukem 						ca.argc, ca.argv );
   2365      1.1     lukem 
   2366  1.1.1.2     lukem 				} else {
   2367  1.1.1.2     lukem 					rc = rwm_rw_config( &db, c->fname, c->lineno,
   2368  1.1.1.2     lukem 						ca.argc, ca.argv );
   2369  1.1.1.2     lukem 				}
   2370      1.1     lukem 
   2371  1.1.1.2     lukem 				ca.argv[ 0 ] = argv0;
   2372      1.1     lukem 
   2373  1.1.1.2     lukem 				ch_free( ca.tline );
   2374  1.1.1.3      adam 				ch_free( ca.argv );
   2375  1.1.1.2     lukem 
   2376  1.1.1.2     lukem 				assert( rc == 0 );
   2377      1.1     lukem 			}
   2378      1.1     lukem 
   2379  1.1.1.2     lukem 			argv0 = c->argv[ idx0 ];
   2380  1.1.1.2     lukem 			if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
   2381  1.1.1.2     lukem 				return 1;
   2382  1.1.1.2     lukem 			}
   2383  1.1.1.2     lukem 			c->argv[ idx0 ] += STRLENOF( "rwm-" );
   2384  1.1.1.2     lukem 			if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
   2385  1.1.1.2     lukem 				rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2386  1.1.1.2     lukem 					c->argc - idx0, &c->argv[ idx0 ] );
   2387      1.1     lukem 
   2388  1.1.1.2     lukem 			} else {
   2389  1.1.1.2     lukem 				rc = rwm_rw_config( &db, c->fname, c->lineno,
   2390  1.1.1.2     lukem 					c->argc - idx0, &c->argv[ idx0 ] );
   2391  1.1.1.2     lukem 			}
   2392  1.1.1.2     lukem 			c->argv[ idx0 ] = argv0;
   2393  1.1.1.2     lukem 			if ( rc != 0 ) {
   2394  1.1.1.2     lukem 				rewrite_info_delete( &rwmap->rwm_rw );
   2395  1.1.1.2     lukem 				assert( rwmap->rwm_rw == NULL );
   2396      1.1     lukem 
   2397  1.1.1.2     lukem 				rwmap->rwm_rw = rwm_rw;
   2398  1.1.1.2     lukem 				return 1;
   2399  1.1.1.2     lukem 			}
   2400      1.1     lukem 
   2401  1.1.1.2     lukem 			for ( i = c->valx; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
   2402  1.1.1.2     lukem 			{
   2403  1.1.1.3      adam 				ConfigArgs ca = { 0 };
   2404  1.1.1.3      adam 
   2405  1.1.1.2     lukem 				ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
   2406  1.1.1.2     lukem 				ca.argc = 0;
   2407  1.1.1.5  christos 				init_config_argv( &ca );
   2408  1.1.1.5  christos 				config_parse_ldif( &ca );
   2409  1.1.1.2     lukem 
   2410  1.1.1.2     lukem 				argv0 = ca.argv[ 0 ];
   2411  1.1.1.2     lukem 				ca.argv[ 0 ] += STRLENOF( "rwm-" );
   2412  1.1.1.2     lukem 
   2413  1.1.1.2     lukem 				if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
   2414  1.1.1.2     lukem 					rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2415  1.1.1.2     lukem 						ca.argc, ca.argv );
   2416      1.1     lukem 
   2417  1.1.1.2     lukem 				} else {
   2418  1.1.1.2     lukem 					rc = rwm_rw_config( &db, c->fname, c->lineno,
   2419  1.1.1.2     lukem 						ca.argc, ca.argv );
   2420  1.1.1.2     lukem 				}
   2421  1.1.1.2     lukem 
   2422  1.1.1.2     lukem 				ca.argv[ 0 ] = argv0;
   2423  1.1.1.2     lukem 
   2424  1.1.1.2     lukem 				ch_free( ca.tline );
   2425  1.1.1.3      adam 				ch_free( ca.argv );
   2426  1.1.1.2     lukem 
   2427  1.1.1.2     lukem 				assert( rc == 0 );
   2428      1.1     lukem 			}
   2429  1.1.1.2     lukem 
   2430  1.1.1.2     lukem 			rwmap->rwm_bva_rewrite = ch_realloc( rwmap->rwm_bva_rewrite,
   2431  1.1.1.2     lukem 				( last + 2 )*sizeof( struct berval ) );
   2432  1.1.1.2     lukem 			BER_BVZERO( &rwmap->rwm_bva_rewrite[last+1] );
   2433  1.1.1.2     lukem 
   2434  1.1.1.2     lukem 			for ( i = last - 1; i >= c->valx; i-- )
   2435  1.1.1.2     lukem 			{
   2436  1.1.1.2     lukem 				rwmap->rwm_bva_rewrite[ i + 1 ] = rwmap->rwm_bva_rewrite[ i ];
   2437  1.1.1.2     lukem 			}
   2438  1.1.1.2     lukem 
   2439  1.1.1.2     lukem 			rwm_bva_rewrite_add( rwmap, c->valx, &c->argv[ idx0 ] );
   2440  1.1.1.2     lukem 
   2441  1.1.1.2     lukem 			rewrite_info_delete( &rwm_rw );
   2442  1.1.1.2     lukem 			assert( rwm_rw == NULL );
   2443  1.1.1.2     lukem 
   2444  1.1.1.2     lukem 			break;
   2445  1.1.1.2     lukem 		}
   2446  1.1.1.2     lukem 
   2447  1.1.1.2     lukem 		argv0 = c->argv[ idx0 ];
   2448  1.1.1.2     lukem 		if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
   2449  1.1.1.2     lukem 			return 1;
   2450  1.1.1.2     lukem 		}
   2451  1.1.1.2     lukem 		c->argv[ idx0 ] += STRLENOF( "rwm-" );
   2452  1.1.1.2     lukem 		if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
   2453  1.1.1.2     lukem 			rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
   2454  1.1.1.2     lukem 				c->argc - idx0, &c->argv[ idx0 ] );
   2455  1.1.1.2     lukem 
   2456  1.1.1.2     lukem 		} else {
   2457  1.1.1.2     lukem 			rc = rwm_rw_config( &db, c->fname, c->lineno,
   2458  1.1.1.2     lukem 				c->argc - idx0, &c->argv[ idx0 ] );
   2459  1.1.1.2     lukem 		}
   2460  1.1.1.2     lukem 		c->argv[ idx0 ] = argv0;
   2461  1.1.1.2     lukem 		if ( rc ) {
   2462  1.1.1.2     lukem 			return 1;
   2463  1.1.1.2     lukem 
   2464  1.1.1.2     lukem 		} else {
   2465  1.1.1.2     lukem 			rwm_bva_rewrite_add( rwmap, -1, &c->argv[ idx0 ] );
   2466      1.1     lukem 		}
   2467      1.1     lukem 		break;
   2468      1.1     lukem 
   2469      1.1     lukem 	case RWM_CF_T_F_SUPPORT:
   2470      1.1     lukem 		rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
   2471      1.1     lukem 		if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
   2472      1.1     lukem 			return 1;
   2473      1.1     lukem 		}
   2474      1.1     lukem 
   2475      1.1     lukem 		rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
   2476      1.1     lukem 		rwmap->rwm_flags |= t_f_mode[ rc ].mask;
   2477      1.1     lukem 		rc = 0;
   2478      1.1     lukem 		break;
   2479      1.1     lukem 
   2480      1.1     lukem 	case RWM_CF_MAP:
   2481  1.1.1.2     lukem 		if ( c->valx >= 0 ) {
   2482  1.1.1.3      adam 			struct ldapmap rwm_oc = rwmap->rwm_oc;
   2483  1.1.1.3      adam 			struct ldapmap rwm_at = rwmap->rwm_at;
   2484  1.1.1.3      adam 			char *argv[5];
   2485  1.1.1.3      adam 			int cnt = 0;
   2486  1.1.1.3      adam 
   2487  1.1.1.3      adam 			if ( rwmap->rwm_bva_map ) {
   2488  1.1.1.3      adam 				for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
   2489  1.1.1.3      adam 					/* count */ ;
   2490  1.1.1.3      adam 			}
   2491  1.1.1.3      adam 
   2492  1.1.1.3      adam 			if ( c->valx >= cnt ) {
   2493  1.1.1.3      adam 				c->valx = cnt;
   2494  1.1.1.3      adam 			}
   2495  1.1.1.3      adam 
   2496  1.1.1.3      adam 			memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
   2497  1.1.1.3      adam 			memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
   2498  1.1.1.3      adam 
   2499  1.1.1.3      adam 			/* re-parse all mappings, including the one
   2500  1.1.1.3      adam 			 * that needs to be added */
   2501  1.1.1.3      adam 			argv[0] = "map";
   2502  1.1.1.3      adam 			for ( cnt = 0; cnt < c->valx; cnt++ ) {
   2503  1.1.1.3      adam 				ConfigArgs ca = { 0 };
   2504  1.1.1.3      adam 
   2505  1.1.1.3      adam 				ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
   2506  1.1.1.3      adam 				ca.argc = 0;
   2507  1.1.1.5  christos 				init_config_argv( &ca );
   2508  1.1.1.5  christos 				config_parse_ldif( &ca );
   2509  1.1.1.3      adam 
   2510  1.1.1.3      adam 				argv[1] = ca.argv[0];
   2511  1.1.1.3      adam 				argv[2] = ca.argv[1];
   2512  1.1.1.3      adam 				argv[3] = ca.argv[2];
   2513  1.1.1.3      adam 				argv[4] = ca.argv[3];
   2514  1.1.1.3      adam 
   2515  1.1.1.3      adam 				rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
   2516  1.1.1.3      adam 
   2517  1.1.1.3      adam 				ch_free( ca.tline );
   2518  1.1.1.3      adam 				ch_free( ca.argv );
   2519  1.1.1.3      adam 
   2520  1.1.1.3      adam 				/* in case of failure, restore
   2521  1.1.1.3      adam 				 * the existing mapping */
   2522  1.1.1.3      adam 				if ( rc ) {
   2523  1.1.1.3      adam 					goto rwmmap_fail;
   2524  1.1.1.3      adam 				}
   2525  1.1.1.3      adam 			}
   2526  1.1.1.3      adam 
   2527  1.1.1.3      adam 			argv0 = c->argv[0];
   2528  1.1.1.3      adam 			c->argv[0] = "map";
   2529  1.1.1.3      adam 			rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
   2530  1.1.1.3      adam 			c->argv[0] = argv0;
   2531  1.1.1.3      adam 			if ( rc ) {
   2532  1.1.1.3      adam 				goto rwmmap_fail;
   2533  1.1.1.3      adam 			}
   2534  1.1.1.3      adam 
   2535  1.1.1.3      adam 			if ( rwmap->rwm_bva_map ) {
   2536  1.1.1.3      adam 				for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
   2537  1.1.1.3      adam 					ConfigArgs ca = { 0 };
   2538  1.1.1.3      adam 
   2539  1.1.1.3      adam 					ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
   2540  1.1.1.3      adam 					ca.argc = 0;
   2541  1.1.1.5  christos 					init_config_argv( &ca );
   2542  1.1.1.5  christos 					config_parse_ldif( &ca );
   2543  1.1.1.3      adam 
   2544  1.1.1.3      adam 					argv[1] = ca.argv[0];
   2545  1.1.1.3      adam 					argv[2] = ca.argv[1];
   2546  1.1.1.3      adam 					argv[3] = ca.argv[2];
   2547  1.1.1.3      adam 					argv[4] = ca.argv[3];
   2548  1.1.1.3      adam 
   2549  1.1.1.3      adam 					rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
   2550  1.1.1.3      adam 
   2551  1.1.1.3      adam 					ch_free( ca.tline );
   2552  1.1.1.3      adam 					ch_free( ca.argv );
   2553  1.1.1.3      adam 
   2554  1.1.1.3      adam 					/* in case of failure, restore
   2555  1.1.1.3      adam 					 * the existing mapping */
   2556  1.1.1.3      adam 					if ( rc ) {
   2557  1.1.1.3      adam 						goto rwmmap_fail;
   2558  1.1.1.3      adam 					}
   2559  1.1.1.3      adam 				}
   2560  1.1.1.3      adam 			}
   2561  1.1.1.3      adam 
   2562  1.1.1.3      adam 			/* in case of success, destroy the old mapping
   2563  1.1.1.3      adam 			 * and add the new one */
   2564  1.1.1.3      adam 			if ( rc == 0 ) {
   2565  1.1.1.3      adam 				BerVarray tmp;
   2566  1.1.1.3      adam 				struct berval bv, *bvp = &bv;
   2567  1.1.1.3      adam 
   2568  1.1.1.3      adam 				if ( rwm_bva_add( &bvp, 0, &c->argv[ idx0 ] ) ) {
   2569  1.1.1.3      adam 					rc = 1;
   2570  1.1.1.3      adam 					goto rwmmap_fail;
   2571  1.1.1.3      adam 				}
   2572  1.1.1.3      adam 
   2573  1.1.1.3      adam 				tmp = ber_memrealloc( rwmap->rwm_bva_map,
   2574  1.1.1.3      adam 					sizeof( struct berval )*( cnt + 2 ) );
   2575  1.1.1.3      adam 				if ( tmp == NULL ) {
   2576  1.1.1.3      adam 					ber_memfree( bv.bv_val );
   2577  1.1.1.3      adam 					rc = 1;
   2578  1.1.1.3      adam 					goto rwmmap_fail;
   2579  1.1.1.3      adam 				}
   2580  1.1.1.3      adam 				rwmap->rwm_bva_map = tmp;
   2581  1.1.1.3      adam 				BER_BVZERO( &rwmap->rwm_bva_map[ cnt + 1 ] );
   2582  1.1.1.3      adam 
   2583  1.1.1.3      adam 				avl_free( rwm_oc.remap, rwm_mapping_dst_free );
   2584  1.1.1.3      adam 				avl_free( rwm_oc.map, rwm_mapping_free );
   2585  1.1.1.3      adam 				avl_free( rwm_at.remap, rwm_mapping_dst_free );
   2586  1.1.1.3      adam 				avl_free( rwm_at.map, rwm_mapping_free );
   2587  1.1.1.3      adam 
   2588  1.1.1.3      adam 				for ( ; cnt-- > c->valx; ) {
   2589  1.1.1.3      adam 					rwmap->rwm_bva_map[ cnt + 1 ] = rwmap->rwm_bva_map[ cnt ];
   2590  1.1.1.3      adam 				}
   2591  1.1.1.3      adam 				rwmap->rwm_bva_map[ c->valx ] = bv;
   2592  1.1.1.3      adam 
   2593  1.1.1.3      adam 			} else {
   2594  1.1.1.3      adam rwmmap_fail:;
   2595  1.1.1.3      adam 				avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2596  1.1.1.3      adam 				avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2597  1.1.1.3      adam 				avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2598  1.1.1.3      adam 				avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2599  1.1.1.3      adam 				rwmap->rwm_oc = rwm_oc;
   2600  1.1.1.3      adam 				rwmap->rwm_at = rwm_at;
   2601  1.1.1.3      adam 			}
   2602  1.1.1.3      adam 
   2603  1.1.1.3      adam 			break;
   2604  1.1.1.2     lukem 		}
   2605  1.1.1.2     lukem 
   2606      1.1     lukem 		argv0 = c->argv[ 0 ];
   2607      1.1     lukem 		c->argv[ 0 ] += STRLENOF( "rwm-" );
   2608      1.1     lukem 		rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
   2609      1.1     lukem 		c->argv[ 0 ] = argv0;
   2610      1.1     lukem 		if ( rc ) {
   2611      1.1     lukem 			return 1;
   2612      1.1     lukem 
   2613      1.1     lukem 		} else {
   2614      1.1     lukem 			char		*line;
   2615      1.1     lukem 			struct berval	bv;
   2616      1.1     lukem 
   2617      1.1     lukem 			line = ldap_charray2str( &c->argv[ 1 ], " " );
   2618      1.1     lukem 			if ( line != NULL ) {
   2619      1.1     lukem 				ber_str2bv( line, 0, 0, &bv );
   2620      1.1     lukem 				ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
   2621      1.1     lukem 			}
   2622      1.1     lukem 		}
   2623      1.1     lukem 		break;
   2624      1.1     lukem 
   2625      1.1     lukem 	case RWM_CF_NORMALIZE_MAPPED:
   2626      1.1     lukem 		if ( c->value_int ) {
   2627      1.1     lukem 			rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
   2628      1.1     lukem 		} else {
   2629      1.1     lukem 			rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
   2630      1.1     lukem 		}
   2631      1.1     lukem 		break;
   2632      1.1     lukem 
   2633  1.1.1.2     lukem 	case RWM_CF_DROP_UNREQUESTED:
   2634  1.1.1.2     lukem 		if ( c->value_int ) {
   2635  1.1.1.2     lukem 			rwmap->rwm_flags |= RWM_F_DROP_UNREQUESTED_ATTRS;
   2636  1.1.1.2     lukem 		} else {
   2637  1.1.1.2     lukem 			rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
   2638  1.1.1.2     lukem 		}
   2639  1.1.1.2     lukem 		break;
   2640  1.1.1.2     lukem 
   2641      1.1     lukem 	default:
   2642      1.1     lukem 		assert( 0 );
   2643      1.1     lukem 		return 1;
   2644      1.1     lukem 	}
   2645      1.1     lukem 
   2646      1.1     lukem 	return rc;
   2647      1.1     lukem }
   2648      1.1     lukem 
   2649      1.1     lukem static int
   2650      1.1     lukem rwm_db_init(
   2651      1.1     lukem 	BackendDB	*be,
   2652      1.1     lukem 	ConfigReply	*cr )
   2653      1.1     lukem {
   2654      1.1     lukem 	slap_overinst		*on = (slap_overinst *) be->bd_info;
   2655      1.1     lukem 	struct ldaprwmap	*rwmap;
   2656      1.1     lukem 	int			rc = 0;
   2657      1.1     lukem 
   2658      1.1     lukem 	rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
   2659      1.1     lukem 
   2660  1.1.1.2     lukem 	/* default */
   2661  1.1.1.2     lukem 	rwmap->rwm_flags = RWM_F_DROP_UNREQUESTED_ATTRS;
   2662      1.1     lukem 
   2663  1.1.1.2     lukem 	rc = rwm_info_init( &rwmap->rwm_rw );
   2664      1.1     lukem 
   2665      1.1     lukem 	on->on_bi.bi_private = (void *)rwmap;
   2666      1.1     lukem 
   2667      1.1     lukem 	if ( rc ) {
   2668      1.1     lukem 		(void)rwm_db_destroy( be, NULL );
   2669      1.1     lukem 	}
   2670      1.1     lukem 
   2671      1.1     lukem 	return rc;
   2672      1.1     lukem }
   2673      1.1     lukem 
   2674      1.1     lukem static int
   2675      1.1     lukem rwm_db_destroy(
   2676      1.1     lukem 	BackendDB	*be,
   2677      1.1     lukem 	ConfigReply	*cr )
   2678      1.1     lukem {
   2679      1.1     lukem 	slap_overinst	*on = (slap_overinst *) be->bd_info;
   2680      1.1     lukem 	int		rc = 0;
   2681      1.1     lukem 
   2682      1.1     lukem 	if ( on->on_bi.bi_private ) {
   2683      1.1     lukem 		struct ldaprwmap	*rwmap =
   2684      1.1     lukem 			(struct ldaprwmap *)on->on_bi.bi_private;
   2685      1.1     lukem 
   2686      1.1     lukem 		if ( rwmap->rwm_rw ) {
   2687      1.1     lukem 			rewrite_info_delete( &rwmap->rwm_rw );
   2688  1.1.1.2     lukem 			if ( rwmap->rwm_bva_rewrite )
   2689  1.1.1.2     lukem 				ber_bvarray_free( rwmap->rwm_bva_rewrite );
   2690      1.1     lukem 		}
   2691      1.1     lukem 
   2692      1.1     lukem 		avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
   2693      1.1     lukem 		avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
   2694      1.1     lukem 		avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
   2695      1.1     lukem 		avl_free( rwmap->rwm_at.map, rwm_mapping_free );
   2696      1.1     lukem 		ber_bvarray_free( rwmap->rwm_bva_map );
   2697      1.1     lukem 
   2698      1.1     lukem 		ch_free( rwmap );
   2699      1.1     lukem 	}
   2700      1.1     lukem 
   2701      1.1     lukem 	return rc;
   2702      1.1     lukem }
   2703      1.1     lukem 
   2704      1.1     lukem static slap_overinst rwm = { { NULL } };
   2705      1.1     lukem 
   2706      1.1     lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
   2707      1.1     lukem static
   2708      1.1     lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
   2709      1.1     lukem int
   2710      1.1     lukem rwm_initialize( void )
   2711      1.1     lukem {
   2712      1.1     lukem 	int		rc;
   2713      1.1     lukem 
   2714      1.1     lukem 	/* Make sure we don't exceed the bits reserved for userland */
   2715      1.1     lukem 	config_check_userland( RWM_CF_LAST );
   2716      1.1     lukem 
   2717      1.1     lukem 	memset( &rwm, 0, sizeof( slap_overinst ) );
   2718      1.1     lukem 
   2719      1.1     lukem 	rwm.on_bi.bi_type = "rwm";
   2720      1.1     lukem 	rwm.on_bi.bi_flags =
   2721      1.1     lukem 		SLAPO_BFLAG_SINGLE |
   2722      1.1     lukem 		0;
   2723      1.1     lukem 
   2724      1.1     lukem 	rwm.on_bi.bi_db_init = rwm_db_init;
   2725      1.1     lukem 	rwm.on_bi.bi_db_config = rwm_db_config;
   2726      1.1     lukem 	rwm.on_bi.bi_db_destroy = rwm_db_destroy;
   2727      1.1     lukem 
   2728      1.1     lukem 	rwm.on_bi.bi_op_bind = rwm_op_bind;
   2729      1.1     lukem 	rwm.on_bi.bi_op_search = rwm_op_search;
   2730      1.1     lukem 	rwm.on_bi.bi_op_compare = rwm_op_compare;
   2731      1.1     lukem 	rwm.on_bi.bi_op_modify = rwm_op_modify;
   2732      1.1     lukem 	rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
   2733      1.1     lukem 	rwm.on_bi.bi_op_add = rwm_op_add;
   2734      1.1     lukem 	rwm.on_bi.bi_op_delete = rwm_op_delete;
   2735      1.1     lukem 	rwm.on_bi.bi_op_unbind = rwm_op_unbind;
   2736      1.1     lukem 	rwm.on_bi.bi_extended = rwm_extended;
   2737  1.1.1.2     lukem #if 1 /* TODO */
   2738  1.1.1.2     lukem 	rwm.on_bi.bi_entry_release_rw = rwm_entry_release_rw;
   2739  1.1.1.2     lukem 	rwm.on_bi.bi_entry_get_rw = rwm_entry_get_rw;
   2740  1.1.1.2     lukem #endif
   2741      1.1     lukem 
   2742      1.1     lukem 	rwm.on_bi.bi_operational = rwm_operational;
   2743      1.1     lukem 	rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
   2744      1.1     lukem 
   2745      1.1     lukem 	rwm.on_bi.bi_connection_init = rwm_conn_init;
   2746      1.1     lukem 	rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
   2747      1.1     lukem 
   2748      1.1     lukem 	rwm.on_response = rwm_response;
   2749      1.1     lukem 
   2750      1.1     lukem 	rwm.on_bi.bi_cf_ocs = rwmocs;
   2751      1.1     lukem 
   2752      1.1     lukem 	rc = config_register_schema( rwmcfg, rwmocs );
   2753      1.1     lukem 	if ( rc ) {
   2754      1.1     lukem 		return rc;
   2755      1.1     lukem 	}
   2756      1.1     lukem 
   2757      1.1     lukem 	return overlay_register( &rwm );
   2758      1.1     lukem }
   2759      1.1     lukem 
   2760      1.1     lukem #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
   2761      1.1     lukem int
   2762      1.1     lukem init_module( int argc, char *argv[] )
   2763      1.1     lukem {
   2764      1.1     lukem 	return rwm_initialize();
   2765      1.1     lukem }
   2766      1.1     lukem #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
   2767      1.1     lukem 
   2768      1.1     lukem #endif /* SLAPD_OVER_RWM */
   2769