1 /* rwm.c - rewrite/remap operations */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2006 The OpenLDAP Foundation.
6 * Portions Copyright 2003 Pierangelo Masarati.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
24 #include <ac/string.h>
29 typedef struct rwm_op_state {
38 rwm_db_destroy( BackendDB *be );
40 typedef struct rwm_op_cb {
45 static rwm_op_cb rwm_cb;
52 ber_memfree_x( data, NULL );
56 rwm_op_cleanup( Operation *op, SlapReply *rs )
58 slap_callback *cb = op->o_callback;
59 rwm_op_state *ros = cb->sc_private;
61 if ( rs->sr_type == REP_RESULT || op->o_abandon ||
62 rs->sr_err == SLAPD_ABANDON ) {
64 op->o_req_dn = ros->ro_dn;
65 op->o_req_ndn = ros->ro_ndn;
67 if ( !BER_BVISEMPTY( &ros->r_dn )) ch_free( ros->r_dn.bv_val );
68 if ( !BER_BVISEMPTY( &ros->r_ndn )) ch_free( ros->r_ndn.bv_val );
71 case LDAP_REQ_COMPARE:
76 if ( op->orr_newSup != ros->orr_newSup ) {
77 ch_free( op->orr_newSup->bv_val );
78 ch_free( op->orr_nnewSup->bv_val );
79 op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
80 op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
81 op->orr_newSup = ros->orr_newSup;
82 op->orr_nnewSup = ros->orr_nnewSup;
86 ch_free( op->ors_attrs );
87 filter_free_x( op, op->ors_filter );
88 ch_free( op->ors_filterstr.bv_val );
89 op->ors_attrs = ros->ors_attrs;
90 op->ors_filter = ros->ors_filter;
91 op->ors_filterstr = ros->ors_filterstr;
97 return SLAP_CB_CONTINUE;
101 rwm_callback_get( Operation *op, SlapReply *rs )
103 rwm_op_cb *roc = NULL;
105 if ( op->o_threadctx == NULL ) {
108 ldap_pvt_thread_pool_getkey( op->o_threadctx,
109 rwm_keyfree, (void *)&roc, NULL );
111 roc = ch_malloc( sizeof( struct rwm_op_cb ));
112 ldap_pvt_thread_pool_setkey( op->o_threadctx,
113 rwm_keyfree, roc, rwm_keyfree );
116 roc->cb.sc_cleanup = rwm_op_cleanup;
117 roc->cb.sc_response = NULL;
118 roc->cb.sc_next = op->o_callback;
119 roc->cb.sc_private = &roc->ros;
120 roc->ros.ro_dn = op->o_req_dn;
121 roc->ros.ro_ndn = op->o_req_ndn;
122 roc->ros.o_request = op->o_request;
123 BER_BVZERO( &roc->ros.r_dn );
124 BER_BVZERO( &roc->ros.r_ndn );
131 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
134 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
135 struct ldaprwmap *rwmap =
136 (struct ldaprwmap *)on->on_bi.bi_private;
138 struct berval dn = BER_BVNULL,
144 * Rewrite the dn if needed
147 #ifdef ENABLE_REWRITE
148 dc.conn = op->o_conn;
150 dc.ctx = (char *)cookie;
151 #else /* ! ENABLE_REWRITE */
152 dc.tofrom = ((int *)cookie)[0];
154 #endif /* ! ENABLE_REWRITE */
156 /* NOTE: in those cases where only the ndn is available,
157 * and the caller sets op->o_req_dn = op->o_req_ndn,
158 * only rewrite the op->o_req_ndn and use it as
159 * op->o_req_dn as well */
161 if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
163 rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
165 rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
168 if ( rc != LDAP_SUCCESS ) {
172 if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
173 || ndn.bv_val == op->o_req_ndn.bv_val )
178 if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
191 rwm_op_add( Operation *op, SlapReply *rs )
193 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
194 struct ldaprwmap *rwmap =
195 (struct ldaprwmap *)on->on_bi.bi_private;
199 Attribute **ap = NULL;
200 char *olddn = op->o_req_dn.bv_val;
203 rwm_op_cb *roc = rwm_callback_get( op, rs );
205 #ifdef ENABLE_REWRITE
206 rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
207 #else /* ! ENABLE_REWRITE */
209 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
210 #endif /* ! ENABLE_REWRITE */
211 if ( rc != LDAP_SUCCESS ) {
212 op->o_bd->bd_info = (BackendInfo *)on->on_info;
213 send_ldap_error( op, rs, rc, "addDN massage error" );
217 if ( olddn != op->o_req_dn.bv_val ) {
218 ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
219 ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
222 /* Count number of attributes in entry */
223 isupdate = be_shadow_update( op );
224 for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
227 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
228 (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
232 for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[ last ] ); last++ )
235 for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
236 struct ldapmapping *mapping = NULL;
238 ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
240 if ( mapping == NULL ) {
241 if ( rwmap->rwm_at.drop_missing ) {
242 /* FIXME: we allow to remove objectClasses as well;
243 * if the resulting entry is inconsistent, that's
244 * the relayed database's business...
246 ch_free( (*ap)->a_vals[ j ].bv_val );
248 (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
250 BER_BVZERO( &(*ap)->a_vals[ last ] );
256 ch_free( (*ap)->a_vals[ j ].bv_val );
257 ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
261 } else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
266 struct ldapmapping *mapping = NULL;
268 ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
270 if ( mapping == NULL ) {
271 if ( rwmap->rwm_at.drop_missing ) {
276 if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
277 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
280 * FIXME: rewrite could fail; in this case
281 * the operation should give up, right?
283 #ifdef ENABLE_REWRITE
284 rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
286 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
287 #else /* ! ENABLE_REWRITE */
289 rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals,
290 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
291 #endif /* ! ENABLE_REWRITE */
296 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
297 #ifdef ENABLE_REWRITE
298 rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
300 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
301 #else /* ! ENABLE_REWRITE */
303 rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals,
304 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
305 #endif /* ! ENABLE_REWRITE */
306 if ( rc != LDAP_SUCCESS ) {
311 if ( mapping != NULL ) {
312 assert( mapping->m_dst_ad != NULL );
313 (*ap)->a_desc = mapping->m_dst_ad;
322 /* FIXME: leaking attribute/values? */
329 op->o_callback = &roc->cb;
331 return SLAP_CB_CONTINUE;
334 #ifdef ENABLE_REWRITE
336 rwm_conn_init( BackendDB *be, Connection *conn )
338 slap_overinst *on = (slap_overinst *) be->bd_info;
339 struct ldaprwmap *rwmap =
340 (struct ldaprwmap *)on->on_bi.bi_private;
342 ( void )rewrite_session_init( rwmap->rwm_rw, conn );
344 return SLAP_CB_CONTINUE;
348 rwm_conn_destroy( BackendDB *be, Connection *conn )
350 slap_overinst *on = (slap_overinst *) be->bd_info;
351 struct ldaprwmap *rwmap =
352 (struct ldaprwmap *)on->on_bi.bi_private;
354 ( void )rewrite_session_delete( rwmap->rwm_rw, conn );
356 return SLAP_CB_CONTINUE;
358 #endif /* ENABLE_REWRITE */
361 rwm_op_bind( Operation *op, SlapReply *rs )
363 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
366 rwm_op_cb *roc = rwm_callback_get( op, rs );
368 #ifdef ENABLE_REWRITE
369 rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
370 #else /* ! ENABLE_REWRITE */
372 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
373 #endif /* ! ENABLE_REWRITE */
374 if ( rc != LDAP_SUCCESS ) {
375 op->o_bd->bd_info = (BackendInfo *)on->on_info;
376 send_ldap_error( op, rs, rc, "bindDN massage error" );
380 op->o_callback = &roc->cb;
382 return SLAP_CB_CONTINUE;
386 rwm_op_unbind( Operation *op, SlapReply *rs )
388 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
389 struct ldaprwmap *rwmap =
390 (struct ldaprwmap *)on->on_bi.bi_private;
392 #ifdef ENABLE_REWRITE
393 rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
394 #endif /* ENABLE_REWRITE */
396 return SLAP_CB_CONTINUE;
400 rwm_op_compare( Operation *op, SlapReply *rs )
402 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
403 struct ldaprwmap *rwmap =
404 (struct ldaprwmap *)on->on_bi.bi_private;
407 struct berval mapped_at = BER_BVNULL,
408 mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
410 rwm_op_cb *roc = rwm_callback_get( op, rs );
412 #ifdef ENABLE_REWRITE
413 rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
414 #else /* ! ENABLE_REWRITE */
416 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
417 #endif /* ! ENABLE_REWRITE */
418 if ( rc != LDAP_SUCCESS ) {
419 op->o_bd->bd_info = (BackendInfo *)on->on_info;
420 send_ldap_error( op, rs, rc, "compareDN massage error" );
424 /* if the attribute is an objectClass, try to remap its value */
425 if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
426 || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
428 rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
429 &mapped_vals[0], RWM_MAP );
430 if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
432 op->o_bd->bd_info = (BackendInfo *)on->on_info;
433 send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
436 } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
437 ber_bvreplace_x( &op->orc_ava->aa_value, &mapped_vals[0], op->o_tmpmemctx );
439 mapped_at = op->orc_ava->aa_desc->ad_cname;
442 struct ldapmapping *mapping = NULL;
443 AttributeDescription *ad = op->orc_ava->aa_desc;
445 ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
447 if ( mapping == NULL ) {
448 if ( rwmap->rwm_at.drop_missing ) {
449 op->o_bd->bd_info = (BackendInfo *)on->on_info;
450 send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
455 assert( mapping->m_dst_ad != NULL );
456 ad = mapping->m_dst_ad;
459 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
460 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
462 struct berval *mapped_valsp[2];
464 mapped_valsp[0] = &mapped_vals[0];
465 mapped_valsp[1] = &mapped_vals[1];
467 mapped_vals[0] = op->orc_ava->aa_value;
469 #ifdef ENABLE_REWRITE
470 rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
471 #else /* ! ENABLE_REWRITE */
473 rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );
474 #endif /* ! ENABLE_REWRITE */
476 if ( rc != LDAP_SUCCESS ) {
477 op->o_bd->bd_info = (BackendInfo *)on->on_info;
478 send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
482 if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
483 /* NOTE: if we get here, rwm_dnattr_rewrite()
484 * already freed the old value, so now
486 ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
488 ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
491 op->orc_ava->aa_desc = ad;
494 op->o_callback = &roc->cb;
496 return SLAP_CB_CONTINUE;
500 rwm_op_delete( Operation *op, SlapReply *rs )
502 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
505 rwm_op_cb *roc = rwm_callback_get( op, rs );
507 #ifdef ENABLE_REWRITE
508 rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
509 #else /* ! ENABLE_REWRITE */
511 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
512 #endif /* ! ENABLE_REWRITE */
513 if ( rc != LDAP_SUCCESS ) {
514 op->o_bd->bd_info = (BackendInfo *)on->on_info;
515 send_ldap_error( op, rs, rc, "deleteDN massage error" );
519 op->o_callback = &roc->cb;
521 return SLAP_CB_CONTINUE;
525 rwm_op_modify( Operation *op, SlapReply *rs )
527 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
528 struct ldaprwmap *rwmap =
529 (struct ldaprwmap *)on->on_bi.bi_private;
535 rwm_op_cb *roc = rwm_callback_get( op, rs );
537 #ifdef ENABLE_REWRITE
538 rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
539 #else /* ! ENABLE_REWRITE */
541 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
542 #endif /* ! ENABLE_REWRITE */
543 if ( rc != LDAP_SUCCESS ) {
544 op->o_bd->bd_info = (BackendInfo *)on->on_info;
545 send_ldap_error( op, rs, rc, "modifyDN massage error" );
549 isupdate = be_shadow_update( op );
550 for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) {
553 struct ldapmapping *mapping = NULL;
555 if ( (*mlp)->sml_desc == slap_schema.si_ad_objectClass
556 || (*mlp)->sml_desc == slap_schema.si_ad_structuralObjectClass )
560 } else if ( !isupdate && !get_relax( op ) && (*mlp)->sml_desc->ad_type->sat_no_user_mod )
567 drop_missing = rwm_mapping( &rwmap->rwm_at,
568 &(*mlp)->sml_desc->ad_cname,
570 if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
576 if ( (*mlp)->sml_values != NULL ) {
580 for ( last = 0; !BER_BVISNULL( &(*mlp)->sml_values[ last ] ); last++ )
584 for ( j = 0; !BER_BVISNULL( &(*mlp)->sml_values[ j ] ); j++ ) {
585 struct ldapmapping *oc_mapping = NULL;
587 ( void )rwm_mapping( &rwmap->rwm_oc, &(*mlp)->sml_values[ j ],
588 &oc_mapping, RWM_MAP );
589 if ( oc_mapping == NULL ) {
590 if ( rwmap->rwm_at.drop_missing ) {
591 /* FIXME: we allow to remove objectClasses as well;
592 * if the resulting entry is inconsistent, that's
593 * the relayed database's business...
595 ch_free( (*mlp)->sml_values[ j ].bv_val );
597 (*mlp)->sml_values[ j ] = (*mlp)->sml_values[ last ];
599 BER_BVZERO( &(*mlp)->sml_values[ last ] );
605 ch_free( (*mlp)->sml_values[ j ].bv_val );
606 ber_dupbv( &(*mlp)->sml_values[ j ], &oc_mapping->m_dst );
611 if ( (*mlp)->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
612 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
614 #ifdef ENABLE_REWRITE
615 rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
617 (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
618 #else /* ! ENABLE_REWRITE */
620 rc = rwm_dnattr_rewrite( op, rs, &rc,
622 (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
623 #endif /* ! ENABLE_REWRITE */
625 } else if ( (*mlp)->sml_desc == slap_schema.si_ad_ref ) {
626 #ifdef ENABLE_REWRITE
627 rc = rwm_referral_rewrite( op, rs,
630 (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
631 #else /* ! ENABLE_REWRITE */
633 rc = rwm_referral_rewrite( op, rs, &rc,
635 (*mlp)->sml_nvalues ? &(*mlp)->sml_nvalues : NULL );
636 #endif /* ! ENABLE_REWRITE */
637 if ( rc != LDAP_SUCCESS ) {
642 if ( rc != LDAP_SUCCESS ) {
649 if ( mapping != NULL ) {
650 /* use new attribute description */
651 assert( mapping->m_dst_ad != NULL );
652 (*mlp)->sml_desc = mapping->m_dst_ad;
655 mlp = &(*mlp)->sml_next;
660 *mlp = (*mlp)->sml_next;
661 slap_mod_free( &ml->sml_mod, 0 );
665 op->o_callback = &roc->cb;
667 return SLAP_CB_CONTINUE;
671 rwm_op_modrdn( Operation *op, SlapReply *rs )
673 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
674 struct ldaprwmap *rwmap =
675 (struct ldaprwmap *)on->on_bi.bi_private;
679 rwm_op_cb *roc = rwm_callback_get( op, rs );
681 if ( op->orr_newSup ) {
683 struct berval nnewSup = BER_BVNULL;
684 struct berval newSup = BER_BVNULL;
687 * Rewrite the new superior, if defined and required
690 #ifdef ENABLE_REWRITE
691 dc.conn = op->o_conn;
693 dc.ctx = "newSuperiorDN";
694 #else /* ! ENABLE_REWRITE */
697 #endif /* ! ENABLE_REWRITE */
698 newSup = *op->orr_newSup;
699 nnewSup = *op->orr_nnewSup;
700 rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
701 if ( rc != LDAP_SUCCESS ) {
702 op->o_bd->bd_info = (BackendInfo *)on->on_info;
703 send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
707 if ( op->orr_newSup->bv_val != newSup.bv_val ) {
708 op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
710 op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
712 *op->orr_newSup = newSup;
713 *op->orr_nnewSup = nnewSup;
718 * Rewrite the dn, if needed
720 #ifdef ENABLE_REWRITE
721 rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
722 #else /* ! ENABLE_REWRITE */
724 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
725 #endif /* ! ENABLE_REWRITE */
726 if ( rc != LDAP_SUCCESS ) {
727 op->o_bd->bd_info = (BackendInfo *)on->on_info;
728 send_ldap_error( op, rs, rc, "renameDN massage error" );
729 if ( op->orr_newSup != roc->ros.orr_newSup ) {
730 ch_free( op->orr_newSup->bv_val );
731 ch_free( op->orr_nnewSup->bv_val );
732 op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
733 op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
734 op->orr_newSup = roc->ros.orr_newSup;
735 op->orr_nnewSup = roc->ros.orr_nnewSup;
740 /* TODO: rewrite newRDN, attribute types,
741 * values of DN-valued attributes ... */
743 op->o_callback = &roc->cb;
745 return SLAP_CB_CONTINUE;
750 rwm_swap_attrs( Operation *op, SlapReply *rs )
752 slap_callback *cb = op->o_callback;
753 rwm_op_state *ros = cb->sc_private;
755 rs->sr_attrs = ros->ors_attrs;
757 return SLAP_CB_CONTINUE;
761 rwm_op_search( Operation *op, SlapReply *rs )
763 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
764 struct ldaprwmap *rwmap =
765 (struct ldaprwmap *)on->on_bi.bi_private;
770 struct berval fstr = BER_BVNULL;
773 AttributeName *an = NULL;
777 rwm_op_cb *roc = rwm_callback_get( op, rs );
779 #ifdef ENABLE_REWRITE
780 rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
781 "searchFilter", op->ors_filterstr.bv_val );
782 if ( rc == LDAP_SUCCESS )
783 rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
784 #else /* ! ENABLE_REWRITE */
786 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
787 #endif /* ! ENABLE_REWRITE */
788 if ( rc != LDAP_SUCCESS ) {
789 text = "searchDN massage error";
794 * Rewrite the dn if needed
797 #ifdef ENABLE_REWRITE
798 dc.conn = op->o_conn;
800 dc.ctx = "searchFilterAttrDN";
801 #else /* ! ENABLE_REWRITE */
804 #endif /* ! ENABLE_REWRITE */
806 rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
807 if ( rc != LDAP_SUCCESS ) {
808 text = "searchFilter/searchFilterAttrDN massage error";
812 f = str2filter_x( op, fstr.bv_val );
815 text = "massaged filter parse error";
820 op->ors_filterstr = fstr;
822 rc = rwm_map_attrnames( &rwmap->rwm_at, &rwmap->rwm_oc,
823 op->ors_attrs, &an, RWM_MAP );
824 if ( rc != LDAP_SUCCESS ) {
825 text = "attribute list mapping error";
830 roc->cb.sc_response = rwm_swap_attrs;
832 op->o_callback = &roc->cb;
834 return SLAP_CB_CONTINUE;
842 filter_free_x( op, f );
845 if ( !BER_BVISNULL( &fstr ) ) {
846 ch_free( fstr.bv_val );
849 op->oq_search = roc->ros.oq_search;
851 op->o_bd->bd_info = (BackendInfo *)on->on_info;
852 send_ldap_error( op, rs, rc, text );
859 rwm_exop_passwd( Operation *op, SlapReply *rs )
861 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
865 struct berval id = BER_BVNULL,
869 if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
873 if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
874 rs->sr_err = LDAP_OTHER;
878 rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
879 &pwold, &pwnew, &rs->sr_text );
880 if ( rs->sr_err != LDAP_SUCCESS ) {
884 if ( !BER_BVISNULL( &id ) ) {
885 rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
886 &op->o_req_ndn, op->o_tmpmemctx );
887 if ( rs->sr_err != LDAP_SUCCESS ) {
888 rs->sr_text = "Invalid DN";
893 ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
894 ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
897 roc = rwm_callback_get( op, rs );
899 #ifdef ENABLE_REWRITE
900 rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
901 #else /* ! ENABLE_REWRITE */
903 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
904 #endif /* ! ENABLE_REWRITE */
905 if ( rc != LDAP_SUCCESS ) {
906 op->o_bd->bd_info = (BackendInfo *)on->on_info;
907 send_ldap_error( op, rs, rc, "extendedDN massage error" );
911 /* TODO: re-encode the request with the massaged DN */
913 op->o_callback = &roc->cb;
915 return SLAP_CB_CONTINUE;
920 BI_op_extended *extended;
922 { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), rwm_exop_passwd },
927 rwm_extended( Operation *op, SlapReply *rs )
929 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
935 for ( i = 0; exop_table[i].extended != NULL; i++ ) {
936 if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
938 rc = exop_table[i].extended( op, rs );
943 case SLAP_CB_CONTINUE:
948 send_ldap_result( op, rs );
955 roc = rwm_callback_get( op, rs );
957 #ifdef ENABLE_REWRITE
958 rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
959 #else /* ! ENABLE_REWRITE */
961 rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );
962 #endif /* ! ENABLE_REWRITE */
963 if ( rc != LDAP_SUCCESS ) {
964 op->o_bd->bd_info = (BackendInfo *)on->on_info;
965 send_ldap_error( op, rs, rc, "extendedDN massage error" );
969 /* TODO: rewrite/map extended data ? ... */
970 op->o_callback = &roc->cb;
972 return SLAP_CB_CONTINUE;
976 rwm_matched( Operation *op, SlapReply *rs )
978 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
979 struct ldaprwmap *rwmap =
980 (struct ldaprwmap *)on->on_bi.bi_private;
982 struct berval dn, mdn;
986 if ( rs->sr_matched == NULL ) {
987 return SLAP_CB_CONTINUE;
991 #ifdef ENABLE_REWRITE
992 dc.conn = op->o_conn;
994 dc.ctx = "matchedDN";
995 #else /* ! ENABLE_REWRITE */
998 #endif /* ! ENABLE_REWRITE */
999 ber_str2bv( rs->sr_matched, 0, 0, &dn );
1001 rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
1002 if ( rc != LDAP_SUCCESS ) {
1004 rs->sr_text = "Rewrite error";
1008 if ( mdn.bv_val != dn.bv_val ) {
1009 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
1010 ch_free( (void *)rs->sr_matched );
1013 rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
1015 rs->sr_matched = mdn.bv_val;
1018 return SLAP_CB_CONTINUE;
1022 rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
1024 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1025 struct ldaprwmap *rwmap =
1026 (struct ldaprwmap *)on->on_bi.bi_private;
1034 * Rewrite the dn attrs, if needed
1037 #ifdef ENABLE_REWRITE
1038 dc.conn = op->o_conn;
1040 #else /* ! ENABLE_REWRITE */
1043 #endif /* ! ENABLE_REWRITE */
1045 /* FIXME: the entries are in the remote mapping form;
1046 * so we need to select those attributes we are willing
1047 * to return, and remap them accordingly */
1049 /* FIXME: in principle, one could map an attribute
1050 * on top of another, which already exists.
1051 * As such, in the end there might exist more than
1052 * one instance of an attribute.
1053 * We should at least check if this occurs, and issue
1054 * an error (because multiple instances of attrs in
1055 * response are not valid), or merge the values (what
1056 * about duplicate values?) */
1057 isupdate = be_shadow_update( op );
1058 for ( ap = a_first; *ap; ) {
1059 struct ldapmapping *mapping = NULL;
1064 if ( SLAP_OPATTRS( rs->sr_attr_flags ) && is_at_operational( (*ap)->a_desc->ad_type ) )
1069 if ( op->ors_attrs != NULL &&
1070 !SLAP_USERATTRS( rs->sr_attr_flags ) &&
1071 !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
1076 drop_missing = rwm_mapping( &rwmap->rwm_at,
1077 &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
1078 if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
1083 if ( mapping != NULL ) {
1084 (*ap)->a_desc = mapping->m_dst_ad;
1088 if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
1089 if ( stripEntryDN ) {
1090 /* will be generated by frontend */
1094 } else if ( !isupdate
1096 && (*ap)->a_desc->ad_type->sat_no_user_mod
1097 && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
1102 for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[last] ); last++ )
1106 /* empty? leave it in place because of attrsonly and vlv */
1111 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
1112 || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
1116 for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
1117 struct berval mapped;
1119 rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
1120 if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
1121 ch_free( bv[0].bv_val );
1122 BER_BVZERO( &bv[0] );
1123 if ( &(*ap)->a_vals[last] > &bv[0] ) {
1124 bv[0] = (*ap)->a_vals[last];
1125 BER_BVZERO( &(*ap)->a_vals[last] );
1130 } else if ( mapped.bv_val != bv[0].bv_val ) {
1132 * FIXME: after LBER_FREEing
1133 * the value is replaced by
1134 * ch_alloc'ed memory
1136 ber_bvreplace( &bv[0], &mapped );
1141 * It is necessary to try to rewrite attributes with
1142 * dn syntax because they might be used in ACLs as
1143 * members of groups; since ACLs are applied to the
1144 * rewritten stuff, no dn-based subject clause could
1145 * be used at the ldap backend side (see
1146 * http://www.OpenLDAP.org/faq/data/cache/452.html)
1147 * The problem can be overcome by moving the dn-based
1148 * ACLs to the target directory server, and letting
1149 * everything pass thru the ldap backend. */
1150 /* FIXME: handle distinguishedName-like syntaxes, like
1151 * nameAndOptionalUID */
1152 } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
1153 || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
1155 #ifdef ENABLE_REWRITE
1156 dc.ctx = "searchAttrDN";
1157 #endif /* ENABLE_REWRITE */
1158 rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals );
1159 if ( rc != LDAP_SUCCESS ) {
1163 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
1164 #ifdef ENABLE_REWRITE
1165 dc.ctx = "searchAttrDN";
1166 #endif /* ENABLE_REWRITE */
1167 rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
1168 if ( rc != LDAP_SUCCESS ) {
1173 if ( mapping != NULL ) {
1174 /* rewrite the attribute description */
1175 assert( mapping->m_dst_ad != NULL );
1176 (*ap)->a_desc = mapping->m_dst_ad;
1180 ap = &(*ap)->a_next;
1185 *ap = (*ap)->a_next;
1194 rwm_send_entry( Operation *op, SlapReply *rs )
1196 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1197 struct ldaprwmap *rwmap =
1198 (struct ldaprwmap *)on->on_bi.bi_private;
1202 struct berval dn = BER_BVNULL,
1207 assert( rs->sr_entry != NULL );
1210 * Rewrite the dn of the result, if needed
1213 #ifdef ENABLE_REWRITE
1214 dc.conn = op->o_conn;
1216 dc.ctx = "searchEntryDN";
1217 #else /* ! ENABLE_REWRITE */
1220 #endif /* ! ENABLE_REWRITE */
1223 flags = rs->sr_flags;
1224 if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
1225 /* FIXME: all we need to duplicate are:
1228 * - attributes that are requested
1229 * - no values if attrsonly is set
1234 rc = LDAP_NO_MEMORY;
1238 flags &= ~REP_ENTRY_MUSTRELEASE;
1239 flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
1243 * Note: this may fail if the target host(s) schema differs
1244 * from the one known to the meta, and a DN with unknown
1245 * attributes is returned.
1249 rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
1250 if ( rc != LDAP_SUCCESS ) {
1255 if ( e->e_name.bv_val != dn.bv_val ) {
1256 ch_free( e->e_name.bv_val );
1257 ch_free( e->e_nname.bv_val );
1263 /* TODO: map entry attribute types, objectclasses
1264 * and dn-valued attribute values */
1266 /* FIXME: the entries are in the remote mapping form;
1267 * so we need to select those attributes we are willing
1268 * to return, and remap them accordingly */
1269 (void)rwm_attrs( op, rs, &e->e_attrs, 1 );
1271 if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1272 be_entry_release_rw( op, rs->sr_entry, 0 );
1276 rs->sr_flags = flags;
1278 return SLAP_CB_CONTINUE;
1281 if ( e != NULL && e != rs->sr_entry ) {
1282 if ( e->e_name.bv_val == dn.bv_val ) {
1283 BER_BVZERO( &e->e_name );
1286 if ( e->e_nname.bv_val == ndn.bv_val ) {
1287 BER_BVZERO( &e->e_nname );
1293 if ( !BER_BVISNULL( &dn ) ) {
1294 ch_free( dn.bv_val );
1297 if ( !BER_BVISNULL( &ndn ) ) {
1298 ch_free( ndn.bv_val );
1305 rwm_operational( Operation *op, SlapReply *rs )
1307 /* FIXME: the entries are in the remote mapping form;
1308 * so we need to select those attributes we are willing
1309 * to return, and remap them accordingly */
1310 if ( rs->sr_operational_attrs ) {
1311 rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
1314 return SLAP_CB_CONTINUE;
1318 /* don't use this; it cannot be reverted, and leaves op->o_req_dn
1319 * rewritten for subsequent operations; fine for plain suffixmassage,
1320 * but destroys everything else */
1322 rwm_chk_referrals( Operation *op, SlapReply *rs )
1324 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1327 #ifdef ENABLE_REWRITE
1328 rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
1329 #else /* ! ENABLE_REWRITE */
1331 rc = rwm_op_dn_massage( op, rs, &rc );
1332 #endif /* ! ENABLE_REWRITE */
1333 if ( rc != LDAP_SUCCESS ) {
1334 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1335 send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
1339 return SLAP_CB_CONTINUE;
1351 #ifdef ENABLE_REWRITE
1352 slap_overinst *on = (slap_overinst *) be->bd_info;
1353 struct ldaprwmap *rwmap =
1354 (struct ldaprwmap *)on->on_bi.bi_private;
1356 return rewrite_parse( rwmap->rwm_rw,
1357 fname, lineno, argc, argv );
1359 #else /* !ENABLE_REWRITE */
1360 fprintf( stderr, "%s: line %d: rewrite capabilities "
1361 "are not enabled\n", fname, lineno );
1362 #endif /* !ENABLE_REWRITE */
1368 rwm_suffixmassage_config(
1375 slap_overinst *on = (slap_overinst *) be->bd_info;
1376 struct ldaprwmap *rwmap =
1377 (struct ldaprwmap *)on->on_bi.bi_private;
1379 struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
1381 #ifdef ENABLE_REWRITE
1383 #endif /* ENABLE_REWRITE */
1388 * suffixmassage [<suffix>] <massaged suffix>
1390 * the [<suffix>] field must be defined as a valid suffix
1391 * for the current database;
1392 * the <massaged suffix> shouldn't have already been
1393 * defined as a valid suffix for the current server
1396 if ( be->be_suffix == NULL ) {
1397 fprintf( stderr, "%s: line %d: "
1398 " \"suffixMassage [<suffix>]"
1399 " <massaged suffix>\" without "
1400 "<suffix> part requires database "
1401 "suffix be defined first.\n",
1405 bvnc = be->be_suffix[ 0 ];
1408 } else if ( argc == 3 ) {
1409 ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
1413 fprintf( stderr, "%s: line %d: syntax is"
1414 " \"suffixMassage [<suffix>]"
1415 " <massaged suffix>\"\n",
1420 if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1421 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
1422 fname, lineno, bvnc.bv_val );
1426 ber_str2bv( argv[ massaged ], 0, 0, &brnc );
1427 if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1428 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
1429 fname, lineno, brnc.bv_val );
1430 free( nvnc.bv_val );
1431 free( pvnc.bv_val );
1435 #ifdef ENABLE_REWRITE
1437 * The suffix massaging is emulated
1438 * by means of the rewrite capabilities
1440 rc = rwm_suffix_massage_config( rwmap->rwm_rw,
1441 &pvnc, &nvnc, &prnc, &nrnc );
1442 free( nvnc.bv_val );
1443 free( pvnc.bv_val );
1444 free( nrnc.bv_val );
1445 free( prnc.bv_val );
1449 #else /* !ENABLE_REWRITE */
1450 ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
1451 ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
1453 ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
1454 ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
1455 #endif /* !ENABLE_REWRITE */
1468 slap_overinst *on = (slap_overinst *) be->bd_info;
1469 struct ldaprwmap *rwmap =
1470 (struct ldaprwmap *)on->on_bi.bi_private;
1472 /* objectclass/attribute mapping */
1473 return rwm_map_config( &rwmap->rwm_oc,
1475 fname, lineno, argc, argv );
1479 rwm_response( Operation *op, SlapReply *rs )
1481 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1482 struct ldaprwmap *rwmap =
1483 (struct ldaprwmap *)on->on_bi.bi_private;
1487 if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
1488 return rwm_send_entry( op, rs );
1491 switch( op->o_tag ) {
1492 case LDAP_REQ_SEARCH:
1493 /* Note: the operation attrs are remapped */
1494 if ( rs->sr_type == REP_RESULT
1495 && op->ors_attrs != NULL
1496 && op->ors_attrs != rs->sr_attrs )
1498 ch_free( op->ors_attrs );
1499 op->ors_attrs = rs->sr_attrs;
1505 case LDAP_REQ_DELETE:
1506 case LDAP_REQ_MODRDN:
1507 case LDAP_REQ_MODIFY:
1508 case LDAP_REQ_COMPARE:
1509 case LDAP_REQ_EXTENDED:
1514 * Rewrite the dn of the referrals, if needed
1517 #ifdef ENABLE_REWRITE
1518 dc.conn = op->o_conn;
1520 dc.ctx = "referralDN";
1521 #else /* ! ENABLE_REWRITE */
1524 #endif /* ! ENABLE_REWRITE */
1525 rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
1526 if ( rc != LDAP_SUCCESS ) {
1531 rc = rwm_matched( op, rs );
1535 rc = SLAP_CB_CONTINUE;
1550 slap_overinst *on = (slap_overinst *) be->bd_info;
1551 struct ldaprwmap *rwmap =
1552 (struct ldaprwmap *)on->on_bi.bi_private;
1557 if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
1559 argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
1562 if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
1563 rc = rwm_rw_config( be, fname, lineno, argc, argv );
1565 } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
1566 rc = rwm_m_config( be, fname, lineno, argc, argv );
1568 } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
1569 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
1571 } else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
1574 "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
1579 if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1580 rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F|RWM_F_SUPPORT_T_F_DISCOVER);
1582 } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1583 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
1585 /* TODO: not implemented yet */
1586 } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
1588 "%s: line %d: \"discover\" not supported yet "
1589 "in \"t-f-support {no|yes|discover}\".\n",
1593 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
1598 "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
1599 fname, lineno, argv[ 1 ] );
1604 rc = SLAP_CONF_UNKNOWN;
1618 slap_overinst *on = (slap_overinst *) be->bd_info;
1619 struct ldapmapping *mapping = NULL;
1620 struct ldaprwmap *rwmap;
1621 #ifdef ENABLE_REWRITE
1623 #endif /* ENABLE_REWRITE */
1626 rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
1628 #ifdef ENABLE_REWRITE
1629 rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
1630 if ( rwmap->rwm_rw == NULL ) {
1635 /* this rewriteContext by default must be null;
1636 * rules can be added if required */
1637 rargv[ 0 ] = "rewriteContext";
1638 rargv[ 1 ] = "searchFilter";
1640 rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 1, 2, rargv );
1642 rargv[ 0 ] = "rewriteContext";
1643 rargv[ 1 ] = "default";
1645 rewrite_parse( rwmap->rwm_rw, "<suffix massage>", 2, 2, rargv );
1646 #endif /* ENABLE_REWRITE */
1648 if ( rwm_map_init( &rwmap->rwm_oc, &mapping ) != LDAP_SUCCESS ||
1649 rwm_map_init( &rwmap->rwm_at, &mapping ) != LDAP_SUCCESS )
1656 on->on_bi.bi_private = (void *)rwmap;
1659 (void)rwm_db_destroy( be );
1669 slap_overinst *on = (slap_overinst *) be->bd_info;
1672 if ( on->on_bi.bi_private ) {
1673 struct ldaprwmap *rwmap =
1674 (struct ldaprwmap *)on->on_bi.bi_private;
1676 #ifdef ENABLE_REWRITE
1677 if ( rwmap->rwm_rw ) {
1678 rewrite_info_delete( &rwmap->rwm_rw );
1680 #else /* !ENABLE_REWRITE */
1681 if ( rwmap->rwm_suffix_massage ) {
1682 ber_bvarray_free( rwmap->rwm_suffix_massage );
1684 #endif /* !ENABLE_REWRITE */
1686 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
1687 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
1688 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
1689 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
1697 static slap_overinst rwm = { { NULL } };
1699 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
1701 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
1703 rwm_initialize( void )
1705 memset( &rwm, 0, sizeof( slap_overinst ) );
1707 rwm.on_bi.bi_type = "rwm";
1708 rwm.on_bi.bi_flags =
1709 SLAPO_BFLAG_SINGLE |
1712 rwm.on_bi.bi_db_init = rwm_db_init;
1713 rwm.on_bi.bi_db_config = rwm_db_config;
1714 rwm.on_bi.bi_db_destroy = rwm_db_destroy;
1716 rwm.on_bi.bi_op_bind = rwm_op_bind;
1717 rwm.on_bi.bi_op_search = rwm_op_search;
1718 rwm.on_bi.bi_op_compare = rwm_op_compare;
1719 rwm.on_bi.bi_op_modify = rwm_op_modify;
1720 rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
1721 rwm.on_bi.bi_op_add = rwm_op_add;
1722 rwm.on_bi.bi_op_delete = rwm_op_delete;
1723 rwm.on_bi.bi_op_unbind = rwm_op_unbind;
1724 rwm.on_bi.bi_extended = rwm_extended;
1726 rwm.on_bi.bi_operational = rwm_operational;
1727 rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
1729 #ifdef ENABLE_REWRITE
1730 rwm.on_bi.bi_connection_init = rwm_conn_init;
1731 rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
1732 #endif /* ENABLE_REWRITE */
1734 rwm.on_response = rwm_response;
1736 return overlay_register( &rwm );
1739 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
1741 init_module( int argc, char *argv[] )
1743 return rwm_initialize();
1745 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
1747 #endif /* SLAPD_OVER_RWM */